XCF v11+ with 64bits offsets support
authorThomas Bernard <miniupnp@free.fr>
Thu, 06 Dec 2018 14:12:38 +0100
changeset 6326536f264b1eb
parent 631 2346808be360
child 633 d3c9832b95fb
XCF v11+ with 64bits offsets support
IMG_xcf.c
     1.1 --- a/IMG_xcf.c	Fri Nov 30 11:04:15 2018 +0100
     1.2 +++ b/IMG_xcf.c	Thu Dec 06 14:12:38 2018 +0100
     1.3 @@ -138,9 +138,11 @@
     1.4  
     1.5  typedef struct {
     1.6    char   sign [14];
     1.7 +  Uint32 file_version;
     1.8    Uint32 width;
     1.9    Uint32 height;
    1.10    Sint32 image_type;
    1.11 +  Uint32 precision;
    1.12    xcf_prop * properties;
    1.13  
    1.14    Uint32 * layer_file_offsets;
    1.15 @@ -240,6 +242,13 @@
    1.16    return data;
    1.17  }
    1.18  
    1.19 +static Uint64 read_offset (SDL_RWops * src, const xcf_header * h) {
    1.20 +  Uint64 offset;  // starting with version 11, offsets are 64 bits
    1.21 +  offset = (h->file_version >= 11) ? (Uint64)SDL_ReadBE32 (src) << 32 : 0;
    1.22 +  offset |= SDL_ReadBE32 (src);
    1.23 +  return offset;
    1.24 +}
    1.25 +
    1.26  
    1.27  static Uint32 Swap32 (Uint32 v) {
    1.28    return
    1.29 @@ -312,10 +321,15 @@
    1.30    h->width       = SDL_ReadBE32 (src);
    1.31    h->height      = SDL_ReadBE32 (src);
    1.32    h->image_type  = SDL_ReadBE32 (src);
    1.33 +  h->file_version = (h->sign[10] - '0') * 100 + (h->sign[11] - '0') * 10 + (h->sign[12] - '0');
    1.34  #ifdef DEBUG
    1.35 -  printf ("XCF signature : %.14s\n", h->sign);
    1.36 +  printf ("XCF signature : %.14s (version %u)\n", h->sign, h->file_version);
    1.37    printf (" (%u,%u) type=%u\n", h->width, h->height, h->image_type);
    1.38  #endif
    1.39 +  if (h->file_version >= 4)
    1.40 +    h->precision = SDL_ReadBE32 (src);
    1.41 +  else
    1.42 +    h->precision = 150;
    1.43  
    1.44    h->properties = NULL;
    1.45    h->layer_file_offsets = NULL;
    1.46 @@ -360,7 +374,7 @@
    1.47    SDL_free (l);
    1.48  }
    1.49  
    1.50 -static xcf_layer * read_xcf_layer (SDL_RWops * src) {
    1.51 +static xcf_layer * read_xcf_layer (SDL_RWops * src, const xcf_header * h) {
    1.52    xcf_layer * l;
    1.53    xcf_prop    prop;
    1.54  
    1.55 @@ -370,6 +384,9 @@
    1.56    l->layer_type = SDL_ReadBE32 (src);
    1.57  
    1.58    l->name = read_string (src);
    1.59 +#ifdef DEBUG
    1.60 +  printf ("layer (%d,%d) type=%d '%s'\n", l->width, l->height, l->layer_type, l->name);
    1.61 +#endif
    1.62  
    1.63    do {
    1.64      if (!xcf_read_property (src, &prop)) {
    1.65 @@ -384,8 +401,8 @@
    1.66      }
    1.67    } while (prop.id != PROP_END);
    1.68  
    1.69 -  l->hierarchy_file_offset = SDL_ReadBE32 (src);
    1.70 -  l->layer_mask_offset     = SDL_ReadBE32 (src);
    1.71 +  l->hierarchy_file_offset = read_offset (src, h);
    1.72 +  l->layer_mask_offset     = read_offset (src, h);
    1.73  
    1.74    return l;
    1.75  }
    1.76 @@ -395,7 +412,7 @@
    1.77    SDL_free (c);
    1.78  }
    1.79  
    1.80 -static xcf_channel * read_xcf_channel (SDL_RWops * src) {
    1.81 +static xcf_channel * read_xcf_channel (SDL_RWops * src, const xcf_header * h) {
    1.82    xcf_channel * l;
    1.83    xcf_prop    prop;
    1.84  
    1.85 @@ -404,6 +421,9 @@
    1.86    l->height = SDL_ReadBE32 (src);
    1.87  
    1.88    l->name = read_string (src);
    1.89 +#ifdef DEBUG
    1.90 +  printf ("channel (%u,%u) '%s'\n", l->width, l->height, l->name);
    1.91 +#endif
    1.92  
    1.93    l->selection = 0;
    1.94    do {
    1.95 @@ -431,7 +451,7 @@
    1.96      }
    1.97    } while (prop.id != PROP_END);
    1.98  
    1.99 -  l->hierarchy_file_offset = SDL_ReadBE32 (src);
   1.100 +  l->hierarchy_file_offset = read_offset (src, h);
   1.101  
   1.102    return l;
   1.103  }
   1.104 @@ -441,7 +461,7 @@
   1.105    SDL_free (h);
   1.106  }
   1.107  
   1.108 -static xcf_hierarchy * read_xcf_hierarchy (SDL_RWops * src) {
   1.109 +static xcf_hierarchy * read_xcf_hierarchy (SDL_RWops * src, const xcf_header * head) {
   1.110    xcf_hierarchy * h;
   1.111    int i;
   1.112  
   1.113 @@ -454,7 +474,7 @@
   1.114    i = 0;
   1.115    do {
   1.116      h->level_file_offsets = (Uint32 *) SDL_realloc (h->level_file_offsets, sizeof (Uint32) * (i+1));
   1.117 -    h->level_file_offsets [i] = SDL_ReadBE32 (src);
   1.118 +    h->level_file_offsets [i] = read_offset (src, head);
   1.119    } while (h->level_file_offsets [i++]);
   1.120  
   1.121    return h;
   1.122 @@ -465,7 +485,7 @@
   1.123    SDL_free (l);
   1.124  }
   1.125  
   1.126 -static xcf_level * read_xcf_level (SDL_RWops * src) {
   1.127 +static xcf_level * read_xcf_level (SDL_RWops * src, const xcf_header * h) {
   1.128    xcf_level * l;
   1.129    int i;
   1.130  
   1.131 @@ -477,7 +497,7 @@
   1.132    i = 0;
   1.133    do {
   1.134      l->tile_file_offsets = (Uint32 *) SDL_realloc (l->tile_file_offsets, sizeof (Uint32) * (i+1));
   1.135 -    l->tile_file_offsets [i] = SDL_ReadBE32 (src);
   1.136 +    l->tile_file_offsets [i] = read_offset (src, h);
   1.137    } while (l->tile_file_offsets [i++]);
   1.138  
   1.139    return l;
   1.140 @@ -491,7 +511,8 @@
   1.141    unsigned char * load;
   1.142  
   1.143    load = (unsigned char *) SDL_malloc (len); // expect this is okay
   1.144 -  SDL_RWread (src, load, len, 1);
   1.145 +  if (load != NULL)
   1.146 +    SDL_RWread (src, load, len, 1);
   1.147  
   1.148    return load;
   1.149  }
   1.150 @@ -507,6 +528,8 @@
   1.151    }
   1.152  
   1.153    t = load = (unsigned char *) SDL_malloc (len);
   1.154 +  if (load == NULL)
   1.155 +    return NULL;
   1.156    reallen = SDL_RWread (src, t, 1, len);
   1.157  
   1.158    data = (unsigned char *) SDL_calloc (1, x*y*bpp);
   1.159 @@ -612,7 +635,7 @@
   1.160      Uint32         *row;
   1.161  
   1.162      SDL_RWseek(src, layer->hierarchy_file_offset, RW_SEEK_SET);
   1.163 -    hierarchy = read_xcf_hierarchy(src);
   1.164 +    hierarchy = read_xcf_hierarchy(src, head);
   1.165  
   1.166      if (hierarchy->bpp > 4) {  /* unsupported. */
   1.167          SDL_Log("Unknown Gimp image bpp (%u)\n", (unsigned int) hierarchy->bpp);
   1.168 @@ -629,7 +652,7 @@
   1.169      level = NULL;
   1.170      for (i = 0; hierarchy->level_file_offsets[i]; i++) {
   1.171          SDL_RWseek(src, hierarchy->level_file_offsets[i], RW_SEEK_SET);
   1.172 -        level = read_xcf_level(src);
   1.173 +        level = read_xcf_level(src, head);
   1.174  
   1.175          ty = tx = 0;
   1.176          for (j = 0; level->tile_file_offsets[j]; j++) {
   1.177 @@ -810,7 +833,7 @@
   1.178  
   1.179    offsets = 0;
   1.180  
   1.181 -  while ((offset = SDL_ReadBE32 (src))) {
   1.182 +  while ((offset = read_offset (src, head))) {
   1.183      head->layer_file_offsets = (Uint32 *) SDL_realloc (head->layer_file_offsets, sizeof (Uint32) * (offsets+1));
   1.184      head->layer_file_offsets [offsets] = (Uint32)offset;
   1.185      offsets++;
   1.186 @@ -830,20 +853,22 @@
   1.187      SDL_Rect rs, rd;
   1.188      SDL_RWseek (src, head->layer_file_offsets [i-1], RW_SEEK_SET);
   1.189  
   1.190 -    layer = read_xcf_layer (src);
   1.191 -    do_layer_surface (lays, src, head, layer, load_tile);
   1.192 -    rs.x = 0;
   1.193 -    rs.y = 0;
   1.194 -    rs.w = layer->width;
   1.195 -    rs.h = layer->height;
   1.196 -    rd.x = layer->offset_x;
   1.197 -    rd.y = layer->offset_y;
   1.198 -    rd.w = layer->width;
   1.199 -    rd.h = layer->height;
   1.200 +    layer = read_xcf_layer (src, head);
   1.201 +    if (layer != NULL) {
   1.202 +      do_layer_surface (lays, src, head, layer, load_tile);
   1.203 +      rs.x = 0;
   1.204 +      rs.y = 0;
   1.205 +      rs.w = layer->width;
   1.206 +      rs.h = layer->height;
   1.207 +      rd.x = layer->offset_x;
   1.208 +      rd.y = layer->offset_y;
   1.209 +      rd.w = layer->width;
   1.210 +      rd.h = layer->height;
   1.211  
   1.212 -    if (layer->visible)
   1.213 -      SDL_BlitSurface (lays, &rs, surface, &rd);
   1.214 -    free_xcf_layer (layer);
   1.215 +      if (layer->visible)
   1.216 +        SDL_BlitSurface (lays, &rs, surface, &rd);
   1.217 +      free_xcf_layer (layer);
   1.218 +    }
   1.219    }
   1.220  
   1.221    SDL_FreeSurface (lays);
   1.222 @@ -853,11 +878,13 @@
   1.223    // read channels
   1.224    channel = NULL;
   1.225    chnls   = 0;
   1.226 -  while ((offset = SDL_ReadBE32 (src))) {
   1.227 +  while ((offset = read_offset (src, head))) {
   1.228      channel = (xcf_channel **) SDL_realloc (channel, sizeof (xcf_channel *) * (chnls+1));
   1.229      fp = SDL_RWtell (src);
   1.230      SDL_RWseek (src, offset, RW_SEEK_SET);
   1.231 -    channel [chnls++] = (read_xcf_channel (src));
   1.232 +    channel [chnls] = (read_xcf_channel (src));
   1.233 +    if (channel [chnls] != NULL)
   1.234 +      chnls++;
   1.235      SDL_RWseek (src, fp, RW_SEEK_SET);
   1.236    }
   1.237