Revision: 1691
          http://gtkpod.svn.sourceforge.net/gtkpod/?rev=1691&view=rev
Author:   jcsjcs
Date:     2007-09-08 08:15:57 -0700 (Sat, 08 Sep 2007)

Log Message:
-----------
        * src/db-image-parser.c
          src/itdb_device.c
          src/ithumb-writer.c
          src/db-image-parser.h
          src/itdb_device.h
          src/itdb.h
          src/itdb_artwork.c
          tests/test-covers.c: added support to read and write coverart on
          iPhones. New cover formats are: MEDIUM, XLARGE, XSMALL, SMEDIUM
          -- should be renamed if function becomes clearer.

          Introduced New image formats for the thumbnails
          (THUMB_FORMAT_RGB555, THUMB_FORMAT_REC_RGB555). Coding/decoding
          functions are pack_/unpack_RGB_555() and
          pack_/unpack_REC_RGB_555().

          Introduced possible padding for thumbnail files
          (Itdb_ArtworkFormat).

          * src/db-artwork-parser.c: make output filename unique.

Modified Paths:
--------------
    libgpod/trunk/ChangeLog
    libgpod/trunk/docs/reference/tmpl/artwork.sgml
    libgpod/trunk/src/db-artwork-parser.c
    libgpod/trunk/src/db-image-parser.c
    libgpod/trunk/src/db-image-parser.h
    libgpod/trunk/src/itdb.h
    libgpod/trunk/src/itdb_artwork.c
    libgpod/trunk/src/itdb_device.c
    libgpod/trunk/src/itdb_device.h
    libgpod/trunk/src/ithumb-writer.c
    libgpod/trunk/tests/test-covers.c

Modified: libgpod/trunk/ChangeLog
===================================================================
--- libgpod/trunk/ChangeLog     2007-09-04 16:10:05 UTC (rev 1690)
+++ libgpod/trunk/ChangeLog     2007-09-08 15:15:57 UTC (rev 1691)
@@ -1,5 +1,28 @@
-2007-09-4 Jorg Schuler <jcsjcs at users.sourceforge.net>
+2007-09-08 Jorg Schuler <jcsjcs at users.sourceforge.net>
 
+       * src/db-image-parser.c
+         src/itdb_device.c
+         src/ithumb-writer.c
+         src/db-image-parser.h
+         src/itdb_device.h
+         src/itdb.h
+         src/itdb_artwork.c
+         tests/test-covers.c: added support to read and write coverart on
+         iPhones. New cover formats are: MEDIUM, XLARGE, XSMALL, SMEDIUM
+         -- should be renamed if function becomes clearer.
+
+         Introduced New image formats for the thumbnails
+         (THUMB_FORMAT_RGB555, THUMB_FORMAT_REC_RGB555). Coding/decoding
+         functions are pack_/unpack_RGB_555() and
+         pack_/unpack_REC_RGB_555().
+
+         Introduced possible padding for thumbnail files
+         (Itdb_ArtworkFormat).
+
+         * src/db-artwork-parser.c: make output filename unique.
+
+2007-09-04 Jorg Schuler <jcsjcs at users.sourceforge.net>
+
        * itdb_itunesdb.c (itdb_get_control_dir):
          added support for iPhones
 

Modified: libgpod/trunk/docs/reference/tmpl/artwork.sgml
===================================================================
--- libgpod/trunk/docs/reference/tmpl/artwork.sgml      2007-09-04 16:10:05 UTC 
(rev 1690)
+++ libgpod/trunk/docs/reference/tmpl/artwork.sgml      2007-09-08 15:15:57 UTC 
(rev 1691)
@@ -74,6 +74,10 @@
 @ITDB_THUMB_PHOTO_LARGE: 
 @ITDB_THUMB_PHOTO_FULL_SCREEN: 
 @ITDB_THUMB_PHOTO_TV_SCREEN: 
[EMAIL PROTECTED]: 
[EMAIL PROTECTED]: 
[EMAIL PROTECTED]: 
[EMAIL PROTECTED]: 
 
 <!-- ##### FUNCTION itdb_artwork_new ##### -->
 <para>

Modified: libgpod/trunk/src/db-artwork-parser.c
===================================================================
--- libgpod/trunk/src/db-artwork-parser.c       2007-09-04 16:10:05 UTC (rev 
1690)
+++ libgpod/trunk/src/db-artwork-parser.c       2007-09-08 15:15:57 UTC (rev 
1691)
@@ -587,6 +587,11 @@
            case ITDB_THUMB_PHOTO_FULL_SCREEN:
            case ITDB_THUMB_PHOTO_TV_SCREEN:
                break;
+           case ITDB_THUMB_COVER_XLARGE:
+           case ITDB_THUMB_COVER_MEDIUM:
+           case ITDB_THUMB_COVER_SMEDIUM:
+           case ITDB_THUMB_COVER_XSMALL:
+               break;
            }
            formats++;
        }
@@ -620,6 +625,11 @@
            case ITDB_THUMB_PHOTO_FULL_SCREEN:
            case ITDB_THUMB_PHOTO_TV_SCREEN:
                return TRUE;
+           case ITDB_THUMB_COVER_XLARGE:
+           case ITDB_THUMB_COVER_MEDIUM:
+           case ITDB_THUMB_COVER_SMEDIUM:
+           case ITDB_THUMB_COVER_XSMALL:
+               break;
            }
            formats++;
        }

Modified: libgpod/trunk/src/db-image-parser.c
===================================================================
--- libgpod/trunk/src/db-image-parser.c 2007-09-04 16:10:05 UTC (rev 1690)
+++ libgpod/trunk/src/db-image-parser.c 2007-09-08 15:15:57 UTC (rev 1691)
@@ -113,6 +113,11 @@
        corr_id = get_gint32_db (db, mhni->correlation_id);
        img->type = image_type_from_corr_id (device, corr_id);
 
+#if DEBUG_ARTWORK
+       printf ("corr_id: %d, of: %6d sz: %6d, x: %3d, y: %3d, xpad: %3d, ypad: 
%3d\n",
+               corr_id, img->offset, img->size, img->width, img->height, 
img->horizontal_padding, img->vertical_padding);
+#endif
+
        if (img->type == -1)
        {
            g_warning (_("Unexpected image type in mhni: size: %ux%u (%d), 
offset: %d\n"), 

Modified: libgpod/trunk/src/db-image-parser.h
===================================================================
--- libgpod/trunk/src/db-image-parser.h 2007-09-04 16:10:05 UTC (rev 1690)
+++ libgpod/trunk/src/db-image-parser.h 2007-09-08 15:15:57 UTC (rev 1691)
@@ -31,18 +31,36 @@
 #include "itdb_private.h"
 #include "itdb.h"
 
-#define RED_BITS   5
-#define RED_SHIFT 11
-#define RED_MASK  (((1 << RED_BITS)-1) << RED_SHIFT)
+#define DEBUG_ARTWORK 0
 
-#define GREEN_BITS 6
-#define GREEN_SHIFT 5
-#define GREEN_MASK (((1 << GREEN_BITS)-1) << GREEN_SHIFT)
+#define RED_BITS_565   5
+#define RED_SHIFT_565 11
+#define RED_MASK_565  (((1 << RED_BITS_565)-1) << RED_SHIFT_565)
 
-#define BLUE_BITS 5
-#define BLUE_SHIFT 0
-#define BLUE_MASK (((1 << BLUE_BITS)-1) << BLUE_SHIFT)
+#define GREEN_BITS_565 6
+#define GREEN_SHIFT_565 5
+#define GREEN_MASK_565 (((1 << GREEN_BITS_565)-1) << GREEN_SHIFT_565)
 
+#define BLUE_BITS_565 5
+#define BLUE_SHIFT_565 0
+#define BLUE_MASK_565 (((1 << BLUE_BITS_565)-1) << BLUE_SHIFT_565)
+
+#define ALPHA_BITS_555 1
+#define ALPHA_SHIFT_555 15
+#define ALPHA_MASK_555  (((1 << ALPHA_BITS_555)-1) << ALPHA_SHIFT_555)
+
+#define RED_BITS_555   5
+#define RED_SHIFT_555 10
+#define RED_MASK_555  (((1 << RED_BITS_555)-1) << RED_SHIFT_555)
+
+#define GREEN_BITS_555 5
+#define GREEN_SHIFT_555 5
+#define GREEN_MASK_555 (((1 << GREEN_BITS_555)-1) << GREEN_SHIFT_555)
+
+#define BLUE_BITS_555 5
+#define BLUE_SHIFT_555 0
+#define BLUE_MASK_555 (((1 << BLUE_BITS_555)-1) << BLUE_SHIFT_555)
+
 G_GNUC_INTERNAL Itdb_Thumb *ipod_image_new_from_mhni (MhniHeader *mhni, 
                                                      Itdb_DB *db);
 

Modified: libgpod/trunk/src/itdb.h
===================================================================
--- libgpod/trunk/src/itdb.h    2007-09-04 16:10:05 UTC (rev 1690)
+++ libgpod/trunk/src/itdb.h    2007-09-08 15:15:57 UTC (rev 1691)
@@ -428,7 +428,11 @@
     ITDB_THUMB_PHOTO_SMALL,
     ITDB_THUMB_PHOTO_LARGE,
     ITDB_THUMB_PHOTO_FULL_SCREEN,
-    ITDB_THUMB_PHOTO_TV_SCREEN
+    ITDB_THUMB_PHOTO_TV_SCREEN,
+    ITDB_THUMB_COVER_XLARGE,      /* iPhone: cover flow */
+    ITDB_THUMB_COVER_MEDIUM,      /* iPhone: cover view */
+    ITDB_THUMB_COVER_SMEDIUM,     /* iPhone: ??         */
+    ITDB_THUMB_COVER_XSMALL,      /* iPhone: ??         */
 } ItdbThumbType;
 
 

Modified: libgpod/trunk/src/itdb_artwork.c
===================================================================
--- libgpod/trunk/src/itdb_artwork.c    2007-09-04 16:10:05 UTC (rev 1690)
+++ libgpod/trunk/src/itdb_artwork.c    2007-09-08 15:15:57 UTC (rev 1691)
@@ -1,4 +1,4 @@
-/* Time-stamp: <2007-08-18 16:22:17 jcs>
+/* Time-stamp: <2007-09-09 00:12:28 jcs>
 |
 |  Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
 |  Part of the gtkpod project.
@@ -434,29 +434,219 @@
        guint i;
 
        g_return_val_if_fail (bytes_len < 2*(G_MAXUINT/3), NULL);
+
        result = g_malloc ((bytes_len/2) * 3);
-       if (result == NULL) {
-               return NULL;
+
+       for (i = 0; i < bytes_len/2; i++) {
+               guint16 cur_pixel;
+               /* FIXME: endianness */
+               cur_pixel = get_gint16 (pixels[i], byte_order);
+               /* Unpack pixels */
+               result[3*i] = (cur_pixel & RED_MASK_565) >> RED_SHIFT_565;
+               result[3*i+1] = (cur_pixel & GREEN_MASK_565) >> GREEN_SHIFT_565;
+               result[3*i+2] = (cur_pixel & BLUE_MASK_565) >> BLUE_SHIFT_565;
+               
+               /* Normalize color values so that they use a [0..255] range */
+               result[3*i] <<= (8 - RED_BITS_565);
+               result[3*i+1] <<= (8 - GREEN_BITS_565);
+               result[3*i+2] <<= (8 - BLUE_BITS_565);
        }
+
+       return result;
+}
+
+static guchar *
+unpack_RGB_555 (guint16 *pixels, guint bytes_len, guint byte_order)
+{
+       guchar *result;
+       guint i;
+
+       g_return_val_if_fail (bytes_len < 2*(G_MAXUINT/3), NULL);
+
+       result = g_malloc ((bytes_len/2) * 3);
+
        for (i = 0; i < bytes_len/2; i++) {
                guint16 cur_pixel;
                /* FIXME: endianness */
                cur_pixel = get_gint16 (pixels[i], byte_order);
                /* Unpack pixels */
-               result[3*i] = (cur_pixel & RED_MASK) >> RED_SHIFT;
-               result[3*i+1] = (cur_pixel & GREEN_MASK) >> GREEN_SHIFT;
-               result[3*i+2] = (cur_pixel & BLUE_MASK) >> BLUE_SHIFT;
+               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;
                
                /* Normalize color values so that they use a [0..255] range */
-               result[3*i] <<= (8 - RED_BITS);
-               result[3*i+1] <<= (8 - GREEN_BITS);
-               result[3*i+2] <<= (8 - BLUE_BITS);
+               result[3*i] <<= (8 - RED_BITS_555);
+               result[3*i+1] <<= (8 - GREEN_BITS_555);
+               result[3*i+2] <<= (8 - BLUE_BITS_555);
        }
 
        return result;
 }
 
 
+static guint16 *rearrange_pixels (guint16 *pixels_s, guint16 *pixels_d,
+                                 gint width, gint height, gint row_stride)
+{
+    g_return_val_if_fail (width == height, pixels_d);
+
+    if (pixels_d == NULL)
+    {
+       pixels_d = g_malloc0 (sizeof (guint16)*width*height);
+    }
+
+    if (width == 1)
+    {
+       *pixels_d = *pixels_s;
+    }
+    else
+    {
+       rearrange_pixels (pixels_s + 0,
+                         pixels_d + 0 + 0,
+                         width/2, height/2,
+                         row_stride);
+       rearrange_pixels (pixels_s + (width/2)*(height/2),
+                         pixels_d + (height/2)*row_stride + 0,
+                         width/2, height/2,
+                         row_stride);
+       rearrange_pixels (pixels_s + 2*(width/2)*(height/2),
+                         pixels_d + width/2,
+                         width/2, height/2,
+                         row_stride);
+       rearrange_pixels (pixels_s + 3*(width/2)*(height/2),
+                         pixels_d + (height/2)*row_stride + width/2,
+                         width/2, height/2,
+                         row_stride);
+    }
+    
+    return pixels_d;
+}
+
+
+static guchar *
+unpack_rec_RGB_555 (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;
+
+       guint i;
+
+       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);
+
+       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;
+       }
+
+       pixels_arranged = rearrange_pixels (use_pixels, NULL,
+                                           width, height, width);
+
+       if (pixels_arranged == NULL)
+       {
+           return NULL;
+       }
+
+       result = g_malloc ((bytes_len/2) * 3);
+
+       for (i = 0; i < bytes_len/2; i++) {
+               guint16 cur_pixel;
+               /* FIXME: endianness */
+               cur_pixel = get_gint16 (pixels_arranged[i], byte_order);
+               /* 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;
+               
+               /* 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);
+       }
+
+       return result;
+}
+
+
+#if DEBUG_ARTWORK
+static guchar *
+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;
+
+       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);
+
+       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;
+       }
+
+/*     pixels_arranged = rearrange_pixels (use_pixels, NULL,
+                                           width, height, width);
+
+       if (pixels_arranged == NULL)
+       {
+           return NULL;
+       }
+*/
+
+       result = g_malloc ((bytes_len/2) * 3);
+
+       for (i = 0; i < bytes_len/2; i++) {
+               guint16 cur_pixel;
+               /* FIXME: endianness */
+               cur_pixel = get_gint16 (pixels[i], byte_order);
+               /* 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;
+               
+               /* 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);
+       }
+
+       return result;
+}
+#endif
+
+
 /* limit8bit() and unpack_UYVY() adapted from imgconvert.c from the
  * GPixPod project (www.gpixpod.org) */
 static gint limit8bit (float x)
@@ -472,7 +662,8 @@
     return x;
 }
 static guchar *
-unpack_UYVY (guchar *yuvdata, gint bytes_len, gint width, gint height)
+unpack_UYVY (guchar *yuvdata, gint bytes_len, guint byte_order,
+            gint width, gint height)
 {
     gint imgsize = width*3*height;
     guchar* rgbdata;
@@ -485,6 +676,7 @@
     gint h = 0;
 
     g_return_val_if_fail (bytes_len < 2*(G_MAXUINT/3), NULL);
+/*     printf ("w=%d h=%d s=%d\n", width, height, bytes_len); */
     g_return_val_if_fail (width * height * 2 == bytes_len, NULL);
 
     rgbdata =  g_malloc(imgsize);
@@ -598,6 +790,13 @@
 static guchar *
 itdb_thumb_get_rgb_data (Itdb_Device *device, Itdb_Thumb *thumb)
 {
+#if 0
+    #include <unistd.h>
+    #include <fcntl.h>
+    static gint i=0;
+    int fd;
+    gchar *name;
+#endif
        void *pixels_raw;
        guchar *pixels=NULL;
        const Itdb_ArtworkFormat *img_info;
@@ -609,6 +808,14 @@
        g_return_val_if_fail (img_info, NULL);
        
        pixels_raw = get_pixel_data (device, thumb);
+
+#if 0
+    name = g_strdup_printf ("thumb_%03d.raw", i++);
+    fd = creat (name, S_IRWXU|S_IRWXG|S_IRWXO);
+    write (fd, pixels_raw, thumb->size);
+    close (fd);
+    g_free (name);
+#endif
        if (pixels_raw == NULL) {
                return NULL;
        }
@@ -625,8 +832,39 @@
            pixels = unpack_RGB_565 (pixels_raw, thumb->size,
                                     itdb_thumb_get_byteorder 
(img_info->format));
            break;
-       case THUMB_FORMAT_UYVY:
+       case THUMB_FORMAT_RGB555_LE_90:
+       case THUMB_FORMAT_RGB555_BE_90:
+           /* FIXME: actually the previous two might require
+              different treatment (used on iPod Photo for the full
+              screen photo thumbnail) */
+       case THUMB_FORMAT_RGB555_LE:
+       case THUMB_FORMAT_RGB555_BE:
+           pixels = unpack_RGB_555 (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
+              different treatment (used on iPod Photo for the full
+              screen photo thumbnail) */
+       case THUMB_FORMAT_REC_RGB555_LE:
+       case THUMB_FORMAT_REC_RGB555_BE:
+           pixels = unpack_rec_RGB_555 (pixels_raw, thumb->size,
+                                        itdb_thumb_get_byteorder 
(img_info->format),
+                                        img_info->width, img_info->height);
+           break;
+       case THUMB_FORMAT_EXPERIMENTAL_LE:
+       case THUMB_FORMAT_EXPERIMENTAL_BE:
+#if DEBUG_ARTWORK
+           pixels = unpack_experimental (pixels_raw, thumb->size,
+                                         itdb_thumb_get_byteorder 
(img_info->format),
+                                         img_info->width, img_info->height);
+           break;
+#endif
+       case THUMB_FORMAT_UYVY_LE:
+       case THUMB_FORMAT_UYVY_BE:
            pixels = unpack_UYVY (pixels_raw, thumb->size,
+                                 itdb_thumb_get_byteorder (img_info->format),
                                  img_info->width, img_info->height);
            break;
        }
@@ -701,6 +939,14 @@
                width = 220;  height = 176;  break;
            case ITDB_THUMB_PHOTO_TV_SCREEN:
                width = 720;  height = 480;  break;
+           case ITDB_THUMB_COVER_XLARGE:
+               width = 320;  height = 320;  break;
+           case ITDB_THUMB_COVER_MEDIUM:
+               width = 128;  height = 128;  break;
+           case ITDB_THUMB_COVER_SMEDIUM:
+               width = 88;  height = 88;  break;
+           case ITDB_THUMB_COVER_XSMALL:
+               width = 56;  height = 56;  break;
            }
            if (width == 0)
            {
@@ -814,6 +1060,10 @@
        if (pad_y + height > img_info->height)
            height = img_info->height - pad_y;
 
+#if DEBUG_ARTWORK
+       printf ("px=%2d py=%2d x=%3d y=%3d\n", pad_x, pad_y, width, height);
+#endif
+
        pixbuf_sub = gdk_pixbuf_new_subpixbuf (pixbuf_full,
                                               pad_x, pad_y,
                                               width, height);
@@ -903,14 +1153,24 @@
 {
     switch (format)
     {
+    case THUMB_FORMAT_UYVY_LE:
     case THUMB_FORMAT_RGB565_LE:
     case THUMB_FORMAT_RGB565_LE_90:
+    case THUMB_FORMAT_RGB555_LE:
+    case THUMB_FORMAT_RGB555_LE_90:
+    case THUMB_FORMAT_REC_RGB555_LE:
+    case THUMB_FORMAT_REC_RGB555_LE_90:
+    case THUMB_FORMAT_EXPERIMENTAL_LE:
        return G_LITTLE_ENDIAN;
+    case THUMB_FORMAT_UYVY_BE:
     case THUMB_FORMAT_RGB565_BE:
     case THUMB_FORMAT_RGB565_BE_90:
+    case THUMB_FORMAT_RGB555_BE:
+    case THUMB_FORMAT_RGB555_BE_90:
+    case THUMB_FORMAT_REC_RGB555_BE:
+    case THUMB_FORMAT_REC_RGB555_BE_90:
+    case THUMB_FORMAT_EXPERIMENTAL_BE:
        return G_BIG_ENDIAN;
-    case THUMB_FORMAT_UYVY:
-       return -1;
     }
     g_return_val_if_reached (-1);
 }

Modified: libgpod/trunk/src/itdb_device.c
===================================================================
--- libgpod/trunk/src/itdb_device.c     2007-09-04 16:10:05 UTC (rev 1690)
+++ libgpod/trunk/src/itdb_device.c     2007-09-08 15:15:57 UTC (rev 1691)
@@ -213,7 +213,7 @@
     {ITDB_THUMB_PHOTO_SMALL,       42,  30, 1009, THUMB_FORMAT_RGB565_LE},
     {ITDB_THUMB_PHOTO_LARGE,      130,  88, 1015, THUMB_FORMAT_RGB565_LE},
     {ITDB_THUMB_PHOTO_FULL_SCREEN,220, 176, 1013, THUMB_FORMAT_RGB565_BE_90},
-    {ITDB_THUMB_PHOTO_TV_SCREEN,  720, 480, 1019, THUMB_FORMAT_UYVY},
+    {ITDB_THUMB_PHOTO_TV_SCREEN,  720, 480, 1019, THUMB_FORMAT_UYVY_BE},
     {-1,                           -1,  -1,   -1, -1}
 };
 
@@ -231,7 +231,7 @@
     {ITDB_THUMB_PHOTO_SMALL,       50,  41, 1036, THUMB_FORMAT_RGB565_LE},
     {ITDB_THUMB_PHOTO_LARGE,      130,  88, 1015, THUMB_FORMAT_RGB565_LE},
     {ITDB_THUMB_PHOTO_FULL_SCREEN,320, 240, 1024, THUMB_FORMAT_RGB565_LE},
-    {ITDB_THUMB_PHOTO_TV_SCREEN,  720, 480, 1019, THUMB_FORMAT_UYVY},
+    {ITDB_THUMB_PHOTO_TV_SCREEN,  720, 480, 1019, THUMB_FORMAT_UYVY_BE},
     {-1,                           -1,  -1,   -1, -1}
 };
 
@@ -241,7 +241,17 @@
     {-1,                           -1,  -1,   -1, -1}
 };
 
+static const Itdb_ArtworkFormat ipod_iphone_1_artwork_info[] = {
+    {ITDB_THUMB_COVER_LARGE,      256, 256, 3001, THUMB_FORMAT_REC_RGB555_LE},
+    {ITDB_THUMB_COVER_MEDIUM,     128, 128, 3002, THUMB_FORMAT_REC_RGB555_LE},
+    {ITDB_THUMB_COVER_SMALL,       64,  64, 3003, THUMB_FORMAT_REC_RGB555_LE},
+    {ITDB_THUMB_COVER_XLARGE,     320, 320, 3005, THUMB_FORMAT_RGB555_LE},
+    {ITDB_THUMB_COVER_XSMALL,      56,  56, 3006, THUMB_FORMAT_RGB555_LE,  
8192}, /*pad data to  8192 bytes */
+    {ITDB_THUMB_COVER_SMEDIUM,     88,  88, 3007, THUMB_FORMAT_RGB555_LE, 
16364}, /*pad data to 16384 bytes */
+    {-1,                           -1,  -1,   -1, -1}
+};
 
+
 /* This will be indexed using a value from the ITDB_IPOD_MODEL enum */
 static const Itdb_ArtworkFormat *ipod_artwork_info_table[] = {
         NULL,                      /* Invalid       */
@@ -266,7 +276,7 @@
        ipod_nano_artwork_info,    /* Nano (Blue)   */
        ipod_nano_artwork_info,    /* Nano (Green)  */
        ipod_nano_artwork_info,    /* Nano (Pink)   */
-       NULL,                      /* iPhone (1) -- FIXME! */
+       ipod_iphone_1_artwork_info,/* iPhone (1)    */
        NULL
 };
 

Modified: libgpod/trunk/src/itdb_device.h
===================================================================
--- libgpod/trunk/src/itdb_device.h     2007-09-04 16:10:05 UTC (rev 1690)
+++ libgpod/trunk/src/itdb_device.h     2007-09-08 15:15:57 UTC (rev 1691)
@@ -50,11 +50,22 @@
 
 enum _ItdbThumbFormat
 {
-    THUMB_FORMAT_UYVY,
+    THUMB_FORMAT_UYVY_LE,
+    THUMB_FORMAT_UYVY_BE,
     THUMB_FORMAT_RGB565_LE,
     THUMB_FORMAT_RGB565_LE_90,
     THUMB_FORMAT_RGB565_BE,
     THUMB_FORMAT_RGB565_BE_90,
+    THUMB_FORMAT_RGB555_LE,
+    THUMB_FORMAT_RGB555_LE_90,
+    THUMB_FORMAT_RGB555_BE,
+    THUMB_FORMAT_RGB555_BE_90,
+    THUMB_FORMAT_REC_RGB555_LE,
+    THUMB_FORMAT_REC_RGB555_LE_90,
+    THUMB_FORMAT_REC_RGB555_BE,
+    THUMB_FORMAT_REC_RGB555_BE_90,
+    THUMB_FORMAT_EXPERIMENTAL_LE,
+    THUMB_FORMAT_EXPERIMENTAL_BE,
 };
 
 
@@ -83,6 +94,7 @@
        gint16 height;
        gint16 correlation_id;
         ItdbThumbFormat format;
+        gint32 padding;
 };
 
 G_GNUC_INTERNAL const Itdb_ArtworkFormat *itdb_device_get_artwork_formats 
(Itdb_Device *device);

Modified: libgpod/trunk/src/ithumb-writer.c
===================================================================
--- libgpod/trunk/src/ithumb-writer.c   2007-09-04 16:10:05 UTC (rev 1690)
+++ libgpod/trunk/src/ithumb-writer.c   2007-09-08 15:15:57 UTC (rev 1691)
@@ -1,4 +1,4 @@
-/*  Time-stamp: <2007-02-10 01:00:40 jcs>
+/*  Time-stamp: <2007-09-09 00:13:13 jcs>
  *
  *  Copyright (C) 2005 Christophe Fergeau
  *
@@ -103,12 +103,12 @@
                        g = pixels[h*row_stride + w*channels + 1]; 
                        b = pixels[h*row_stride + w*channels + 2]; 
 
-                       r >>= (8 - RED_BITS);
-                       g >>= (8 - GREEN_BITS);
-                       b >>= (8 - BLUE_BITS);
-                       r = (r << RED_SHIFT) & RED_MASK;
-                       g = (g << GREEN_SHIFT) & GREEN_MASK;
-                       b = (b << BLUE_SHIFT) & BLUE_MASK;
+                       r >>= (8 - RED_BITS_565);
+                       g >>= (8 - GREEN_BITS_565);
+                       b >>= (8 - BLUE_BITS_565);
+                       r = (r << RED_SHIFT_565) & RED_MASK_565;
+                       g = (g << GREEN_SHIFT_565) & GREEN_MASK_565;
+                       b = (b << BLUE_SHIFT_565) & BLUE_MASK_565;
                        result[line + w + horizontal_padding] =
                            get_gint16 (r | g | b, byte_order);
                }
@@ -116,7 +116,122 @@
        return result;
 }
 
+static guint16 *
+pack_RGB_555 (GdkPixbuf *pixbuf, const Itdb_ArtworkFormat *img_info,
+             gint horizontal_padding, gint vertical_padding)
+{
+       guchar *pixels;
+       guint16 *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
+        */
+       result = g_malloc0 (img_info->width * img_info->height * 2);
+
+       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++) {
+                       gint r;
+                       gint g;
+                       gint b;
+                       gint 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_555);
+                       g >>= (8 - GREEN_BITS_555);
+                       b >>= (8 - BLUE_BITS_555);
+                       a = (1 << ALPHA_SHIFT_555) & ALPHA_MASK_555;
+                       r = (r << RED_SHIFT_555) & RED_MASK_555;
+                       g = (g << GREEN_SHIFT_555) & GREEN_MASK_555;
+                       b = (b << BLUE_SHIFT_555) & BLUE_MASK_555;
+                       result[line + w + horizontal_padding] =
+                           get_gint16 (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
+                          this bit because that's what I have seen. */
+               }
+       }
+       return result;
+}
+
+
+static guint16 *derange_pixels (guint16 *pixels_s, guint16 *pixels_d,
+                               gint width, gint height, gint row_stride)
+{
+    g_return_val_if_fail (width == height, pixels_s);
+
+    if (pixels_s == NULL)
+    {
+       pixels_s = g_malloc0 (sizeof (guint16)*width*height);
+    }
+
+    if (width == 1)
+    {
+       *pixels_s = *pixels_d;
+    }
+    else
+    {
+       derange_pixels (pixels_s + 0,
+                       pixels_d + 0 + 0,
+                       width/2, height/2,
+                       row_stride);
+       derange_pixels (pixels_s + (width/2)*(height/2),
+                       pixels_d + (height/2)*row_stride + 0,
+                       width/2, height/2,
+                       row_stride);
+       derange_pixels (pixels_s + 2*(width/2)*(height/2),
+                       pixels_d + width/2,
+                       width/2, height/2,
+                       row_stride);
+       derange_pixels (pixels_s + 3*(width/2)*(height/2),
+                       pixels_d + (height/2)*row_stride + width/2,
+                       width/2, height/2,
+                       row_stride);
+    }
+    
+    return pixels_s;
+}
+
+static guint16 *
+pack_rec_RGB_555 (GdkPixbuf *pixbuf, const Itdb_ArtworkFormat *img_info,
+                 gint horizontal_padding, gint vertical_padding)
+{
+    guint16 *pixels;
+    guint16 *deranged_pixels = NULL;
+
+    pixels = pack_RGB_555 (pixbuf, img_info,
+                          horizontal_padding, vertical_padding);
+
+    if (pixels)
+    {
+       deranged_pixels = derange_pixels (NULL, pixels,
+                                         img_info->width, img_info->height,
+                                         img_info->width);
+       g_free (pixels);
+    }
+
+    return deranged_pixels;
+}
+
+
 /* pack_UYVY() is adapted from imgconvert.c from the GPixPod project
  * (www.gpixpod.org) */
 static guchar *
@@ -424,6 +539,10 @@
        break;
     case ITDB_THUMB_COVER_LARGE:
     case ITDB_THUMB_COVER_SMALL:
+    case ITDB_THUMB_COVER_XLARGE:
+    case ITDB_THUMB_COVER_MEDIUM:
+    case ITDB_THUMB_COVER_SMEDIUM:
+    case ITDB_THUMB_COVER_XSMALL:
        thumb->filename = g_strdup_printf (":F%d_%d.ithmb", 
                                           writer->img_info->correlation_id,
                                           writer->current_file_index);
@@ -468,7 +587,33 @@
                               thumb->horizontal_padding,
                               thumb->vertical_padding);
        break;
-    case THUMB_FORMAT_UYVY:
+    case THUMB_FORMAT_RGB555_LE_90:
+    case THUMB_FORMAT_RGB555_BE_90:
+       /* FIXME: actually the previous two might require
+          different treatment (used on iPod Photo for the full
+          screen photo thumbnail) */
+    case THUMB_FORMAT_RGB555_LE:
+    case THUMB_FORMAT_RGB555_BE:
+       pixels = pack_RGB_555 (pixbuf, writer->img_info,
+                              thumb->horizontal_padding,
+                              thumb->vertical_padding);
+       break;
+    case THUMB_FORMAT_REC_RGB555_LE_90:
+    case THUMB_FORMAT_REC_RGB555_BE_90:
+       /* FIXME: actually the previous two might require
+          different treatment (used on iPod Photo for the full
+          screen photo thumbnail) */
+    case THUMB_FORMAT_REC_RGB555_LE:
+    case THUMB_FORMAT_REC_RGB555_BE:
+       pixels = pack_rec_RGB_555 (pixbuf, writer->img_info,
+                                  thumb->horizontal_padding,
+                                  thumb->vertical_padding);
+       break;
+    case THUMB_FORMAT_EXPERIMENTAL_LE:
+    case THUMB_FORMAT_EXPERIMENTAL_BE:
+       break;
+    case THUMB_FORMAT_UYVY_BE:
+    case THUMB_FORMAT_UYVY_LE:
        pixels = pack_UYVY (pixbuf, writer->img_info,
                            thumb->horizontal_padding,
                            thumb->vertical_padding);
@@ -490,6 +635,23 @@
     g_free (pixels);
     writer->cur_offset += thumb->size;
 
+    if (writer->img_info->padding != 0)
+    {
+       gint padding = writer->img_info->padding - thumb->size;
+       g_return_val_if_fail (padding >= 0, TRUE);
+       if (padding != 0)
+       {
+            /* FIXME: check if a simple fseek() will do the same */
+           gchar *pad_bytes = g_malloc0 (padding);
+           if (fwrite (pad_bytes, padding, 1, writer->f) != 1) {
+               g_free (pad_bytes);
+               g_print ("Error writing to file: %s\n", strerror (errno));
+               return FALSE;
+           }
+           g_free (pad_bytes);
+           writer->cur_offset += padding;
+       }
+    }
     return TRUE;
 }
 
@@ -949,6 +1111,10 @@
                iThumbWriter *writer;
 
                switch (format->type) {
+               case ITDB_THUMB_COVER_XLARGE:
+               case ITDB_THUMB_COVER_MEDIUM:
+               case ITDB_THUMB_COVER_SMEDIUM:
+               case ITDB_THUMB_COVER_XSMALL:
                case ITDB_THUMB_COVER_SMALL:
                case ITDB_THUMB_COVER_LARGE:
                case ITDB_THUMB_PHOTO_SMALL:

Modified: libgpod/trunk/tests/test-covers.c
===================================================================
--- libgpod/trunk/tests/test-covers.c   2007-09-04 16:10:05 UTC (rev 1690)
+++ libgpod/trunk/tests/test-covers.c   2007-09-08 15:15:57 UTC (rev 1691)
@@ -47,8 +47,8 @@
 static void
 save_song_thumbnails (Itdb_Track *song)
 {
+        static gint count = 0;
        GList *it;
-       
        for (it = song->artwork->thumbnails; it != NULL; it = it->next) {
                Itdb_Thumb *thumb;
                gchar *filename;
@@ -57,7 +57,8 @@
                g_return_if_fail (thumb);
 
                filename = NULL;
-               filename = g_strdup_printf 
("%s-%s-%s-%d-%016"G_GINT64_MODIFIER"x.png",
+               filename = g_strdup_printf 
("%03d_%s-%s-%s-%d-%016"G_GINT64_MODIFIER"x.png",
+                                           count++,
                                            song->artist, song->album, 
                                            song->title, thumb->type, 
                                            song->dbid);


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
gtkpod-cvs2 mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gtkpod-cvs2

Reply via email to