diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/db-image-parser.h | 16 | ||||
-rw-r--r-- | src/itdb_artwork.c | 102 | ||||
-rw-r--r-- | src/itdb_device.c | 5 | ||||
-rw-r--r-- | src/itdb_device.h | 4 | ||||
-rw-r--r-- | src/ithumb-writer.c | 111 |
5 files changed, 180 insertions, 58 deletions
diff --git a/src/db-image-parser.h b/src/db-image-parser.h index 79f538e..bd06434 100644 --- a/src/db-image-parser.h +++ b/src/db-image-parser.h @@ -61,6 +61,22 @@ #define BLUE_SHIFT_555 0 #define BLUE_MASK_555 (((1 << BLUE_BITS_555)-1) << BLUE_SHIFT_555) +#define ALPHA_BITS_888 8 +#define ALPHA_SHIFT_888 24 +#define ALPHA_MASK_888 (((1 << ALPHA_BITS_888)-1) << ALPHA_SHIFT_888) + +#define RED_BITS_888 8 +#define RED_SHIFT_888 16 +#define RED_MASK_888 (((1 << RED_BITS_888)-1) << RED_SHIFT_888) + +#define GREEN_BITS_888 8 +#define GREEN_SHIFT_888 8 +#define GREEN_MASK_888 (((1 << GREEN_BITS_888)-1) << GREEN_SHIFT_888) + +#define BLUE_BITS_888 8 +#define BLUE_SHIFT_888 0 +#define BLUE_MASK_888 (((1 << BLUE_BITS_888)-1) << BLUE_SHIFT_888) + G_GNUC_INTERNAL Itdb_Thumb *ipod_image_new_from_mhni (MhniHeader *mhni, Itdb_DB *db); diff --git a/src/itdb_artwork.c b/src/itdb_artwork.c index d176fe9..d2cd5f6 100644 --- a/src/itdb_artwork.c +++ b/src/itdb_artwork.c @@ -1,4 +1,4 @@ -/* Time-stamp: <2007-09-09 00:12:28 jcs> +/* Time-stamp: <2007-10-27 21:54:23 jcs> | | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. @@ -483,6 +483,36 @@ unpack_RGB_555 (guint16 *pixels, guint bytes_len, guint byte_order) return result; } +static guchar * +unpack_RGB_888 (guint16 *pixels, guint bytes_len, guint byte_order) +{ + guchar *result; + guint i; + guint32 *pixels32; + + result = g_malloc ((bytes_len/4) * 3); + + pixels32 = (guint32 *)pixels; + + for (i = 0; i < bytes_len/4; i++) { + guint32 cur_pixel; + /* FIXME: endianness */ + cur_pixel = get_gint32 (pixels32[i], byte_order); + /* Unpack pixels */ + result[3*i] = (cur_pixel & RED_MASK_888) >> RED_SHIFT_888; + result[3*i+1] = (cur_pixel & GREEN_MASK_888) >> GREEN_SHIFT_888; + result[3*i+2] = (cur_pixel & BLUE_MASK_888) >> BLUE_SHIFT_888; + + /* Normalize color values so that they use a [0..255] range */ + /* (not necessary for 888 encoding) */ +/* result[3*i] <<= (8 - RED_BITS_888); */ +/* result[3*i+1] <<= (8 - GREEN_BITS_888); */ +/* result[3*i+2] <<= (8 - BLUE_BITS_888); */ + } + + return result; +} + static guint16 *rearrange_pixels (guint16 *pixels_s, guint16 *pixels_d, gint width, gint height, gint row_stride) @@ -589,57 +619,30 @@ unpack_experimental (guint16 *pixels, guint bytes_len, guint byte_order, gint width, gint height) { guchar *result; - guint16 *use_pixels; - gboolean free_use_pixels = FALSE; - guint16 *pixels_arranged = NULL; - guint i; + guint32 *rpixels; - g_return_val_if_fail (bytes_len < 2*(G_MAXUINT/3), NULL); - g_return_val_if_fail (2*width*height < G_MAXUINT, NULL); - g_return_val_if_fail (width==height, NULL); + g_return_val_if_fail (bytes_len < (G_MAXUINT/3), NULL); - if (2*width*height > bytes_len) - { - use_pixels = g_malloc0 (2*width*height); - g_memmove (use_pixels, pixels, bytes_len); - free_use_pixels = TRUE; - } - else - { - use_pixels = pixels; - } + result = g_malloc ((bytes_len/4) * 3); -/* pixels_arranged = rearrange_pixels (use_pixels, NULL, - width, height, width); + rpixels = (guint32 *)pixels; - if (pixels_arranged == NULL) - { - return NULL; - } -*/ - - result = g_malloc ((bytes_len/2) * 3); - - for (i = 0; i < bytes_len/2; i++) { - guint16 cur_pixel; + for (i = 0; i < bytes_len/4; i++) { + guint32 cur_pixel; /* FIXME: endianness */ - cur_pixel = get_gint16 (pixels[i], byte_order); + cur_pixel = get_gint32 (rpixels[i], byte_order); +printf ("%8x\n", cur_pixel); /* Unpack pixels */ - result[3*i] = (cur_pixel & RED_MASK_555) >> RED_SHIFT_555; - result[3*i+1] = (cur_pixel & GREEN_MASK_555) >> GREEN_SHIFT_555; - result[3*i+2] = (cur_pixel & BLUE_MASK_555) >> BLUE_SHIFT_555; + result[3*i] = (cur_pixel & RED_MASK_888) >> RED_SHIFT_888; + result[3*i+1] = (cur_pixel & GREEN_MASK_888) >> GREEN_SHIFT_888; + result[3*i+2] = (cur_pixel & BLUE_MASK_888) >> BLUE_SHIFT_888; /* Normalize color values so that they use a [0..255] range */ - result[3*i] <<= (8 - RED_BITS_555); - result[3*i+1] <<= (8 - GREEN_BITS_555); - result[3*i+2] <<= (8 - BLUE_BITS_555); - } - - g_free (pixels_arranged); - if (free_use_pixels) - { - g_free (use_pixels); + /* (not really necessary for 888 encoding) */ +/* result[3*i] <<= (8 - RED_BITS_888); */ +/* result[3*i+1] <<= (8 - GREEN_BITS_888); */ +/* result[3*i+2] <<= (8 - BLUE_BITS_888); */ } return result; @@ -842,6 +845,15 @@ itdb_thumb_get_rgb_data (Itdb_Device *device, Itdb_Thumb *thumb) pixels = unpack_RGB_555 (pixels_raw, thumb->size, itdb_thumb_get_byteorder (img_info->format)); break; + case THUMB_FORMAT_RGB888_LE_90: + case THUMB_FORMAT_RGB888_BE_90: + /* FIXME: actually the previous two might require + different treatment */ + case THUMB_FORMAT_RGB888_LE: + case THUMB_FORMAT_RGB888_BE: + pixels = unpack_RGB_888 (pixels_raw, thumb->size, + itdb_thumb_get_byteorder (img_info->format)); + break; case THUMB_FORMAT_REC_RGB555_LE_90: case THUMB_FORMAT_REC_RGB555_BE_90: /* FIXME: actually the previous two might require @@ -1158,6 +1170,8 @@ itdb_thumb_get_byteorder (const ItdbThumbFormat format) case THUMB_FORMAT_RGB565_LE_90: case THUMB_FORMAT_RGB555_LE: case THUMB_FORMAT_RGB555_LE_90: + case THUMB_FORMAT_RGB888_LE: + case THUMB_FORMAT_RGB888_LE_90: case THUMB_FORMAT_REC_RGB555_LE: case THUMB_FORMAT_REC_RGB555_LE_90: case THUMB_FORMAT_EXPERIMENTAL_LE: @@ -1167,6 +1181,8 @@ itdb_thumb_get_byteorder (const ItdbThumbFormat format) case THUMB_FORMAT_RGB565_BE_90: case THUMB_FORMAT_RGB555_BE: case THUMB_FORMAT_RGB555_BE_90: + case THUMB_FORMAT_RGB888_BE: + case THUMB_FORMAT_RGB888_BE_90: case THUMB_FORMAT_REC_RGB555_BE: case THUMB_FORMAT_REC_RGB555_BE_90: case THUMB_FORMAT_EXPERIMENTAL_BE: diff --git a/src/itdb_device.c b/src/itdb_device.c index d6ace10..13d6d11 100644 --- a/src/itdb_device.c +++ b/src/itdb_device.c @@ -314,9 +314,10 @@ static const Itdb_ArtworkFormat ipod_classic_1_artwork_info[] = { {ITDB_THUMB_COVER_XLARGE, 320, 320, 1060, THUMB_FORMAT_RGB565_LE}, /* not sure if the THUMB_FORMAT is correct */ - {ITDB_THUMB_PHOTO_TV_SCREEN, 720, 480, 1067, THUMB_FORMAT_UYVY_BE}, +/* {ITDB_THUMB_PHOTO_TV_SCREEN, 720, 480, 1067, THUMB_FORMAT_UYVY_BE},*/ + {ITDB_THUMB_PHOTO_TV_SCREEN, 720, 480, 1067, THUMB_FORMAT_RGB565_BE}, /* not sure if the THUMB_FORMAT is correct */ - {ITDB_THUMB_PHOTO_FULL_SCREEN,320, 240, 1064, THUMB_FORMAT_RGB565_LE}, + {ITDB_THUMB_PHOTO_FULL_SCREEN,320, 240, 1064, THUMB_FORMAT_RGB888_LE}, {ITDB_THUMB_PHOTO_SMALL, 64, 64, 1066, THUMB_FORMAT_RGB565_LE}, /* These are the same as for the iPod video... -- labeled by the iPod as "chapter images" */ diff --git a/src/itdb_device.h b/src/itdb_device.h index 904dca3..0c45009 100644 --- a/src/itdb_device.h +++ b/src/itdb_device.h @@ -64,6 +64,10 @@ enum _ItdbThumbFormat THUMB_FORMAT_REC_RGB555_LE_90, THUMB_FORMAT_REC_RGB555_BE, THUMB_FORMAT_REC_RGB555_BE_90, + THUMB_FORMAT_RGB888_LE, + THUMB_FORMAT_RGB888_LE_90, + THUMB_FORMAT_RGB888_BE, + THUMB_FORMAT_RGB888_BE_90, THUMB_FORMAT_EXPERIMENTAL_LE, THUMB_FORMAT_EXPERIMENTAL_BE, }; diff --git a/src/ithumb-writer.c b/src/ithumb-writer.c index c6fa507..2c925a8 100644 --- a/src/ithumb-writer.c +++ b/src/ithumb-writer.c @@ -1,4 +1,4 @@ -/* Time-stamp: <2007-09-09 00:13:13 jcs> +/* Time-stamp: <2007-10-27 22:01:00 jcs> * * Copyright (C) 2005 Christophe Fergeau * @@ -67,7 +67,8 @@ typedef struct _iThumbWriter iThumbWriter; static guint16 * pack_RGB_565 (GdkPixbuf *pixbuf, const Itdb_ArtworkFormat *img_info, - gint horizontal_padding, gint vertical_padding) + gint horizontal_padding, gint vertical_padding, + guint32 *thumb_size) { guchar *pixels; guint16 *result; @@ -88,7 +89,8 @@ pack_RGB_565 (GdkPixbuf *pixbuf, const Itdb_ArtworkFormat *img_info, * hardcoded in libipoddevice code, so dst_width * dst_height * 2 can't * overflow, even on an iPod containing malicious data */ - result = g_malloc0 (img_info->width * img_info->height * 2); + *thumb_size = img_info->width * img_info->height * 2; + result = g_malloc0 (*thumb_size); byte_order = itdb_thumb_get_byteorder (img_info->format); @@ -118,7 +120,8 @@ pack_RGB_565 (GdkPixbuf *pixbuf, const Itdb_ArtworkFormat *img_info, static guint16 * pack_RGB_555 (GdkPixbuf *pixbuf, const Itdb_ArtworkFormat *img_info, - gint horizontal_padding, gint vertical_padding) + gint horizontal_padding, gint vertical_padding, + guint32 *thumb_size) { guchar *pixels; guint16 *result; @@ -139,7 +142,9 @@ pack_RGB_555 (GdkPixbuf *pixbuf, const Itdb_ArtworkFormat *img_info, * hardcoded in libipoddevice code, so dst_width * dst_height * 2 can't * overflow, even on an iPod containing malicious data */ - result = g_malloc0 (img_info->width * img_info->height * 2); + + *thumb_size = img_info->width * img_info->height * 2; + result = g_malloc0 (*thumb_size); byte_order = itdb_thumb_get_byteorder (img_info->format); @@ -173,6 +178,65 @@ pack_RGB_555 (GdkPixbuf *pixbuf, const Itdb_ArtworkFormat *img_info, } +static guint16 * +pack_RGB_888 (GdkPixbuf *pixbuf, const Itdb_ArtworkFormat *img_info, + gint horizontal_padding, gint vertical_padding, + guint32 *thumb_size) +{ + guchar *pixels; + guint32 *result; + gint row_stride; + gint channels; + gint width; + gint height; + gint w; + gint h; + gint byte_order; + + g_object_get (G_OBJECT (pixbuf), + "rowstride", &row_stride, "n-channels", &channels, + "height", &height, "width", &width, + "pixels", &pixels, NULL); + g_return_val_if_fail ((width <= img_info->width) && (height <= img_info->height), NULL); + /* dst_width and dst_height come from a width/height database + * hardcoded in libipoddevice code, so dst_width * dst_height * 2 can't + * overflow, even on an iPod containing malicious data + */ + *thumb_size = img_info->width * img_info->height * 4; + result = g_malloc0 (*thumb_size); + + byte_order = itdb_thumb_get_byteorder (img_info->format); + + for (h = 0; h < height; h++) { + gint line = (h+vertical_padding)*img_info->width; + for (w = 0; w < width; w++) { + guint32 r; + guint32 g; + guint32 b; + guint32 a; + + r = pixels[h*row_stride + w*channels]; + g = pixels[h*row_stride + w*channels + 1]; + b = pixels[h*row_stride + w*channels + 2]; + + r >>= (8 - RED_BITS_888); + g >>= (8 - GREEN_BITS_888); + b >>= (8 - BLUE_BITS_888); + a = (0xff << ALPHA_SHIFT_888) & ALPHA_MASK_888; + r = (r << RED_SHIFT_888) & RED_MASK_888; + g = (g << GREEN_SHIFT_888) & GREEN_MASK_888; + b = (b << BLUE_SHIFT_888) & BLUE_MASK_888; + result[line + w + horizontal_padding] = + get_gint32 (a | r | g | b, byte_order); + /* I'm not sure if the highest bit really is + the alpha channel. For now I'm just setting + these bits because that's what I have seen. */ + } + } + return (guint16 *)result; +} + + static guint16 *derange_pixels (guint16 *pixels_s, guint16 *pixels_d, gint width, gint height, gint row_stride) { @@ -212,13 +276,15 @@ static guint16 *derange_pixels (guint16 *pixels_s, guint16 *pixels_d, static guint16 * pack_rec_RGB_555 (GdkPixbuf *pixbuf, const Itdb_ArtworkFormat *img_info, - gint horizontal_padding, gint vertical_padding) + gint horizontal_padding, gint vertical_padding, + guint32 *thumb_size) { guint16 *pixels; guint16 *deranged_pixels = NULL; pixels = pack_RGB_555 (pixbuf, img_info, - horizontal_padding, vertical_padding); + horizontal_padding, vertical_padding, + thumb_size); if (pixels) { @@ -236,7 +302,8 @@ pack_rec_RGB_555 (GdkPixbuf *pixbuf, const Itdb_ArtworkFormat *img_info, * (www.gpixpod.org) */ static guchar * pack_UYVY (GdkPixbuf *orig_pixbuf, const Itdb_ArtworkFormat *img_info, - gint horizontal_padding, gint vertical_padding) + gint horizontal_padding, gint vertical_padding, + guint32 *thumb_size) { GdkPixbuf *pixbuf; guchar *pixels, *yuvdata; @@ -257,6 +324,7 @@ pack_UYVY (GdkPixbuf *orig_pixbuf, const Itdb_ArtworkFormat *img_info, width = img_info->width; height = img_info->height; + *thumb_size = 2*width*height; g_object_get (G_OBJECT (orig_pixbuf), "height", &orig_height, "width", &orig_width, NULL); @@ -274,6 +342,7 @@ pack_UYVY (GdkPixbuf *orig_pixbuf, const Itdb_ArtworkFormat *img_info, "pixels", &pixels, NULL); yuvsize = width*2*height; + yuvdata = g_malloc (yuvsize); halfyuv = yuvsize/2; if (gdk_pixbuf_get_has_alpha(pixbuf)) @@ -572,7 +641,6 @@ ithumb_writer_write_thumbnail (iThumbWriter *writer, thumb->width = thumb->horizontal_padding + width; thumb->height = thumb->vertical_padding + height; thumb->offset = writer->cur_offset; - thumb->size = writer->img_info->width * writer->img_info->height * 2; switch (writer->img_info->format) { @@ -585,7 +653,8 @@ ithumb_writer_write_thumbnail (iThumbWriter *writer, case THUMB_FORMAT_RGB565_BE: pixels = pack_RGB_565 (pixbuf, writer->img_info, thumb->horizontal_padding, - thumb->vertical_padding); + thumb->vertical_padding, + &thumb->size); break; case THUMB_FORMAT_RGB555_LE_90: case THUMB_FORMAT_RGB555_BE_90: @@ -596,7 +665,20 @@ ithumb_writer_write_thumbnail (iThumbWriter *writer, case THUMB_FORMAT_RGB555_BE: pixels = pack_RGB_555 (pixbuf, writer->img_info, thumb->horizontal_padding, - thumb->vertical_padding); + thumb->vertical_padding, + &thumb->size); + break; + case THUMB_FORMAT_RGB888_LE_90: + case THUMB_FORMAT_RGB888_BE_90: + /* FIXME: actually the previous two might require + different treatment (used on iPod Photo for the full + screen photo thumbnail) */ + case THUMB_FORMAT_RGB888_LE: + case THUMB_FORMAT_RGB888_BE: + pixels = pack_RGB_888 (pixbuf, writer->img_info, + thumb->horizontal_padding, + thumb->vertical_padding, + &thumb->size); break; case THUMB_FORMAT_REC_RGB555_LE_90: case THUMB_FORMAT_REC_RGB555_BE_90: @@ -607,7 +689,8 @@ ithumb_writer_write_thumbnail (iThumbWriter *writer, case THUMB_FORMAT_REC_RGB555_BE: pixels = pack_rec_RGB_555 (pixbuf, writer->img_info, thumb->horizontal_padding, - thumb->vertical_padding); + thumb->vertical_padding, + &thumb->size); break; case THUMB_FORMAT_EXPERIMENTAL_LE: case THUMB_FORMAT_EXPERIMENTAL_BE: @@ -616,7 +699,8 @@ ithumb_writer_write_thumbnail (iThumbWriter *writer, case THUMB_FORMAT_UYVY_LE: pixels = pack_UYVY (pixbuf, writer->img_info, thumb->horizontal_padding, - thumb->vertical_padding); + thumb->vertical_padding, + &thumb->size); break; } @@ -627,6 +711,7 @@ ithumb_writer_write_thumbnail (iThumbWriter *writer, { return FALSE; } + if (fwrite (pixels, thumb->size, 1, writer->f) != 1) { g_free (pixels); g_print ("Error writing to file: %s\n", strerror (errno)); |