Support XCG files v11+ with 64bits offsets SDL-1.2
authorThomas Bernard <miniupnp@free.fr>
Thu, 06 Dec 2018 13:44:10 +0100
branchSDL-1.2
changeset 6351d88a9866410
parent 634 68f958f43339
child 636 1d33bfccd462
Support XCG files v11+ with 64bits offsets
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 13:44:10 2018 +0100
     1.3 @@ -143,9 +143,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 @@ -254,6 +256,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 @@ -327,10 +336,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 @@ -375,7 +389,7 @@
    1.47    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 @@ -385,6 +399,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 @@ -399,8 +416,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 @@ -410,7 +427,7 @@
    1.77    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 @@ -419,6 +436,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 @@ -446,7 +466,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 @@ -456,7 +476,7 @@
   1.105    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 @@ -469,7 +489,7 @@
   1.114    i = 0;
   1.115    do {
   1.116      h->level_file_offsets = (Uint32 *) 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 @@ -480,7 +500,7 @@
   1.123    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 @@ -492,7 +512,7 @@
   1.132    i = 0;
   1.133    do {
   1.134      l->tile_file_offsets = (Uint32 *) 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 @@ -506,7 +526,8 @@
   1.141    unsigned char * load;
   1.142  
   1.143    load = (unsigned char *) 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 @@ -628,7 +649,7 @@
   1.151    Uint32 *row;
   1.152  
   1.153    SDL_RWseek (src, layer->hierarchy_file_offset, RW_SEEK_SET);
   1.154 -  hierarchy = read_xcf_hierarchy (src);
   1.155 +  hierarchy = read_xcf_hierarchy (src, head);
   1.156  
   1.157    if (hierarchy->bpp > 4) {  /* unsupported. */
   1.158      fprintf (stderr, "Unknown Gimp image bpp (%u)\n", (unsigned int) hierarchy->bpp);
   1.159 @@ -645,7 +666,7 @@
   1.160    level = NULL;
   1.161    for (i = 0; hierarchy->level_file_offsets [i]; i++) {
   1.162      SDL_RWseek (src, hierarchy->level_file_offsets [i], RW_SEEK_SET);
   1.163 -    level = read_xcf_level (src);
   1.164 +    level = read_xcf_level (src, head);
   1.165  
   1.166      ty = tx = 0;
   1.167      for (j = 0; level->tile_file_offsets [j]; j++) {
   1.168 @@ -654,6 +675,8 @@
   1.169        oy = ty+64 > level->height ? level->height % 64 : 64;
   1.170  
   1.171        if (level->tile_file_offsets [j+1]) {
   1.172 +        if (level->tile_file_offsets [j+1] <= level->tile_file_offsets [j])
   1.173 +          break;
   1.174  	tile = load_tile
   1.175  	  (src,
   1.176  	   level->tile_file_offsets [j+1] - level->tile_file_offsets [j],
   1.177 @@ -829,7 +852,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 *) realloc (head->layer_file_offsets, sizeof (Uint32) * (offsets+1));
   1.184      head->layer_file_offsets [offsets] = (Uint32)offset;
   1.185      offsets++;
   1.186 @@ -849,20 +872,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 @@ -872,11 +897,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 **) 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, head));
   1.233 +    if (channel [chnls] != NULL)
   1.234 +      chnls++;
   1.235      SDL_RWseek (src, fp, RW_SEEK_SET);    
   1.236    }
   1.237