summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJorg Schuler <jcsjcs@users.sourceforge.net>2007-10-27 13:11:35 +0000
committerJorg Schuler <jcsjcs@users.sourceforge.net>2007-10-27 13:11:35 +0000
commit46b4a757c9349b6727b9f25aee4456a2007d6f9c (patch)
tree08fb6aa2409bce45fd4c2eae12d701c86b1cd03a
parenta443d5bb4d8f41d3d866a41b6282673e83de771c (diff)
downloadlibgpod-46b4a757c9349b6727b9f25aee4456a2007d6f9c.tar.gz
libgpod-46b4a757c9349b6727b9f25aee4456a2007d6f9c.tar.xz
libgpod-46b4a757c9349b6727b9f25aee4456a2007d6f9c.zip
* src/itdb_device.c (ipod_classic_1_artwork_info)
src/ithumb-writer.c (pack_RGB_888, pack_RGB_565, pack_RGB_555, pack_rec_RGB_555, ithumb_writer_write_thumbnail) src/db-image-parser.h (_888 definitions) src/itdb_device.h (RGB888 thumb format enum definitions) src/itdb_artwork.c (unpack_RGB_888, unpack_experimental, itdb_thumb_get_rgb_data) Partial support for photos on new iPod Nano 3G and iPod Classics. Photos should be displayed correctly on the iPod but the video output will show garbage (couldn't try video output per se, but from the data iTunes produces this is clear). git-svn-id: https://gtkpod.svn.sf.net/svnroot/gtkpod/libgpod/trunk@1741 f01d2545-417e-4e96-918e-98f8d0dbbcb6
-rw-r--r--ChangeLog17
-rw-r--r--src/db-image-parser.h16
-rw-r--r--src/itdb_artwork.c102
-rw-r--r--src/itdb_device.c5
-rw-r--r--src/itdb_device.h4
-rw-r--r--src/ithumb-writer.c111
6 files changed, 197 insertions, 58 deletions
diff --git a/ChangeLog b/ChangeLog
index 3ef6fcc..f7d79f1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2007-10-27 Jorg Schuler <jcsjcs at users.sourceforge.net>
+
+ * src/itdb_device.c (ipod_classic_1_artwork_info)
+ src/ithumb-writer.c (pack_RGB_888, pack_RGB_565, pack_RGB_555,
+ pack_rec_RGB_555, ithumb_writer_write_thumbnail)
+ src/db-image-parser.h (_888 definitions)
+ src/itdb_device.h (RGB888 thumb format enum definitions)
+ src/itdb_artwork.c (unpack_RGB_888, unpack_experimental,
+ itdb_thumb_get_rgb_data)
+
+ Partial support for photos on new iPod Nano 3G and iPod
+ Classics.
+
+ Photos should be displayed correctly on the iPod but the video
+ output will show garbage (couldn't try video output per se, but
+ from the data iTunes produces this is clear).
+
2007-10-24 Christophe Fergeau <teuf@gnome.org>
* src/db-artwork-writer.c: (write_mhif), (should_write),
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));