Author: abrander
Date: 2009-09-23 17:14:46 +0200 (Wed, 23 Sep 2009)
New Revision: 2653

Added:
   trunk/librawstudio/rs-tiff-ifd-entry.c
   trunk/librawstudio/rs-tiff-ifd-entry.h
   trunk/librawstudio/rs-tiff-ifd.c
   trunk/librawstudio/rs-tiff-ifd.h
   trunk/librawstudio/rs-tiff.c
   trunk/librawstudio/rs-tiff.h
Modified:
   trunk/librawstudio/Makefile.am
   trunk/librawstudio/rawstudio.h
Log:
Added simple generic TIFF parser to librawstudio.

Modified: trunk/librawstudio/Makefile.am
===================================================================
--- trunk/librawstudio/Makefile.am      2009-09-23 15:12:09 UTC (rev 2652)
+++ trunk/librawstudio/Makefile.am      2009-09-23 15:14:46 UTC (rev 2653)
@@ -34,6 +34,9 @@
        rs-spline.h \
        rs-curve.h \
        rs-stock.h \
+       rs-tiff.h \
+       rs-tiff-ifd.h \
+       rs-tiff-ifd-entry.h \
        x86-cpu.h
 
 lib_LTLIBRARIES = librawstudio-1.1.la
@@ -62,6 +65,9 @@
        rs-color-transform.c rs-color-transform.h \
        rs-spline.c rs-spline.h \
        rs-curve.c rs-curve.h \
+       rs-tiff.c rs-tiff.h \
+       rs-tiff-ifd.c rs-tiff-ifd.h \
+       rs-tiff-ifd-entry.c rs-tiff-ifd-entry.h \
        rs-stock.c rs-stock.h
 
 librawstudio_1_1_la_LIBADD = @PACKAGE_LIBS@ @LIBJPEG@ @LIBTIFF@ $(INTLLIBS)

Modified: trunk/librawstudio/rawstudio.h
===================================================================
--- trunk/librawstudio/rawstudio.h      2009-09-23 15:12:09 UTC (rev 2652)
+++ trunk/librawstudio/rawstudio.h      2009-09-23 15:14:46 UTC (rev 2653)
@@ -55,6 +55,9 @@
 #include "rs-spline.h"
 #include "rs-curve.h"
 #include "rs-stock.h"
+#include "rs-tiff-ifd-entry.h"
+#include "rs-tiff-ifd.h"
+#include "rs-tiff.h"
 
 #include "x86-cpu.h"
 

Added: trunk/librawstudio/rs-tiff-ifd-entry.c
===================================================================
--- trunk/librawstudio/rs-tiff-ifd-entry.c                              (rev 0)
+++ trunk/librawstudio/rs-tiff-ifd-entry.c      2009-09-23 15:14:46 UTC (rev 
2653)
@@ -0,0 +1,230 @@
+#include "rs-tiff-ifd-entry.h"
+
+G_DEFINE_TYPE (RSTiffIfdEntry, rs_tiff_ifd_entry, G_TYPE_OBJECT)
+
+static const struct {
+       gushort tag;
+       const char *description;
+} tiff_tags[] = {
+       { 0x00fe, "NewSubfileType" },
+       { 0x00ff, "SubfileType" },
+       { 0x0100, "ImageWidth" },
+       { 0x0101, "ImageLength" },
+       { 0x0102, "BitsPerSample" },
+       { 0x0103, "Compression" },
+       { 0x0106, "PhotometricInterpretation" },
+       { 0x0107, "Threshholding" },
+       { 0x0108, "CellWidth" },
+       { 0x0109, "CellLength" },
+       { 0x0100, "ImageWidth" },
+       { 0x010a, "FillOrder" },
+       { 0x010d, "DocumentName" },
+       { 0x010e, "ImageDescription" },
+       { 0x010f, "Make" },
+       { 0x0110, "Model" },
+       { 0x0111, "StripOffsets" },
+       { 0x0112, "Orientation" },
+       { 0x0115, "SamplesPerPixel" },
+       { 0x0116, "RowsPerStrip" },
+       { 0x0117, "StripByteCounts" },
+       { 0x0118, "MinSampleValue" },
+       { 0x0119, "MaxSampleValue" },
+       { 0x011a, "XResolution" },
+       { 0x011b, "YResolution" },
+       { 0x011c, "PlanarConfiguration" },
+       { 0x011d, "PageName" },
+       { 0x011e, "XPosition" },
+       { 0x011f, "YPosition" },
+       { 0x0120, "FreeOffsets" },
+       { 0x0121, "FreeByteCounts" },
+       { 0x0122, "GrayResponseUnit" },
+       { 0x0123, "GrayResponseCurve" },
+       { 0x0124, "T4Options" },
+       { 0x0125, "T6Options" },
+       { 0x0128, "ResolutionUnit" },
+       { 0x0129, "PageNumber" },
+       { 0x012d, "TransferFunction" },
+       { 0x0131, "Software" },
+       { 0x0132, "DateTime" },
+       { 0x013b, "Artist" },
+       { 0x013c, "HostComputer" },
+       { 0x013d, "Predictor" },
+       { 0x013e, "WhitePoint" },
+       { 0x013f, "PrimaryChromaticities" },
+       { 0x0140, "ColorMap" },
+       { 0x0141, "HalftoneHints" },
+       { 0x0142, "TileWidth" },
+       { 0x0143, "TileLength" },
+       { 0x0144, "TileOffsets" },
+       { 0x0145, "TileByteCounts" },
+       { 0x014c, "InkSet" },
+       { 0x014d, "InkNames" },
+       { 0x014e, "NumberOfInks" },
+       { 0x0200, "JPEGProc" },
+       { 0x0201, "JPEGInterchangeFormat" },
+       { 0x0202, "JPEGInterchangeFormatLength" },
+       { 0x0203, "JPEGRestartInterval" },
+       { 0x0205, "JPEGLosslessPredictors" },
+       { 0x0206, "JPEGPointTransforms" },
+       { 0x0207, "JPEGQTables" },
+       { 0x0208, "JPEGDCTables" },
+       { 0x0209, "JPEGACTables" },
+       { 0x0211, "YCbCrCoefficients" },
+       { 0x0212, "YCbCrSubSampling" },
+       { 0x0213, "YCbCrPositioning" },
+       { 0x0214, "ReferenceBlackWhite" },
+       { 0x0150, "DotRange" },
+       { 0x0151, "TargetPrinter" },
+       { 0x0152, "ExtraSamples" },
+       { 0x0153, "SampleFormat" },
+       { 0x0154, "SMinSampleValue" },
+       { 0x0155, "SMaxSampleValue" },
+       { 0x0156, "TransferRange" },
+       { 0x8298, "Copyright" },
+       /* EXIF specifics */
+       { 0x8769, "Exif IFD Pointer" },
+       { 0x8825, "GPS Info IFD Pointer" },
+       /* DNG tags */
+       { 0xc612, "DNGVersion" },
+       { 0xc613, "DNGBackwardVersion" },
+       { 0xc614, "UniqueCameraModel" },
+       { 0xc615, "LocalizedCameraModel" },
+       { 0xc616, "CFAPlaneColor" },
+       { 0xc617, "CFALayout" },
+       { 0xc618, "LinearizationTable" },
+       { 0xc619, "BlackLevelRepeatDim" },
+       { 0xc61a, "BlackLevel" },
+       { 0xc61b, "BlackLevelDeltaH" },
+       { 0xc61c, "BlackLevelDeltaV" },
+       { 0xc61d, "WhiteLevel" },
+       { 0xc61e, "DefaultScale" },
+       { 0xc61f, "DefaultCropOrigin" },
+       { 0xc620, "DefaultCropSize" },
+       { 0xc621, "ColorMatrix1" },
+       { 0xc622, "ColorMatrix2" },
+       { 0xc623, "CameraCalibration1" },
+       { 0xc624, "CameraCalibration2" },
+       { 0xc625, "ReductionMatrix1" },
+       { 0xc626, "ReductionMatrix2" },
+       { 0xc627, "AnalogBalance" },
+       { 0xc628, "AsShotNeutral" },
+       { 0xc629, "AsShotWhiteXY" },
+       { 0xc62a, "BaselineExposure" },
+       { 0xc62b, "BaselineNoise" },
+       { 0xc62c, "BaselineSharpness" },
+       { 0xc62d, "BayerGreenSplit" },
+       { 0xc62e, "LinearResponseLimit" },
+       { 0xc62f, "CameraSerialNumber" },
+       { 0xc630, "LensInfo" },
+       { 0xc631, "ChromaBlurRadius" },
+       { 0xc632, "AntiAliasStrength" },
+       { 0xc633, "ShadowScale" },
+       { 0xc634, "DNGPrivateData" },
+       { 0xc635, "MakerNoteSafety" },
+       { 0xc65a, "CalibrationIlluminant1" },
+       { 0xc65b, "CalibrationIlluminant2" },
+       { 0xc65c, "BestQualityScale" },
+       { 0xc65d, "RawDataUniqueID" },
+       { 0xc68b, "OriginalRawFileName" },
+       { 0xc68c, "OriginalRawFileData" },
+       { 0xc68d, "ActiveArea" },
+       { 0xc68e, "MaskedAreas" },
+       { 0xc68f, "AsShotICCProfile" },
+       { 0xc690, "AsShotPreProfileMatrix" },
+       { 0xc691, "CurrentICCProfile" },
+       { 0xc692, "CurrentPreProfileMatrix" },
+       { 0xc6bf, "ColorimetricReference" },
+       { 0xc6f3, "CameraCalibrationSignature" },
+       { 0xc6f4, "ProfileCalibrationSignature" },
+       { 0xc6f5, "ExtraCameraProfiles" },
+       { 0xc6f6, "AsShotProfileName" },
+       { 0xc6f7, "NoiseReductionApplied" },
+       { 0xc6f8, "ProfileName" },
+       { 0xc6f9, "ProfileHueSatMapDims" },
+       { 0xc6fa, "ProfileHueSatMapData1" },
+       { 0xc6fb, "ProfileHueSatMapData2" },
+       { 0xc6fc, "ProfileToneCurve" },
+       { 0xc6fd, "ProfileEmbedPolicy" },
+       { 0xc6fe, "ProfileCopyright" },
+       { 0xc714, "ForwardMatrix1" },
+       { 0xc715, "ForwardMatrix2" },
+       { 0xc716, "PreviewApplicationName" },
+       { 0xc717, "PreviewApplicationVersion" },
+       { 0xc718, "PreviewSettingsName" },
+       { 0xc719, "PreviewSettingsDigest" },
+       { 0xc71a, "PreviewColorSpace" },
+       { 0xc71b, "PreviewDateTime" },
+       { 0xc71c, "RawImageDigest" },
+       { 0xc71d, "OriginalRawFileDigest" },
+       { 0xc71e, "SubTileBlockSize" },
+       { 0xc71f, "RowInterleaveFactor" },
+       { 0xc725, "ProfileLookTableDims" },
+       { 0xc726, "ProfileLookTableData" },
+       { 0xc740, "OpcodeList1" },
+       { 0xc741, "OpcodeList2" },
+       { 0xc74e, "OpcodeList3" },
+       { 0xc761, "NoiseProfile" },
+       { 0x0, NULL }
+};
+
+static void
+rs_tiff_ifd_entry_get_property(GObject *object, guint property_id, GValue 
*value, GParamSpec *pspec)
+{
+       switch (property_id)
+       {
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, 
pspec);
+       }
+}
+
+static void
+rs_tiff_ifd_entry_set_property(GObject *object, guint property_id, const 
GValue *value, GParamSpec *pspec)
+{
+       switch (property_id)
+       {
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, 
pspec);
+       }
+}
+
+static void
+rs_tiff_ifd_entry_dispose(GObject *object)
+{
+       G_OBJECT_CLASS(rs_tiff_ifd_entry_parent_class)->dispose (object);
+}
+
+static void
+rs_tiff_ifd_entry_finalize(GObject *object)
+{
+       G_OBJECT_CLASS(rs_tiff_ifd_entry_parent_class)->finalize (object);
+}
+
+static void
+rs_tiff_ifd_entry_class_init(RSTiffIfdEntryClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+       object_class->get_property = rs_tiff_ifd_entry_get_property;
+       object_class->set_property = rs_tiff_ifd_entry_set_property;
+       object_class->dispose = rs_tiff_ifd_entry_dispose;
+       object_class->finalize = rs_tiff_ifd_entry_finalize;
+}
+
+static void
+rs_tiff_ifd_entry_init(RSTiffIfdEntry *self)
+{
+}
+
+RSTiffIfdEntry *
+rs_tiff_ifd_entry_new(RSTiff *tiff, guint offset)
+{
+       gint i;
+       RSTiffIfdEntry *entry = g_object_new(RS_TYPE_TIFF_IFD_ENTRY, NULL);
+
+       entry->tag = rs_tiff_get_ushort(tiff, offset+0);
+       entry->type = rs_tiff_get_ushort(tiff, offset+2);
+       entry->count = rs_tiff_get_uint(tiff, offset+4);
+       entry->value_offset = rs_tiff_get_uint(tiff, offset+8);
+
+       return entry;
+}

Added: trunk/librawstudio/rs-tiff-ifd-entry.h
===================================================================
--- trunk/librawstudio/rs-tiff-ifd-entry.h                              (rev 0)
+++ trunk/librawstudio/rs-tiff-ifd-entry.h      2009-09-23 15:14:46 UTC (rev 
2653)
@@ -0,0 +1,36 @@
+#ifndef RS_TIFF_IFD_ENTRY_H
+#define RS_TIFF_IFD_ENTRY_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define RS_TYPE_TIFF_IFD_ENTRY rs_tiff_ifd_entry_get_type()
+#define RS_TIFF_IFD_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
RS_TYPE_TIFF_IFD_ENTRY, RSTiffIfdEntry))
+#define RS_TIFF_IFD_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), 
RS_TYPE_TIFF_IFD_ENTRY, RSTiffIfdEntryClass))
+#define RS_IS_TIFF_IFD_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
RS_TYPE_TIFF_IFD_ENTRY))
+#define RS_IS_TIFF_IFD_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), 
RS_TYPE_TIFF_IFD_ENTRY))
+#define RS_TIFF_IFD_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), 
RS_TYPE_TIFF_IFD_ENTRY, RSTiffIfdEntryClass))
+
+typedef struct {
+       GObject parent;
+
+       gushort tag;
+       gushort type;
+       guint count;
+       guint value_offset;
+} RSTiffIfdEntry;
+
+typedef struct {
+       GObjectClass parent_class;
+} RSTiffIfdEntryClass;
+
+#include <rawstudio.h>
+
+GType rs_tiff_ifd_entry_get_type(void);
+
+RSTiffIfdEntry *rs_tiff_ifd_entry_new(RSTiff *tiff, guint offset);
+
+G_END_DECLS
+
+#endif /* RS_TIFF_IFD_ENTRY_H */

Added: trunk/librawstudio/rs-tiff-ifd.c
===================================================================
--- trunk/librawstudio/rs-tiff-ifd.c                            (rev 0)
+++ trunk/librawstudio/rs-tiff-ifd.c    2009-09-23 15:14:46 UTC (rev 2653)
@@ -0,0 +1,158 @@
+#include <rawstudio.h>
+#include "rs-tiff-ifd.h"
+
+G_DEFINE_TYPE (RSTiffIfd, rs_tiff_ifd, G_TYPE_OBJECT)
+
+static void read(RSTiffIfd *ifd);
+
+enum {
+       PROP_0,
+       PROP_TIFF,
+       PROP_OFFSET,
+       PROP_NEXT_IFD,
+};
+
+static void
+rs_tiff_ifd_get_property (GObject *object, guint property_id, GValue *value, 
GParamSpec *pspec)
+{
+       RSTiffIfd *ifd = RS_TIFF_IFD(object);
+
+       switch (property_id)
+       {
+               case PROP_NEXT_IFD:
+                       g_value_set_uint(value, ifd->next_ifd);
+                       break;
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, 
pspec);
+       }
+}
+
+static void
+rs_tiff_ifd_set_property(GObject *object, guint property_id, const GValue 
*value, GParamSpec *pspec)
+{
+       RSTiffIfd *ifd = RS_TIFF_IFD(object);
+
+       switch (property_id)
+       {
+               case PROP_TIFF:
+                       ifd->tiff = g_object_ref(g_value_get_object(value));
+                       if (ifd->tiff && ifd->offset)
+                               RS_TIFF_IFD_GET_CLASS(ifd)->read(ifd);
+                       break;
+               case PROP_OFFSET:
+                       ifd->offset = g_value_get_uint(value);
+                       if (ifd->tiff && ifd->offset)
+                               RS_TIFF_IFD_GET_CLASS(ifd)->read(ifd);
+                       break;
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, 
pspec);
+       }
+}
+
+static void
+rs_tiff_ifd_dispose(GObject *object)
+{
+       RSTiffIfd *ifd = RS_TIFF_IFD(object);
+
+       if (!ifd->dispose_has_run)
+       {
+               ifd->dispose_has_run = TRUE;
+               g_object_unref(ifd->tiff);
+       }
+
+       G_OBJECT_CLASS(rs_tiff_ifd_parent_class)->dispose (object);
+}
+
+static void
+rs_tiff_ifd_finalize(GObject *object)
+{
+       G_OBJECT_CLASS(rs_tiff_ifd_parent_class)->finalize (object);
+}
+
+static void
+rs_tiff_ifd_class_init(RSTiffIfdClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+       object_class->get_property = rs_tiff_ifd_get_property;
+       object_class->set_property = rs_tiff_ifd_set_property;
+       object_class->dispose = rs_tiff_ifd_dispose;
+       object_class->finalize = rs_tiff_ifd_finalize;
+
+       g_object_class_install_property(object_class,
+               PROP_TIFF, g_param_spec_object(
+                       "tiff", "tiff", "The RSTiff associated with the 
RSTiffIfd",
+                       RS_TYPE_TIFF, G_PARAM_CONSTRUCT_ONLY | 
G_PARAM_WRITABLE));
+
+       g_object_class_install_property(object_class,
+               PROP_OFFSET, g_param_spec_uint(
+                       "offset", "offset", "IFD offset",
+                       0, G_MAXUINT, 0, G_PARAM_CONSTRUCT_ONLY | 
G_PARAM_WRITABLE));
+
+       g_object_class_install_property(object_class,
+               PROP_NEXT_IFD, g_param_spec_uint(
+                       "next-ifd", "next-ifd", "Offset for next ifd",
+                       0, G_MAXUINT, 0, G_PARAM_READABLE));
+
+       klass->read = read;
+}
+
+static void
+rs_tiff_ifd_init(RSTiffIfd *self)
+{
+}
+
+RSTiffIfd *
+rs_tiff_ifd_new(RSTiff *tiff, guint offset)
+{
+       g_assert(RS_IS_TIFF(tiff));
+
+       return g_object_new(RS_TYPE_TIFF_IFD, "tiff", tiff, "offset", offset, 
NULL);
+}
+
+guint
+rs_tiff_ifd_get_next(RSTiffIfd *ifd)
+{
+       g_assert(RS_IS_TIFF_IFD(ifd));
+
+       return ifd->next_ifd;
+}
+
+static void
+read(RSTiffIfd *ifd)
+{
+       gint i;
+
+       ifd->num_entries = rs_tiff_get_ushort(ifd->tiff, ifd->offset);
+       ifd->next_ifd = rs_tiff_get_uint(ifd->tiff, ifd->offset + 2 + 
ifd->num_entries*12);
+
+       if (ifd->next_ifd == ifd->offset)
+               ifd->next_ifd = 0;
+       else if (ifd->next_ifd > (ifd->tiff->map_length-12))
+               ifd->next_ifd = 0;
+
+       /* Read all entries */
+       for(i=0;i<ifd->num_entries;i++)
+               ifd->entries = g_list_append(ifd->entries, 
rs_tiff_ifd_entry_new(ifd->tiff, ifd->offset + 2 + i * 12));
+}
+
+static gint
+_tag_search(RSTiffIfdEntry *entry, gushort tag)
+{
+       return entry->tag - tag;
+}
+
+RSTiffIfdEntry *
+rs_tiff_ifd_get_entry_by_tag(RSTiffIfd *ifd, gushort tag)
+{
+       g_assert(RS_IS_TIFF_IFD(ifd));
+       GList *found;
+       RSTiffIfdEntry *ret = NULL;
+
+       found = g_list_find_custom(ifd->entries, GUINT_TO_POINTER(tag), 
(GCompareFunc) _tag_search);
+
+       if (found)
+               ret = g_object_ref(found->data);
+
+       return ret;
+}

Added: trunk/librawstudio/rs-tiff-ifd.h
===================================================================
--- trunk/librawstudio/rs-tiff-ifd.h                            (rev 0)
+++ trunk/librawstudio/rs-tiff-ifd.h    2009-09-23 15:14:46 UTC (rev 2653)
@@ -0,0 +1,43 @@
+#ifndef RS_TIFF_IFD_H
+#define RS_TIFF_IFD_H
+
+#include <glib-object.h>
+#include "rs-tiff.h"
+
+G_BEGIN_DECLS
+
+#define RS_TYPE_TIFF_IFD rs_tiff_ifd_get_type()
+#define RS_TIFF_IFD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RS_TYPE_TIFF_IFD, 
RSTiffIfd))
+#define RS_TIFF_IFD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), 
RS_TYPE_TIFF_IFD, RSTiffIfdClass))
+#define RS_IS_TIFF_IFD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
RS_TYPE_TIFF_IFD))
+#define RS_IS_TIFF_IFD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), 
RS_TYPE_TIFF_IFD))
+#define RS_TIFF_IFD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), 
RS_TYPE_TIFF_IFD, RSTiffIfdClass))
+
+typedef struct {
+       GObject parent;
+
+       gboolean dispose_has_run;
+
+       RSTiff *tiff;
+       guint offset;
+
+       gushort num_entries;
+       GList *entries;
+       guint next_ifd;
+} RSTiffIfd;
+
+typedef struct {
+       GObjectClass parent_class;
+
+       void (*read)(RSTiffIfd *ifd);
+} RSTiffIfdClass;
+
+GType rs_tiff_ifd_get_type(void);
+
+RSTiffIfd *rs_tiff_ifd_new(RSTiff *tiff, guint offset);
+
+RSTiffIfdEntry *rs_tiff_ifd_get_entry_by_tag(RSTiffIfd *ifd, gushort tag);
+
+G_END_DECLS
+
+#endif /* RS_TIFF_IFD_H */

Added: trunk/librawstudio/rs-tiff.c
===================================================================
--- trunk/librawstudio/rs-tiff.c                                (rev 0)
+++ trunk/librawstudio/rs-tiff.c        2009-09-23 15:14:46 UTC (rev 2653)
@@ -0,0 +1,170 @@
+#include <rawstudio.h>
+#include <sys/stat.h>
+#include "rs-tiff.h"
+
+G_DEFINE_TYPE (RSTiff, rs_tiff, G_TYPE_OBJECT)
+
+static gboolean read_image_file_header(RSTiff *tiff);
+static gboolean read_from_file(RSTiff *tiff);
+
+enum {
+       PROP_0,
+       PROP_FILENAME,
+};
+
+static void
+rs_tiff_get_property(GObject *object, guint property_id, GValue *value, 
GParamSpec *pspec)
+{
+       RSTiff *tiff = RS_TIFF(object);
+
+       switch (property_id)
+       {
+               case PROP_FILENAME:
+                       g_value_set_string(value, tiff->filename);
+                       break;
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, 
pspec);
+       }
+}
+
+static void
+rs_tiff_set_property(GObject *object, guint property_id, const GValue *value, 
GParamSpec *pspec)
+{
+       RSTiff *tiff = RS_TIFF(object);
+
+       switch (property_id)
+       {
+               case PROP_FILENAME:
+                       tiff->filename = g_value_dup_string(value);
+                       read_from_file(tiff);
+                       break;
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, 
pspec);
+       }
+}
+
+static void
+rs_tiff_dispose(GObject *object)
+{
+       RSTiff *tiff = RS_TIFF(object);
+
+       if (!tiff->dispose_has_run)
+       {
+               tiff->dispose_has_run = TRUE;
+               g_free(tiff->map);
+       }
+
+       G_OBJECT_CLASS(rs_tiff_parent_class)->dispose(object);
+}
+
+static void
+rs_tiff_finalize(GObject *object)
+{
+       G_OBJECT_CLASS(rs_tiff_parent_class)->finalize(object);
+}
+
+static void
+rs_tiff_class_init(RSTiffClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+       object_class->get_property = rs_tiff_get_property;
+       object_class->set_property = rs_tiff_set_property;
+       object_class->dispose = rs_tiff_dispose;
+       object_class->finalize = rs_tiff_finalize;
+
+       g_object_class_install_property(object_class,
+               PROP_FILENAME, g_param_spec_string(
+                       "filename", "Filename", "The filename to load",
+                       NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
+
+       klass->read_image_file_header = read_image_file_header;
+}
+
+static void
+rs_tiff_init(RSTiff *self)
+{
+}
+
+static gboolean
+read_image_file_header(RSTiff *tiff)
+{
+       gboolean ret = TRUE;
+       guint next_ifd;
+
+       /* Read endianness */
+       if ((tiff->map[0] == 'I') && (tiff->map[1] == 'I'))
+               tiff->byte_order = G_LITTLE_ENDIAN;
+       else if ((tiff->map[0] == 'M') && (tiff->map[1] == 'M'))
+               tiff->byte_order = G_BIG_ENDIAN;
+       else /* Not a TIFF file */
+               ret = FALSE;
+
+       /* Read TIFF identifier */
+       if (rs_tiff_get_ushort(tiff, 2) != 42)
+               ret = FALSE;
+
+       tiff->first_ifd_offset = rs_tiff_get_uint(tiff, 4);
+
+       next_ifd = tiff->first_ifd_offset;
+       while(next_ifd)
+       {
+               tiff->num_ifd++;
+               RSTiffIfd *ifd = rs_tiff_ifd_new(tiff, next_ifd);
+               if (ifd)
+               {
+                       tiff->ifds = g_list_append(tiff->ifds, ifd);
+                       next_ifd = rs_tiff_ifd_get_next(ifd);
+               }
+               else
+                       break;
+       }
+
+       return TRUE;
+}
+
+static RSTiff *
+rs_tiff_new(void)
+{
+       return g_object_new(RS_TYPE_TIFF, NULL);
+}
+
+static gboolean
+read_from_file(RSTiff *tiff)
+{
+       gboolean ret = TRUE;
+       GError *error = NULL;
+
+       g_file_get_contents(tiff->filename, (gchar **)&tiff->map, 
&tiff->map_length, &error);
+
+       if (error)
+       {
+               g_warning("GError: '%s'", error->message);
+               g_error_free(error);
+               ret = FALSE;
+       }
+
+       return RS_TIFF_GET_CLASS(tiff)->read_image_file_header(tiff);
+}
+
+RSTiff *
+rs_tiff_new_from_file(const gchar *filename)
+{
+       return g_object_new(RS_TYPE_TIFF, "filename", filename, NULL);
+}
+
+RSTiffIfdEntry *
+rs_tiff_get_ifd_entry(RSTiff *tiff, guint ifd_num, gushort tag)
+{
+       RSTiffIfd *ifd = NULL;
+       RSTiffIfdEntry *ret = NULL;
+       g_assert(RS_IS_TIFF(tiff));
+
+       if (ifd_num <= tiff->num_ifd)
+               ifd = g_list_nth_data(tiff->ifds, ifd_num);
+
+       if (ifd)
+               ret = rs_tiff_ifd_get_entry_by_tag(ifd, tag);
+
+       return ret;
+}

Added: trunk/librawstudio/rs-tiff.h
===================================================================
--- trunk/librawstudio/rs-tiff.h                                (rev 0)
+++ trunk/librawstudio/rs-tiff.h        2009-09-23 15:14:46 UTC (rev 2653)
@@ -0,0 +1,61 @@
+#ifndef RS_TIFF_H
+#define RS_TIFF_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define RS_TYPE_TIFF rs_tiff_get_type()
+#define RS_TIFF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RS_TYPE_TIFF, RSTiff))
+#define RS_TIFF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), RS_TYPE_TIFF, 
RSTiffClass))
+#define RS_IS_TIFF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RS_TYPE_TIFF))
+#define RS_IS_TIFF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), 
RS_TYPE_TIFF))
+#define RS_TIFF_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), 
RS_TYPE_TIFF, RSTiffClass))
+
+/* Macros to read from TIFF files */
+#define __rs_cast(x, type) (*((type*)(&(x))))
+
+#define rs_tiff_get_generic(tiff, pos, TYPE, type) ( \
+       ((tiff)->map_length >= ((pos)+sizeof(type))) \
+       ? \
+       ( \
+               ((tiff)->byte_order == G_LITTLE_ENDIAN) \
+               ? (TYPE##_FROM_LE(__rs_cast((tiff)->map[(pos)], type))) \
+               : (TYPE##_FROM_BE(__rs_cast((tiff)->map[(pos)], type))) \
+       ) \
+       : 0 \
+)
+
+#define rs_tiff_get_simple(tiff, pos, type) ( \
+       ((pos) <= ((tiff)->map_length-sizeof(type))) \
+       ? __rs_cast((tiff)->map[(pos)], type) \
+       : 0 \
+)
+
+#define rs_tiff_get_uchar(tiff, pos) rs_tiff_get_simple(tiff, pos, guchar)
+#define rs_tiff_get_ushort(tiff, pos) rs_tiff_get_generic(tiff, pos, GUINT16, 
guint16)
+#define rs_tiff_get_uint(tiff, pos) rs_tiff_get_generic(tiff, pos, GUINT32, 
guint32)
+#define rs_tiff_get_urational(tiff, pos) ((gfloat) rs_tiff_get_uint(tiff, 
pos)) / ((gfloat) rs_tiff_get_uint(tiff, pos+sizeof(guint)))
+#define rs_tiff_get_char(tiff, pos) rs_tiff_get_simple(tiff, pos, gchar)
+#define rs_tiff_get_short(tiff, pos) rs_tiff_get_generic(tiff, pos, GINT16, 
gshort)
+#define rs_tiff_get_int(tiff, pos) rs_tiff_get_generic(tiff, pos, GINT32, gint)
+#define rs_tiff_get_rational(tiff, pos) ((gfloat) rs_tiff_get_int(tiff, pos)) 
/ ((gfloat) ((rs_tiff_get_int(tiff, pos+sizeof(gint)) == 0) ? 1 : 
rs_tiff_get_int(tiff, pos+sizeof(gint))))
+#define rs_tiff_get_float(tiff, pos) rs_tiff_get_simple(tiff, pos, gfloat)
+#define rs_tiff_get_double(tiff, pos) rs_tiff_get_simple(tiff, pos, gdouble)
+
+typedef struct {
+       GObjectClass parent_class;
+
+       gboolean (*read_image_file_header)(RSTiff *tiff);
+} RSTiffClass;
+
+GType rs_tiff_get_type(void);
+
+RSTiff *rs_tiff_new_from_file(const gchar *filename);
+
+RSTiffIfdEntry *
+rs_tiff_get_ifd_entry(RSTiff *tiff, guint ifd_num, gushort tag);
+
+G_END_DECLS
+
+#endif /* RS_TIFF_H */


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

Reply via email to