Author: post
Date: 2010-10-17 13:34:48 +0200 (Sun, 17 Oct 2010)
New Revision: 3567

Modified:
   trunk/plugins/meta-tiff/tiff-meta.c
Log:
Panasonic: Read makernote (usually include lens name) & load JPEG image for 
icon.

Modified: trunk/plugins/meta-tiff/tiff-meta.c
===================================================================
--- trunk/plugins/meta-tiff/tiff-meta.c 2010-10-16 15:25:06 UTC (rev 3566)
+++ trunk/plugins/meta-tiff/tiff-meta.c 2010-10-17 11:34:48 UTC (rev 3567)
@@ -976,10 +976,78 @@
 }
 
 static gboolean
+makernote_panasonic(RAWFILE *rawfile, guint offset, RSMetadata *meta)
+{
+       gushort number_of_entries;
+       struct IFD ifd;
+       if(!raw_get_ushort(rawfile, offset, &number_of_entries))
+       return FALSE;
+
+       if (number_of_entries>5000)
+               return FALSE;
+
+       offset += 2;
+
+       while(number_of_entries--)
+       {
+               read_ifd(rawfile, offset, &ifd);
+               offset += 12;
+               switch(ifd.tag)
+               {
+                       case 81: /* Lens type */
+                               meta->lens_identifier = raw_strdup(rawfile, 
ifd.value_offset, ifd.count);
+                               break;
+                       case 82: /* Lens serial number */
+                               if (!meta->lens_identifier)
+                                       meta->lens_identifier = 
raw_strdup(rawfile, ifd.value_offset, ifd.count);
+                               break;
+                       case 0x8769: /* ExifIFDPointer */
+                               exif_reader(rawfile, ifd.value_offset, meta);
+                               break;
+                       case 0x0111: /* StripOffsets - may be jpeg data */
+                               if (ifd.count == 1 && raw_get_uint(rawfile, 
ifd.offset, &meta->thumbnail_start))
+                                       meta->thumbnail_start += 
raw_get_base(rawfile);
+                               else
+                                       meta->thumbnail_start = 0;
+                               break;
+                       case 0x0117: /* StripByteCounts */
+                               if (ifd.value_offset)
+                                       meta->thumbnail_length = 
ifd.value_offset;
+                               break;
+               }
+       }
+       return TRUE;
+}
+
+static gboolean
+likely_jpeg_at(RAWFILE *rawfile, guint offset)
+{
+       guchar thumb_test_1 = 0;
+       guchar thumb_test_2 = 0;
+       guchar thumb_test_comps = 0;
+
+       if (raw_get_uchar(rawfile, offset, &thumb_test_1))
+       {
+               /* If SOI marker, it is likely valid JPEG*/
+               if (thumb_test_1 == 0xff && raw_get_uchar(rawfile, offset+1, 
&thumb_test_2))
+                       if (thumb_test_2 == 0xd8)
+                               /* We read the "number of components", any 
value > 4 doesn't make sense */
+                               if (raw_get_uchar(rawfile, offset+6, 
&thumb_test_comps))
+                                       if (thumb_test_comps <= 4)
+                                               return TRUE;
+       }
+       return FALSE;
+}
+
+
+static gboolean
 ifd_panasonic(RAWFILE *rawfile, guint offset, RSMetadata *meta)
 {
        gushort number_of_entries;
        struct IFD ifd;
+       RAWFILE *internal_file;
+       guint off_first;
+       gushort byteorder;
 
        if(!raw_get_ushort(rawfile, offset, &number_of_entries))
                return FALSE;
@@ -993,7 +1061,6 @@
        {
                read_ifd(rawfile, offset, &ifd);
                offset += 12;
-
                switch(ifd.tag)
                {
                        case 0x0017: /* ISO */
@@ -1009,16 +1076,43 @@
                        case 0x0026: /* WBBlueLevel */
                                meta->cam_mul[2] = ifd.value_offset;
                                break;
-                       case 0x002e: /* PreviewImage */
-                               meta->preview_start = ifd.value_offset;
-                               meta->preview_length = ifd.count;
+                       case 0x002e: /* Data Dump */
+                               if (ifd.type != 7 || ifd.count <= 16)
+                                       break;
+                               if (!raw_get_uint(rawfile, 
ifd.value_offset+12+4, &off_first))
+                                       break;
+                               if 
(!raw_get_ushort(rawfile,ifd.value_offset+12, &byteorder))
+                                       break;
+                               meta->thumbnail_length = ifd.count;
+                               internal_file = 
raw_create_from_memory(raw_get_map(rawfile)+ifd.value_offset+12, ifd.count, 
off_first, byteorder);
+                               ifd_reader(internal_file, off_first, meta);
+                               raw_close_file(internal_file);
                                break;
-                       case 0x8769: /* ExifIFDPointer */
-                               exif_reader(rawfile, ifd.value_offset, meta);
-                               break;
                }
        }
+       if (meta->thumbnail_start > raw_get_filesize(rawfile))
+               meta->thumbnail_start = 0;
+       if (!likely_jpeg_at(rawfile, meta->thumbnail_start))
+               meta->thumbnail_start = 0;
 
+       guint thumb_guess =0x1000;
+       /* Thumbnails in Panasonic are always at 0x100 byte boundaries, and 
never observed start after byte 0x3000, so we play safe */
+       while (meta->thumbnail_start == 0 && thumb_guess < 0x8000)
+       {
+               if (likely_jpeg_at(rawfile, thumb_guess))
+                       meta->thumbnail_start = thumb_guess;
+               thumb_guess += 0x100;
+       }
+       /* Find end of image */
+       if (meta->thumbnail_start)
+       {
+               thumb_guess = 0;
+               guchar* image = raw_get_map(rawfile) + meta->thumbnail_start;
+               do {
+                       if (image[thumb_guess] == 0xff && image[thumb_guess] == 
0xd9)
+                               meta->thumbnail_length = thumb_guess+2;
+               } while (thumb_guess++ < raw_get_filesize(rawfile) - 
meta->thumbnail_start);
+       }
        return TRUE;
 }
 
@@ -1266,6 +1360,10 @@
                                        case MAKE_SONY:
                                                makernote_sony(rawfile, 
ifd.value_offset, meta);
                                                break;
+                                       case MAKE_PANASONIC:
+                                               if (raw_strcmp(rawfile, 
ifd.value_offset, "Panasonic", 9))
+                                                       
makernote_panasonic(rawfile, ifd.value_offset+12, meta);
+                                               break;
                                        default:
                                                break;
                                }
@@ -1364,6 +1462,10 @@
                case MAKE_SONY:
                        makernote_sony(maker_raw, org_offset, meta);
                        break;
+               case MAKE_PANASONIC:
+                       if (raw_strcmp(maker_raw, org_offset, "Panasonic", 9))
+                               makernote_panasonic(maker_raw, org_offset+12, 
meta);
+                       break;
                default:
                        break;
        }
@@ -1654,11 +1756,6 @@
                                /* Try to guess file format based on contents 
(JPEG previews) */
                        pixbuf = raw_get_pixbuf(rawfile, offset, length);
        }
-       /* Special case for Panasonic - most have no embedded thumbnail */
-       else if (meta->make == MAKE_PANASONIC)
-       {
-               pixbuf = raw_thumbnail_reader(service, meta);
-       }
        if ( pixbuf && (gdk_pixbuf_get_width(pixbuf) < 10 || 
gdk_pixbuf_get_height(pixbuf) < 10))
                pixbuf = NULL;
 


_______________________________________________
Rawstudio-commit mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit

Reply via email to