On date Wednesday 2011-11-02 21:22:41 +0100, Thomas Kühnel encoded:
> On 27.10.2011 23:44, Stefano Sabatini wrote:
> >On date Sunday 2011-10-23 22:12:01 +0200, Thomas Kühnel encoded:
> >>Updated.
> [...]
> 
> >>+static double tget_double(const uint8_t **p, int le){
> >>+    av_alias64 i = { .u64 = le ? AV_RL64(*p) : AV_RB64(*p)};
> >>+    *p += 8;
> >>+    return i.f64;
> >>+}
> >is type "double" guaranteed to be always 64 bits on all platforms?
> >
> Well doubles in a TIFF file are always 64 bit long, but there is
> nothing about the length of the double type in the C spec.

Yet most implementation are conforming to IEE 754 double-precision
format, which is assumed by Tiff specification. I'm not aware of
non-conforming platforms, but maybe someone can give advices (in the
worst case it might be safe to disable this code in case
platform/compiler doesn't support it, but I don't think there is a
real-world use case for this).

> [...]
> >>+
> >>+static const char *search_keyval(const Key_name *keys, int n, int id) {
> >>+    int low  = 0;
> >>+    int high = n - 1;
> >>+    while (low<= high) {
> >>+        int mid = (low + high) / 2;
> >>+        if (keys[mid].key>  id)
> >>+            high = mid - 1;
> >>+        else if (keys[mid].key<  id)
> >>+            low = mid + 1;
> >>+        else
> >>+            return keys[mid].name;
> >>+    }
> >>+    return NULL;
> >>+}
> >
> >what about bsearch()?
> Oh, good to know that something like this already exists in the
> standard lib.
> 
> [...]
> >>
> >>  /** sizes of various TIFF field types (string size = 100)*/
> >>-static const uint8_t type_sizes[6] = {
> >>-    0, 1, 100, 2, 4, 8
> >>+static const uint8_t type_sizes[14] = {
> >>+    0, 1, 100, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 4
> >
> >annotating this may greatly help readability, I mean:
> >
> >static const uint8_t type_sizes[14] = {
> >     0,   // TIFF_SHORT
> >     1,   // TIFF_LONG
> >     100, // ...
> >
> >
> Yeah, but I'd say this belongs to a separate patch.

Yes, providing a patch for this is welcome (to be applied before or
after this one).

> >>  };
> >>
> >>+typedef struct TiffGeoKey {
> >>+    int key;
> >>+    int type;
> >>+    int count;
> >>+    int offset;
> >>+    char *val;
> >>+
> >>+} TiffGeoKey;
> >>+
> >
> >>+typedef struct Key_name {
> >>+    const int key;
> >>+    const char *const name;
> >>+} Key_name;
> >
> >for overall consistency, "KeyName" is preferred
> >
> >>+
> >>+enum TiffGeoKeys {
> >
> >nit: enum denotes a type, so the singular form looks more natural to
> >me (TiffGeoKey)
> >
> >>+    TIFF_GT_MODEL_TYPE_GEOKEY                = 1024,
> >
> >maybe TIFF_GEOKEY_* =>  more grep friendly
> The current form is more consistent with the spec.
> 
> [...]
> >
> >>+enum Geo_tiff_types {
> >>+    GEOTIFF_SHORT  = 0,
> >>+    GEOTIFF_DOUBLE = 34736,
> >>+    GEOTIFF_STRING = 34737
> >>+};
> >>+
> >>+typedef struct Geokey {
> >>+    const char *const name;
> >>+    const int type;
> >>+} Geokey;
> >
> >what's exactly the relation between:
> >Key_name
> >enum TiffGeoKeys
> >enum Geo_tiff_types
> >Geokey
> >?
> >
> >maybe you can find a more consistent scheme
> >
> >>  /** sizes of various TIFF field types (string size = 1)*/
> >>-static const uint8_t type_sizes2[6] = {
> >>-    0, 1, 1, 2, 4, 8
> >>+static const uint8_t type_sizes2[14] = {
> >>+    0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 4
> >>  };
> >
> >duplicated?
> >
> >What about to include tiff.h and avoid the information duplication
> >(possibly in a separate patch).

> The string-size is different for some reason, but otherwise this
> seems like a good idea.

smells like a bug|hack

> From 26c0d145fdfa4f3f103c79a1340d4ba39f96184c Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?Thomas=20K=C3=BChnel?= <[email protected]>
> Date: Tue, 4 Oct 2011 00:19:52 +0200
> Subject: [PATCH] tiff: Add GeoTIFF support to the TIFF decoder
> 
> ---
>  libavcodec/Makefile    |    4 +-
>  libavcodec/tiff.c      |  314 +++++++++
>  libavcodec/tiff.h      |   91 +++-
>  libavcodec/tiff_data.c | 1826 
> ++++++++++++++++++++++++++++++++++++++++++++++++
>  libavcodec/tiff_data.h |   87 +++
>  libavcodec/tiffenc.c   |    4 +-
>  6 files changed, 2320 insertions(+), 6 deletions(-)
>  create mode 100644 libavcodec/tiff_data.c
>  create mode 100644 libavcodec/tiff_data.h
> 
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index bd4275a..cb2c227 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -367,8 +367,8 @@ OBJS-$(CONFIG_TARGA_ENCODER)           += targaenc.o rle.o
>  OBJS-$(CONFIG_THEORA_DECODER)          += xiph.o
>  OBJS-$(CONFIG_THP_DECODER)             += mjpegdec.o mjpeg.o
>  OBJS-$(CONFIG_TIERTEXSEQVIDEO_DECODER) += tiertexseqv.o
> -OBJS-$(CONFIG_TIFF_DECODER)            += tiff.o lzw.o faxcompr.o
> -OBJS-$(CONFIG_TIFF_ENCODER)            += tiffenc.o rle.o lzwenc.o
> +OBJS-$(CONFIG_TIFF_DECODER)            += tiff.o lzw.o faxcompr.o tiff_data.o
> +OBJS-$(CONFIG_TIFF_ENCODER)            += tiffenc.o rle.o lzwenc.o 
> tiff_data.o
>  OBJS-$(CONFIG_TMV_DECODER)             += tmv.o cga_data.o
>  OBJS-$(CONFIG_TRUEMOTION1_DECODER)     += truemotion1.o
>  OBJS-$(CONFIG_TRUEMOTION2_DECODER)     += truemotion2.o
> diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c
> index a88d0f9..3316ba5 100644
> --- a/libavcodec/tiff.c
> +++ b/libavcodec/tiff.c
> @@ -31,10 +31,12 @@
>  #endif
>  #include "lzw.h"
>  #include "tiff.h"
> +#include "tiff_data.h"
>  #include "faxcompr.h"
>  #include "libavutil/common.h"
>  #include "libavutil/intreadwrite.h"
>  #include "libavutil/imgutils.h"
> +#include "libavutil/avstring.h"
>  
>  typedef struct TiffContext {
>      AVCodecContext *avctx;
> @@ -57,6 +59,9 @@ typedef struct TiffContext {
>      const uint8_t* stripsizes;
>      int stripsize, stripoff;
>      LZWState *lzw;
> +
> +    int geokeycount;
> +    TiffGeoKey *geokeys;
>  } TiffContext;
>  
>  static int tget_short(const uint8_t **p, int le){
> @@ -71,6 +76,13 @@ static int tget_long(const uint8_t **p, int le){
>      return v;
>  }
>  
> +static double tget_double(const uint8_t **p, int le)
> +{
> +    av_alias64 i = { .u64 = le ? AV_RL64(*p) : AV_RB64(*p)};
> +    *p += 8;
> +    return i.f64;
> +}
> +
>  static int tget(const uint8_t **p, int type, int le){
>      switch(type){
>      case TIFF_BYTE : return *(*p)++;
> @@ -80,6 +92,197 @@ static int tget(const uint8_t **p, int type, int le){
>      }
>  }
>  
> +static void free_geokeys(TiffContext * const s)
> +{
> +    int i;
> +    for (i = 0; i < s->geokeycount; i++) {
> +        if (s->geokeys[i].val)
> +            av_freep(&s->geokeys[i].val);
> +    }
> +    av_freep(&s->geokeys);
> +}
> +
> +#define RET_GEOKEY(TYPE, array, element)\
> +    if (key >= TIFF_##TYPE##_KEY_ID_OFFSET &&\
> +        key - TIFF_##TYPE##_KEY_ID_OFFSET < 
> FF_ARRAY_ELEMS(ff_tiff_##array##_keys))\
> +        return ff_tiff_##array##_keys[key - 
> TIFF_##TYPE##_KEY_ID_OFFSET].element;
> +
> +static const char *get_geokey_name(int key)
> +{
> +    RET_GEOKEY(VERT, vert, name);
> +    RET_GEOKEY(PROJ, proj, name);
> +    RET_GEOKEY(GEOG, geog, name);
> +    RET_GEOKEY(CONF, conf, name);
> +
> +    return NULL;
> +}
> +
> +static int get_geokey_type(int key)
> +{
> +    RET_GEOKEY(VERT, vert, type);
> +    RET_GEOKEY(PROJ, proj, type);
> +    RET_GEOKEY(GEOG, geog, type);
> +    RET_GEOKEY(CONF, conf, type);
> +
> +    return AVERROR_INVALIDDATA;
> +}
> +
> +static int cmp_id_key(const void *id, const void *k)
> +{
> +    return *(const int*)id - ((const TiffGeoKeyName*)k)->key;
> +}
> +
> +static const char *search_keyval(const TiffGeoKeyName *keys, int n, int id)
> +{
> +    return ((TiffGeoKeyName*)bsearch(&id, keys, n, sizeof(keys[0]), 
> cmp_id_key))->name;
> +}
> +
> +static char *get_geokey_val(int key, int val)
> +{
> +    char *ap;
> +
> +    if (val == TIFF_GEO_KEY_UNDEFINED)
> +        return av_strdup("undefined");
> +    if (val == TIFF_GEO_KEY_USER_DEFINED)
> +        return av_strdup("User-Defined");
> +
> +#define RET_GEOKEY_VAL(TYPE, array)\
> +    if (val >= TIFF_##TYPE##_OFFSET &&\
> +        val - TIFF_##TYPE##_OFFSET < 
> FF_ARRAY_ELEMS(ff_tiff_##array##_codes))\
> +        return av_strdup(ff_tiff_##array##_codes[val - 
> TIFF_##TYPE##_OFFSET]);
> +
> +    switch (key) {
> +    case TIFF_GT_MODEL_TYPE_GEOKEY:
> +        RET_GEOKEY_VAL(GT_MODEL_TYPE, gt_model_type);
> +        break;
> +    case TIFF_GT_RASTER_TYPE_GEOKEY:
> +        RET_GEOKEY_VAL(GT_RASTER_TYPE, gt_raster_type);
> +        break;
> +    case TIFF_GEOG_LINEAR_UNITS_GEOKEY:
> +    case TIFF_PROJ_LINEAR_UNITS_GEOKEY:
> +    case TIFF_VERTICAL_UNITS_GEOKEY:
> +        RET_GEOKEY_VAL(LINEAR_UNIT, linear_unit);
> +        break;
> +    case TIFF_GEOG_ANGULAR_UNITS_GEOKEY:
> +    case TIFF_GEOG_AZIMUTH_UNITS_GEOKEY:
> +        RET_GEOKEY_VAL(ANGULAR_UNIT, angular_unit);
> +        break;
> +    case TIFF_GEOGRAPHIC_TYPE_GEOKEY:
> +        RET_GEOKEY_VAL(GCS_TYPE, gcs_type);
> +        RET_GEOKEY_VAL(GCSE_TYPE, gcse_type);
> +        break;
> +    case TIFF_GEOG_GEODETIC_DATUM_GEOKEY:
> +        RET_GEOKEY_VAL(GEODETIC_DATUM, geodetic_datum);
> +        RET_GEOKEY_VAL(GEODETIC_DATUM_E, geodetic_datum_e);
> +        break;
> +    case TIFF_GEOG_ELLIPSOID_GEOKEY:
> +        RET_GEOKEY_VAL(ELLIPSOID, ellipsoid);
> +        break;
> +    case TIFF_GEOG_PRIME_MERIDIAN_GEOKEY:
> +        RET_GEOKEY_VAL(PRIME_MERIDIAN, prime_meridian);
> +        break;
> +    case TIFF_PROJECTED_CS_TYPE_GEOKEY:
> +        return av_strdup(search_keyval(ff_tiff_proj_cs_type_codes, 
> FF_ARRAY_ELEMS(ff_tiff_proj_cs_type_codes), val));
> +        break;
> +    case TIFF_PROJECTION_GEOKEY:
> +        return av_strdup(search_keyval(ff_tiff_projection_codes, 
> FF_ARRAY_ELEMS(ff_tiff_projection_codes), val));
> +        break;
> +    case TIFF_PROJ_COORD_TRANS_GEOKEY:
> +        RET_GEOKEY_VAL(COORD_TRANS, coord_trans);
> +        break;
> +    }
> +
> +    ap = av_malloc(14);
> +    if (ap)
> +        snprintf(ap, 14, "Unknown-%d", val);
> +    return ap;
> +}
> +
> +static char *doubles2str(double *dp, int count, const char *sep)
> +{
> +    int i;
> +    char *ap, *ap0;
> +    if (!sep) sep = ", ";
> +    ap = av_malloc((15 + strlen(sep)) * count);
> +    if (!ap)
> +        return NULL;
> +    ap0   = ap;
> +    ap[0] = '\0';
> +    for (i = 0; i < count; i++) {
> +        int l = snprintf(ap, 15 + strlen(sep), "%f%s", dp[i], sep);
> +        ap += l;
> +    }
> +    ap0[strlen(ap0) - strlen(sep)] = '\0';
> +    return ap0;
> +}
> +
> +static char *shorts2str(int *sp, int count, const char *sep)
> +{
> +    int i;
> +    char *ap, *ap0;
> +    if (!sep) sep = ", ";
> +    ap = av_malloc((5 + strlen(sep)) * count);
> +    if (!ap)
> +        return NULL;
> +    ap0   = ap;
> +    ap[0] = '\0';
> +    for (i = 0; i < count; i++) {
> +        int l = snprintf(ap, 5 + strlen(sep), "%d%s", sp[i], sep);
> +        ap += l;
> +    }
> +    ap0[strlen(ap0) - strlen(sep)] = '\0';
> +    return ap0;
> +}
> +
> +static int add_doubles_metadata(const uint8_t **buf, int count,
> +                                const char *name, const char *sep,
> +                                TiffContext *s)
> +{

> +    char * ap;

nit+++: char *ap;

> +    int i;
> +    double *dp = av_malloc(count * type_sizes[TIFF_DOUBLE]);
> +    if (!dp)
> +        return AVERROR(ENOMEM);
> +
> +    for (i = 0; i < count; i++)
> +        dp[i] = tget_double(buf, s->le);
> +    ap = doubles2str(dp, count, sep);
> +    av_freep(&dp);
> +    if (!ap)
> +        return AVERROR(ENOMEM);
> +    av_dict_set(&s->picture.metadata, name, ap, AV_DICT_DONT_STRDUP_VAL);
> +    return 0;
> +}
> +
> +static int add_shorts_metadata(const uint8_t **buf, int count, const char 
> *name,
> +                               const char *sep, TiffContext *s)
> +{
> +    char * ap;
> +    int i;
> +    int *sp = av_malloc(count * type_sizes[TIFF_DOUBLE]);
> +    if (!sp)
> +        return AVERROR(ENOMEM);
> +
> +    for (i = 0; i < count; i++)
> +        sp[i] = tget_short(buf, s->le);
> +    ap = shorts2str(sp, count, sep);
> +    av_freep(&sp);
> +    if (!ap)
> +        return AVERROR(ENOMEM);
> +    av_dict_set(&s->picture.metadata, name, ap, AV_DICT_DONT_STRDUP_VAL);
> +    return 0;
> +}
> +
> +static int add_metadata(const uint8_t **buf, int count, int type,
> +                        const char *name, const char *sep, TiffContext *s)
> +{
> +    switch(type) {
> +    case TIFF_DOUBLE: return add_doubles_metadata(buf, count, name, sep, s);
> +    case TIFF_SHORT : return add_shorts_metadata(buf, count, name, sep, s);
> +    default         : return AVERROR_INVALIDDATA;
> +    };
> +}
> +
>  #if CONFIG_ZLIB
>  static int tiff_uncompress(uint8_t *dst, unsigned long *len, const uint8_t 
> *src, int size)
>  {
> @@ -279,8 +482,10 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t 
> *start, const uint8_t *
>  {
>      int tag, type, count, off, value = 0;
>      int i, j;
> +    int ret;
>      uint32_t *pal;
>      const uint8_t *rp, *gp, *bp;
> +    double *dp;
>  
>      if (end_buf - buf < 12)
>          return -1;
> @@ -485,6 +690,89 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t 
> *start, const uint8_t *
>          if(s->compr == TIFF_G4)
>              s->fax_opts = value;
>          break;
> +#define ADD_METADATA(count, name, sep)\
> +    if (ret = add_metadata(&buf, count, type, name, sep, s) < 0) {\
> +        av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary 
> buffer\n");\
> +        return ret;\
> +    }
> +    case TIFF_MODEL_PIXEL_SCALE:
> +        ADD_METADATA(count, "ModelPixelScaleTag", NULL);
> +        break;
> +    case TIFF_MODEL_TRANSFORMATION:
> +        ADD_METADATA(count, "ModelTransformationTag", NULL);
> +        break;
> +    case TIFF_MODEL_TIEPOINT:
> +        ADD_METADATA(count, "ModelTiepointTag", NULL);
> +        break;
> +    case TIFF_GEO_KEY_DIRECTORY:
> +        ADD_METADATA(1, "GeoTIFF_Version", NULL);
> +        ADD_METADATA(2, "GeoTIFF_Key_Revision", ".");
> +        s->geokeycount   = tget_short(&buf, s->le);
> +        if ( s->geokeycount > count / 4 - 1) {
> +            s->geokeycount = count / 4 - 1;
> +            av_log(s->avctx, AV_LOG_WARNING, "GeoTIFF key directory buffer 
> shorter than specified\n");
> +        }
> +        s->geokeys = av_mallocz(sizeof(TiffGeoKey) * s->geokeycount);
> +        if (!s->geokeys) {
> +            av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary 
> buffer\n");
> +            return AVERROR(ENOMEM);
> +        }
> +        for (i = 0; i < s->geokeycount; i++) {
> +            s->geokeys[i].key    = tget_short(&buf, s->le);
> +            s->geokeys[i].type   = tget_short(&buf, s->le);
> +            s->geokeys[i].count  = tget_short(&buf, s->le);
> +
> +            if (!s->geokeys[i].type)
> +                s->geokeys[i].val  = get_geokey_val(s->geokeys[i].key, 
> tget_short(&buf, s->le));
> +            else
> +                s->geokeys[i].offset = tget_short(&buf, s->le);
> +        }
> +        break;
> +    case TIFF_GEO_DOUBLE_PARAMS:
> +        dp = av_malloc(count * type_sizes[TIFF_DOUBLE]);
> +        if (!dp) {
> +            av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary 
> buffer\n");
> +            return AVERROR(ENOMEM);
> +        }
> +        for (i = 0; i < count; i++)
> +            dp[i] = tget_double(&buf, s->le);
> +        for (i = 0; i < s->geokeycount; i++) {
> +            if (s->geokeys[i].type == TIFF_GEO_DOUBLE_PARAMS) {
> +                if (s->geokeys[i].count == 0
> +                    || s->geokeys[i].offset + s->geokeys[i].count > count)
> +                    av_log(s->avctx, AV_LOG_WARNING, "Invalid GeoTIFF key 
> %d\n", s->geokeys[i].key);
> +                else {

Nit++: if (...) { ... } else { ...
is preferred, here and below

> +                    char *ap = doubles2str(&dp[s->geokeys[i].offset], 
> s->geokeys[i].count, ", ");
> +                    if (!ap) {
> +                        av_log(s->avctx, AV_LOG_ERROR, "Error allocating 
> temporary buffer\n");
> +                        av_freep(&dp);
> +                        return AVERROR(ENOMEM);
> +                    }
> +                    s->geokeys[i].val = ap;
> +                }
> +            }
> +        }
> +        av_freep(&dp);
> +        break;
> +    case TIFF_GEO_ASCII_PARAMS:
> +        for (i = 0; i < s->geokeycount; i++) {
> +            if (s->geokeys[i].type == TIFF_GEO_ASCII_PARAMS) {
> +                if (s->geokeys[i].count == 0
> +                    || s->geokeys[i].offset +  s->geokeys[i].count > count)
> +                    av_log(s->avctx, AV_LOG_WARNING, "Invalid GeoTIFF key 
> %d\n", s->geokeys[i].key);
> +                else {
> +                    char *ap = av_malloc(s->geokeys[i].count);
> +                    if (!ap) {
> +                        av_log(s->avctx, AV_LOG_ERROR, "Error allocating 
> temporary buffer\n");
> +                        return AVERROR(ENOMEM);
> +                    }
> +                    memcpy(ap, &buf[s->geokeys[i].offset], 
> s->geokeys[i].count);
> +                    ap[s->geokeys[i].count - 1] = '\0'; //replace the "|" 
> delimiter with a 0 byte
> +                    s->geokeys[i].val = ap;
> +                }
> +            }
> +        }
> +        break;
>      default:
>          av_log(s->avctx, AV_LOG_DEBUG, "Unknown or unsupported tag 
> %d/0X%0X\n", tag, tag);
>      }
> @@ -522,6 +810,10 @@ static int decode_frame(AVCodecContext *avctx,
>      s->invert = 0;
>      s->compr = TIFF_RAW;
>      s->fill_order = 0;
> +    free_geokeys(s);
> +    /* free existing metadata */
> +    av_dict_free(&s->picture.metadata);
> +
>      // As TIFF 6.0 specification puts it "An arbitrary but carefully chosen 
> number
>      // that further identifies the file as a TIFF file"
>      if(tget_short(&buf, le) != 42){
> @@ -541,6 +833,24 @@ static int decode_frame(AVCodecContext *avctx,
>              return -1;
>          buf += 12;
>      }
> +
> +    for (i = 0; i<s->geokeycount; i++) {
> +        const char *keyname = get_geokey_name(s->geokeys[i].key);
> +        if (!keyname) {
> +            av_log(avctx, AV_LOG_WARNING, "Unknown or unsupported GeoTIFF 
> key %d\n", s->geokeys[i].key);
> +            continue;
> +        }
> +        if (get_geokey_type(s->geokeys[i].key) != s->geokeys[i].type) {
> +            av_log(avctx, AV_LOG_WARNING, "Type of GeoTIFF key %d is 
> wrong\n", s->geokeys[i].key);
> +            continue;
> +        }
> +        ret = av_dict_set(&s->picture.metadata, keyname, s->geokeys[i].val, 
> 0);

> +        if (ret<0) {
> +            av_log(avctx, AV_LOG_ERROR, "Writing metadata failed\n");

Nit: you might provide more feedback here and mentioning the keyname, e.g.:

            av_log(avctx, AV_LOG_ERROR, "Writing metadata tag with key '%s' 
failed\n");

> +            return ret;

> +        }
> +    }
> +
>      if(!s->stripdata && !s->stripoff){
>          av_log(avctx, AV_LOG_ERROR, "Image data is missing\n");
>          return -1;
> @@ -624,6 +934,10 @@ static av_cold int tiff_end(AVCodecContext *avctx)
>  {
>      TiffContext * const s = avctx->priv_data;
>  
> +    free_geokeys(s);
> +    if(avctx->coded_frame && avctx->coded_frame->metadata)

nit++: if_(

> +        av_dict_free(&avctx->coded_frame->metadata);
> +
>      ff_lzw_decode_close(&s->lzw);
>      if(s->picture.data[0])
>          avctx->release_buffer(avctx, &s->picture);
> diff --git a/libavcodec/tiff.h b/libavcodec/tiff.h
> index cf890d6..5bb4aea 100644
> --- a/libavcodec/tiff.h
> +++ b/libavcodec/tiff.h
> @@ -58,6 +58,12 @@ enum TiffTags{
>      TIFF_YCBCR_SUBSAMPLING = 0x212,
>      TIFF_YCBCR_POSITIONING = 0x213,
>      TIFF_REFERENCE_BW = 0x214,
> +    TIFF_MODEL_TIEPOINT = 0x8482,
> +    TIFF_MODEL_PIXEL_SCALE = 0x830E,
> +    TIFF_MODEL_TRANSFORMATION = 0x8480,
> +    TIFF_GEO_KEY_DIRECTORY = 0x87AF,
> +    TIFF_GEO_DOUBLE_PARAMS = 0x87B0,
> +    TIFF_GEO_ASCII_PARAMS = 0x87B1
>  };
>  
>  /** list of TIFF compression types */
> @@ -80,11 +86,92 @@ enum TiffTypes{
>      TIFF_SHORT,
>      TIFF_LONG,
>      TIFF_RATIONAL,
> +    TIFF_SBYTE,
> +    TIFF_UNDEFINED,
> +    TIFF_SSHORT,
> +    TIFF_SLONG,
> +    TIFF_SRATIONAL,
> +    TIFF_FLOAT,
> +    TIFF_DOUBLE,
> +    TIFF_IFD
>  };
>  
>  /** sizes of various TIFF field types (string size = 100)*/
> -static const uint8_t type_sizes[6] = {
> -    0, 1, 100, 2, 4, 8
> +static const uint8_t type_sizes[14] = {
> +    0, 1, 100, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 4
> +};
> +

> +typedef struct TiffGeoKey {
> +    int key;
> +    int type;
> +    int count;
> +    int offset;
> +    char *val;
> +

nit: weird empty line

> +} TiffGeoKey;
> +
> +typedef struct TiffGeoKeyName {
> +    const int key;
> +    const char *const name;
> +} TiffGeoKeyName;
> +

> +typedef struct TiffGeoKeyType {
> +    const char *const name;
> +    const int type;
> +} TiffGeoKeyType;

As an alternative scheme:
TiffGeoTag => contains a tag, i.e. a key<->val association

TiffGeoTagKeyName  => contains a GeoTag key<->name association
TiffGeoTagNameType => contains a GeoTag name<->type association

then you can use enum TiffGeoTagKey and enum TiffGeoTagType without
the need to add the ID suffix, which are somehow confusing.

Using "enums" rather than int in both structures should help
debuggability (you can see the symbol name in GDB) and clever code
completion.

> +
> +enum TiffGeoKeyID {
> +    TIFF_GT_MODEL_TYPE_GEOKEY                = 1024,
> +    TIFF_GT_RASTER_TYPE_GEOKEY               = 1025,
> +    TIFF_GT_CITATION_GEOKEY                  = 1026,
> +    TIFF_GEOGRAPHIC_TYPE_GEOKEY              = 2048,
> +    TIFF_GEOG_CITATION_GEOKEY                = 2049,
> +    TIFF_GEOG_GEODETIC_DATUM_GEOKEY          = 2050,
> +    TIFF_GEOG_PRIME_MERIDIAN_GEOKEY          = 2051,
> +    TIFF_GEOG_LINEAR_UNITS_GEOKEY            = 2052,
> +    TIFF_GEOG_LINEAR_UNIT_SIZE_GEOKEY        = 2053,
> +    TIFF_GEOG_ANGULAR_UNITS_GEOKEY           = 2054,
> +    TIFF_GEOG_ANGULAR_UNIT_SIZE_GEOKEY       = 2055,
> +    TIFF_GEOG_ELLIPSOID_GEOKEY               = 2056,
> +    TIFF_GEOG_SEMI_MAJOR_AXIS_GEOKEY         = 2057,
> +    TIFF_GEOG_SEMI_MINOR_AXIS_GEOKEY         = 2058,
> +    TIFF_GEOG_INV_FLATTENING_GEOKEY          = 2059,
> +    TIFF_GEOG_AZIMUTH_UNITS_GEOKEY           = 2060,
> +    TIFF_GEOG_PRIME_MERIDIAN_LONG_GEOKEY     = 2061,
> +    TIFF_PROJECTED_CS_TYPE_GEOKEY            = 3072,
> +    TIFF_PCS_CITATION_GEOKEY                 = 3073,
> +    TIFF_PROJECTION_GEOKEY                   = 3074,
> +    TIFF_PROJ_COORD_TRANS_GEOKEY             = 3075,
> +    TIFF_PROJ_LINEAR_UNITS_GEOKEY            = 3076,
> +    TIFF_PROJ_LINEAR_UNIT_SIZE_GEOKEY        = 3077,
> +    TIFF_PROJ_STD_PARALLEL1_GEOKEY           = 3078,
> +    TIFF_PROJ_STD_PARALLEL2_GEOKEY           = 3079,
> +    TIFF_PROJ_NAT_ORIGIN_LONG_GEOKEY         = 3080,
> +    TIFF_PROJ_NAT_ORIGIN_LAT_GEOKEY          = 3081,
> +    TIFF_PROJ_FALSE_EASTING_GEOKEY           = 3082,
> +    TIFF_PROJ_FALSE_NORTHING_GEOKEY          = 3083,
> +    TIFF_PROJ_FALSE_ORIGIN_LONG_GEOKEY       = 3084,
> +    TIFF_PROJ_FALSE_ORIGIN_LAT_GEOKEY        = 3085,
> +    TIFF_PROJ_FALSE_ORIGIN_EASTING_GEOKEY    = 3086,
> +    TIFF_PROJ_FALSE_ORIGIN_NORTHING_GEOKEY   = 3087,
> +    TIFF_PROJ_CENTER_LONG_GEOKEY             = 3088,
> +    TIFF_PROJ_CENTER_LAT_GEOKEY              = 3089,
> +    TIFF_PROJ_CENTER_EASTING_GEOKEY          = 3090,
> +    TIFF_PROJ_CENTER_NORTHING_GEOKEY         = 3091,
> +    TIFF_PROJ_SCALE_AT_NAT_ORIGIN_GEOKEY     = 3092,
> +    TIFF_PROJ_SCALE_AT_CENTER_GEOKEY         = 3093,
> +    TIFF_PROJ_AZIMUTH_ANGLE_GEOKEY           = 3094,
> +    TIFF_PROJ_STRAIGHT_VERT_POLE_LONG_GEOKEY = 3095,
> +    TIFF_VERTICAL_CS_TYPE_GEOKEY             = 4096,
> +    TIFF_VERTICAL_CITATION_GEOKEY            = 4097,
> +    TIFF_VERTICAL_DATUM_GEOKEY               = 4098,
> +    TIFF_VERTICAL_UNITS_GEOKEY               = 4099
> +};
> +
> +enum TiffGeoKeyTypeID {
> +    GEOTIFF_SHORT  = 0,
> +    GEOTIFF_DOUBLE = 34736,
> +    GEOTIFF_STRING = 34737
>  };
>  
[...]
>  #endif /* AVCODEC_TIFF_H */
> diff --git a/libavcodec/tiff_data.c b/libavcodec/tiff_data.c
> new file mode 100644
> index 0000000..0924c05
> --- /dev/null
> +++ b/libavcodec/tiff_data.c
> @@ -0,0 +1,1826 @@
> +/*
> + * TIFF data tables
> + * Copyright (c) 2011 Thomas Kuehnel
> + *
> + * This file is part of Libav.
> + *
> + * Libav is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * Libav is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with Libav; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
> USA
> + */
> +
> +/**
> + * @file
> + * TIFF data tables
> + * @author Thomas Kuehnel
> + * @see GeoTIFF specification at
> + * http://www.remotesensing.org/geotiff/spec/geotiffhome.html
> + */
> +
> +#include "tiff_data.h"
> +
> +const TiffGeoKeyType ff_tiff_conf_keys[] = {
[...]
> +const TiffGeoKeyType ff_tiff_geog_keys[] = {
[...]
> +const TiffGeoKeyType ff_tiff_proj_keys[] = {
[...]
> +const TiffGeoKeyType ff_tiff_vert_keys[] = {
> +    {"VerticalCSTypeGeoKey",           GEOTIFF_SHORT },
> +    {"VerticalCitationGeoKey",         GEOTIFF_STRING},
> +    {"VerticalDatumGeoKey",            GEOTIFF_SHORT },
> +    {"VerticalUnitsGeoKey",            GEOTIFF_SHORT }
> +};

Suggestion: maybe ff_tiff_XXX_name_type[] or
ff_tiff_XXX_name_type_map[].

[...]
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to