summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
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));