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