Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 1
/*
2
    IMGLIB:  An example image loading library for use with SDL
3
    Copyright (C) 1999  Sam Lantinga
4
 
5
    This library is free software; you can redistribute it and/or
6
    modify it under the terms of the GNU Library General Public
7
    License as published by the Free Software Foundation; either
8
    version 2 of the License, or (at your option) any later version.
9
 
10
    This library is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
    Library General Public License for more details.
14
 
15
    You should have received a copy of the GNU Library General Public
16
    License along with this library; if not, write to the Free
17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 
19
    Sam Lantinga
20
    5635-34 Springhouse Dr.
21
    Pleasanton, CA 94588 (USA)
22
    slouken@devolution.com
23
 
24
    XCF support by Bernhard J. Pietsch 
25
*/
26
 
27
/* This is a XCF image file loading framework */
28
 
29
#include 
30
#include 
31
#include 
32
 
33
#include "SDL_image.h"
34
 
35
#ifdef LOAD_XCF
36
 
37
static char prop_names [][30] = {
38
  "end",
39
  "colormap",
40
  "active_layer",
41
  "active_channel",
42
  "selection",
43
  "floating_selection",
44
  "opacity",
45
  "mode",
46
  "visible",
47
  "linked",
48
  "preserve_transparency",
49
  "apply_mask",
50
  "edit_mask",
51
  "show_mask",
52
  "show_masked",
53
  "offsets",
54
  "color",
55
  "compression",
56
  "guides",
57
  "resolution",
58
  "tattoo",
59
  "parasites",
60
  "unit",
61
  "paths",
62
  "user_unit"
63
};
64
 
65
typedef enum
66
{
67
  PROP_END = 0,
68
  PROP_COLORMAP = 1,
69
  PROP_ACTIVE_LAYER = 2,
70
  PROP_ACTIVE_CHANNEL = 3,
71
  PROP_SELECTION = 4,
72
  PROP_FLOATING_SELECTION = 5,
73
  PROP_OPACITY = 6,
74
  PROP_MODE = 7,
75
  PROP_VISIBLE = 8,
76
  PROP_LINKED = 9,
77
  PROP_PRESERVE_TRANSPARENCY = 10,
78
  PROP_APPLY_MASK = 11,
79
  PROP_EDIT_MASK = 12,
80
  PROP_SHOW_MASK = 13,
81
  PROP_SHOW_MASKED = 14,
82
  PROP_OFFSETS = 15,
83
  PROP_COLOR = 16,
84
  PROP_COMPRESSION = 17,
85
  PROP_GUIDES = 18,
86
  PROP_RESOLUTION = 19,
87
  PROP_TATTOO = 20,
88
  PROP_PARASITES = 21,
89
  PROP_UNIT = 22,
90
  PROP_PATHS = 23,
91
  PROP_USER_UNIT = 24
92
} xcf_prop_type;
93
 
94
typedef enum {
95
  COMPR_NONE    = 0,
96
  COMPR_RLE     = 1,
97
  COMPR_ZLIB    = 2,
98
  COMPR_FRACTAL = 3
99
} xcf_compr_type;
100
 
101
typedef enum {
102
  IMAGE_RGB       = 0,
103
  IMAGE_GREYSCALE = 1,
104
  IMAGE_INDEXED   = 2
105
} xcf_image_type;
106
 
107
typedef struct {
108
  Uint32 id;
109
  Uint32 length;
110
  union {
111
    struct {
112
      Uint32 num;
113
      char * cmap;
114
    } colormap; // 1
115
    struct {
116
      Uint32 drawable_offset;
117
    } floating_selection; // 5
118
    Sint32 opacity;
119
    Sint32 mode;
120
    int    visible;
121
    int    linked;
122
    int    preserve_transparency;
123
    int    apply_mask;
124
    int    show_mask;
125
    struct {
126
      Sint32 x;
127
      Sint32 y;
128
    } offset;
129
    unsigned char color [3];
130
    Uint8 compression;
131
    struct {
132
      Sint32 x;
133
      Sint32 y;
134
    } resolution;
135
    struct {
136
      char * name;
137
      Uint32 flags;
138
      Uint32 size;
139
      char * data;
140
    } parasite;
141
  } data;
142
} xcf_prop;
143
 
144
typedef struct {
145
  char   sign [14];
146
  Uint32 width;
147
  Uint32 height;
148
  Sint32 image_type;
149
  xcf_prop * properties;
150
 
151
  Uint32 * layer_file_offsets;
152
  Uint32 * channel_file_offsets;
153
 
154
  xcf_compr_type compr;
155
  Uint32         cm_num;
156
  unsigned char * cm_map;
157
} xcf_header;
158
 
159
typedef struct {
160
  Uint32 width;
161
  Uint32 height;
162
  Sint32 layer_type;
163
  char * name;
164
  xcf_prop * properties;
165
 
166
  Uint32 hierarchy_file_offset;
167
  Uint32 layer_mask_offset;
168
 
169
  Uint32 offset_x;
170
  Uint32 offset_y;
171
} xcf_layer;
172
 
173
typedef struct {
174
  Uint32 width;
175
  Uint32 height;
176
  char * name;
177
  xcf_prop * properties;
178
 
179
  Uint32 hierarchy_file_offset;
180
 
181
  Uint32 color;
182
  Uint32 opacity;
183
  int selection : 1;
184
} xcf_channel;
185
 
186
typedef struct {
187
  Uint32 width;
188
  Uint32 height;
189
  Uint32 bpp;
190
 
191
  Uint32 * level_file_offsets;
192
} xcf_hierarchy;
193
 
194
typedef struct {
195
  Uint32 width;
196
  Uint32 height;
197
 
198
  Uint32 * tile_file_offsets;
199
} xcf_level;
200
 
201
typedef unsigned char * xcf_tile;
202
 
203
typedef unsigned char * (* load_tile_type) (SDL_RWops *, Uint32, int, int, int);
204
 
205
 
206
/* See if an image is contained in a data source */
207
int IMG_isXCF(SDL_RWops *src) {
208
  int is_XCF;
209
  char magic[14];
210
 
211
  is_XCF = 0;
212
  if ( SDL_RWread(src, magic, 14, 1) ) {
213
    if (strncmp(magic, "gimp xcf ", 9) == 0) {
214
      is_XCF = 1;
215
    }
216
  }
217
 
218
  return(is_XCF);
219
}
220
 
221
static char * read_string (SDL_RWops * src) {
222
  Uint32 tmp;
223
  char * data;
224
 
225
  tmp = SDL_ReadBE32 (src);
226
  if (tmp > 0) {
227
    data = (char *) malloc (sizeof (char) * tmp);
228
    SDL_RWread (src, data, tmp, 1);
229
  }
230
  else {
231
    data = NULL;
232
  }
233
 
234
  return data;
235
}
236
 
237
 
238
static Uint32 Swap32 (Uint32 v) {
239
  return
240
    ((v & 0x000000FF) << 16)
241
    |  ((v & 0x0000FF00))
242
    |  ((v & 0x00FF0000) >> 16)
243
    |  ((v & 0xFF000000));
244
}
245
 
246
void xcf_read_property (SDL_RWops * src, xcf_prop * prop) {
247
  prop->id = SDL_ReadBE32 (src);
248
  prop->length = SDL_ReadBE32 (src);
249
 
250
  printf ("%.8X: %s: %d\n", SDL_RWtell (src), prop->id < 25 ? prop_names [prop->id] : "unknown", prop->length);
251
 
252
  switch (prop->id) {
253
  case PROP_COLORMAP:
254
    prop->data.colormap.num = SDL_ReadBE32 (src);
255
    prop->data.colormap.cmap = (char *) malloc (sizeof (char) * prop->data.colormap.num * 3);
256
    SDL_RWread (src, prop->data.colormap.cmap, prop->data.colormap.num*3, 1);
257
    break;
258
 
259
  case PROP_OFFSETS:
260
    prop->data.offset.x = SDL_ReadBE32 (src);
261
    prop->data.offset.y = SDL_ReadBE32 (src);
262
    break;
263
  case PROP_OPACITY:
264
    prop->data.opacity = SDL_ReadBE32 (src);
265
    break;
266
  case PROP_COMPRESSION:
267
  case PROP_COLOR:
268
    SDL_RWread (src, &prop->data, prop->length, 1);
269
    break;
270
  default:
271
    //    SDL_RWread (src, &prop->data, prop->length, 1);
272
    SDL_RWseek (src, prop->length, SEEK_CUR);
273
  }
274
}
275
 
276
void free_xcf_header (xcf_header * h) {
277
  if (h->cm_num)
278
    free (h->cm_map);
279
 
280
  free (h);
281
}
282
 
283
xcf_header * read_xcf_header (SDL_RWops * src) {
284
  xcf_header * h;
285
  xcf_prop prop;
286
 
287
  h = (xcf_header *) malloc (sizeof (xcf_header));
288
  SDL_RWread (src, h->sign, 14, 1);
289
  h->width       = SDL_ReadBE32 (src);
290
  h->height      = SDL_ReadBE32 (src);
291
  h->image_type  = SDL_ReadBE32 (src);
292
 
293
  h->properties = NULL;
294
  h->compr      = COMPR_NONE;
295
  h->cm_num = 0;
296
  h->cm_map = NULL;
297
 
298
  // Just read, don't save
299
  do {
300
    xcf_read_property (src, &prop);
301
    if (prop.id == PROP_COMPRESSION)
302
      h->compr = prop.data.compression;
303
    else if (prop.id == PROP_COLORMAP) {
304
      int i;
305
 
306
      h->cm_num = prop.data.colormap.num;
307
      h->cm_map = (char *) malloc (sizeof (char) * 3 * h->cm_num);
308
      memcpy (h->cm_map, prop.data.colormap.cmap, 3*sizeof (char)*h->cm_num);
309
      free (prop.data.colormap.cmap);
310
    }
311
  } while (prop.id != PROP_END);
312
 
313
  return h;
314
}
315
 
316
void free_xcf_layer (xcf_layer * l) {
317
  free (l->name);
318
  free (l);
319
}
320
 
321
xcf_layer * read_xcf_layer (SDL_RWops * src) {
322
  xcf_layer * l;
323
  xcf_prop    prop;
324
 
325
  l = (xcf_layer *) malloc (sizeof (xcf_layer));
326
  l->width  = SDL_ReadBE32 (src);
327
  l->height = SDL_ReadBE32 (src);
328
  l->layer_type = SDL_ReadBE32 (src);
329
 
330
  l->name = read_string (src);
331
 
332
  do {
333
    xcf_read_property (src, &prop);
334
    if (prop.id == PROP_OFFSETS) {
335
      l->offset_x = prop.data.offset.x;
336
      l->offset_y = prop.data.offset.y;
337
    }
338
  } while (prop.id != PROP_END);
339
 
340
  l->hierarchy_file_offset = SDL_ReadBE32 (src);
341
  l->layer_mask_offset     = SDL_ReadBE32 (src);
342
 
343
  return l;
344
}
345
 
346
void free_xcf_channel (xcf_channel * c) {
347
  free (c->name);
348
  free (c);
349
}
350
 
351
xcf_channel * read_xcf_channel (SDL_RWops * src) {
352
  xcf_channel * l;
353
  xcf_prop    prop;
354
 
355
  l = (xcf_channel *) malloc (sizeof (xcf_channel));
356
  l->width  = SDL_ReadBE32 (src);
357
  l->height = SDL_ReadBE32 (src);
358
 
359
  l->name = read_string (src);
360
 
361
  l->selection = 0;
362
  do {
363
    xcf_read_property (src, &prop);
364
    switch (prop.id) {
365
    case PROP_OPACITY:
366
      l->opacity = prop.data.opacity << 24;
367
      break;
368
    case PROP_COLOR:
369
      l->color = ((Uint32) prop.data.color[0] << 16)
370
	| ((Uint32) prop.data.color[1] << 8)
371
	| ((Uint32) prop.data.color[2]);
372
      break;
373
    case PROP_SELECTION:
374
      l->selection = 1;
375
      break;
376
    default:
377
    }
378
  } while (prop.id != PROP_END);
379
 
380
  l->hierarchy_file_offset = SDL_ReadBE32 (src);
381
 
382
  return l;
383
}
384
 
385
void free_xcf_hierarchy (xcf_hierarchy * h) {
386
  free (h->level_file_offsets);
387
  free (h);
388
}
389
 
390
xcf_hierarchy * read_xcf_hierarchy (SDL_RWops * src) {
391
  xcf_hierarchy * h;
392
  int i;
393
 
394
  h = (xcf_hierarchy *) malloc (sizeof (xcf_hierarchy));
395
  h->width  = SDL_ReadBE32 (src);
396
  h->height = SDL_ReadBE32 (src);
397
  h->bpp    = SDL_ReadBE32 (src);
398
 
399
  h->level_file_offsets = NULL;
400
  i = 0;
401
  do {
402
    h->level_file_offsets = (Uint32 *) realloc (h->level_file_offsets, sizeof (Uint32) * (i+1));
403
    h->level_file_offsets [i] = SDL_ReadBE32 (src);
404
  } while (h->level_file_offsets [i++]);
405
 
406
  return h;
407
}
408
 
409
void free_xcf_level (xcf_level * l) {
410
  free (l->tile_file_offsets);
411
  free (l);
412
}
413
 
414
xcf_level * read_xcf_level (SDL_RWops * src) {
415
  xcf_level * l;
416
  int i;
417
 
418
  l = (xcf_level *) malloc (sizeof (xcf_level));
419
  l->width  = SDL_ReadBE32 (src);
420
  l->height = SDL_ReadBE32 (src);
421
 
422
  l->tile_file_offsets = NULL;
423
  i = 0;
424
  do {
425
    l->tile_file_offsets = (Uint32 *) realloc (l->tile_file_offsets, sizeof (Uint32) * (i+1));
426
    l->tile_file_offsets [i] = SDL_ReadBE32 (src);
427
  } while (l->tile_file_offsets [i++]);
428
 
429
  return l;
430
}
431
 
432
void free_xcf_tile (unsigned char * t) {
433
  free (t);
434
}
435
 
436
unsigned char * load_xcf_tile_none (SDL_RWops * src, Uint32 len, int bpp, int x, int y) {
437
  unsigned char * load;
438
 
439
  load = (char *) malloc (len); // expect this is okay
440
  SDL_RWread (src, load, len, 1);
441
 
442
  return load;
443
}
444
 
445
unsigned char * load_xcf_tile_rle (SDL_RWops * src, Uint32 len, int bpp, int x, int y) {
446
  unsigned char * load, * t, * data, * d;
447
  Uint32 reallen;
448
  int i, size, count, j, length;
449
  unsigned char val;
450
 
451
  t = load = (char *) malloc (len);
452
  reallen = SDL_RWread (src, t, 1, len);
453
 
454
  data = (char *) malloc (x*y*bpp);
455
  for (i = 0; i < bpp; i++) {
456
    d    = data + i;
457
    size = x*y;
458
    count = 0;
459
 
460
    while (size > 0) {
461
      val = *t++;
462
 
463
      length = val;
464
      if (length >= 128) {
465
	length = 255 - (length - 1);
466
	if (length == 128) {
467
	  length = (*t << 8) + t[1];
468
	  t += 2;
469
	}
470
 
471
	count += length;
472
	size -= length;
473
 
474
	while (length-- > 0) {
475
	  *d = *t++;
476
	  d += bpp;
477
	}
478
      }
479
      else {
480
	length += 1;
481
	if (length == 128) {
482
	  length = (*t << 8) + t[1];
483
	  t += 2;
484
	}
485
 
486
	count += length;
487
	size -= length;
488
 
489
	val = *t++;
490
 
491
	for (j = 0; j < length; j++) {
492
	  *d = val;
493
	  d += bpp;
494
	}
495
      }
496
    }
497
  }
498
 
499
  free (load);
500
  return (data);
501
}
502
 
503
static Uint32 rgb2grey (Uint32 a) {
504
  Uint8 l;
505
  l = 0.2990 * ((a && 0x00FF0000) >> 16)
506
    + 0.5870 * ((a && 0x0000FF00) >>  8)
507
    + 0.1140 * ((a && 0x000000FF));
508
 
509
  return (l << 16) | (l << 8) | l;
510
}
511
 
512
void create_channel_surface (SDL_Surface * surf, xcf_image_type itype, Uint32 color, Uint32 opacity) {
513
  Uint32 c;
514
 
515
  switch (itype) {
516
  case IMAGE_RGB:
517
  case IMAGE_INDEXED:
518
    c = opacity | color;
519
    break;
520
  case IMAGE_GREYSCALE:
521
    c = opacity | rgb2grey (color);
522
    break;
523
  }
524
  SDL_FillRect (surf, NULL, c);
525
}
526
 
527
int do_layer_surface (SDL_Surface * surface, SDL_RWops * src, xcf_header * head, xcf_layer * layer, load_tile_type load_tile) {
528
  xcf_hierarchy * hierarchy;
529
  xcf_level     * level;
530
  unsigned char * tile;
531
  Uint8  * p8;
532
  Uint16 * p16;
533
  Uint32 * p;
534
  int x, y, tx, ty, ox, oy, width, height, i, j;
535
  Uint32 *row;
536
 
537
  SDL_RWseek (src, layer->hierarchy_file_offset, SEEK_SET);
538
  hierarchy = read_xcf_hierarchy (src);
539
 
540
  level = NULL;
541
  for (i = 0; hierarchy->level_file_offsets [i]; i++) {
542
    SDL_RWseek (src, hierarchy->level_file_offsets [i], SEEK_SET);
543
    level = read_xcf_level (src);
544
 
545
    ty = tx = 0;
546
    for (j = 0; level->tile_file_offsets [j]; j++) {
547
      SDL_RWseek (src, level->tile_file_offsets [j], SEEK_SET);
548
      ox = tx+64 > level->width ? level->width % 64 : 64;
549
      oy = ty+64 > level->height ? level->height % 64 : 64;
550
 
551
      if (level->tile_file_offsets [j+1]) {
552
	tile = load_tile
553
	  (src,
554
	   level->tile_file_offsets [j+1] - level->tile_file_offsets [j],
555
	   hierarchy->bpp,
556
	   ox, oy);
557
      }
558
      else {
559
	tile = load_tile
560
	  (src,
561
	   ox*oy*6,
562
	   hierarchy->bpp,
563
	   ox, oy);
564
      }
565
 
566
      p8  = tile;
567
      p16 = (Uint16 *) p8;
568
      p   = (Uint32 *) p8;
569
      for (y=ty; y < ty+oy; y++) {
570
	row = (Uint32 *)((Uint8 *)surface->pixels + y*surface->pitch + tx*4);
571
	switch (hierarchy->bpp) {
572
	case 4:
573
	  for (x=tx; x < tx+ox; x++)
574
	    *row++ = Swap32 (*p++);
575
	  break;
576
	case 3:
577
	  for (x=tx; x < tx+ox; x++) {
578
	    *row = 0xFF000000;
579
	    *row |= ((Uint32) *(p8++) << 16);
580
	    *row |= ((Uint32) *(p8++) << 8);
581
	    *row |= ((Uint32) *(p8++) << 0);
582
	    row++;
583
	  }
584
	  break;
585
	case 2: // Indexed/Greyscale + Alpha
586
	  switch (head->image_type) {
587
	  case IMAGE_INDEXED:
588
	    for (x=tx; x < tx+ox; x++) {
589
	      *row =  ((Uint32) (head->cm_map [*p8*3])     << 16);
590
	      *row |= ((Uint32) (head->cm_map [*p8*3+1])   << 8);
591
	      *row |= ((Uint32) (head->cm_map [*p8++*3+2]) << 0);
592
	      *row |= ((Uint32) *p8++ << 24);;
593
	      row++;
594
	    }
595
	    break;
596
	  case IMAGE_GREYSCALE:
597
	    for (x=tx; x < tx+ox; x++) {
598
	      *row = ((Uint32) *p8 << 16);
599
	      *row |= ((Uint32) *p8 << 8);
600
	      *row |= ((Uint32) *p8++ << 0);
601
	      *row |= ((Uint32) *p8++ << 24);;
602
	      row++;
603
	    }
604
	    break;
605
	  default:
606
	    fprintf (stderr, "Unknown Gimp image type (%d)\n", head->image_type);
607
	    return 1;
608
	  }
609
	  break;
610
	case 1: // Indexed/Greyscale
611
	  switch (head->image_type) {
612
	  case IMAGE_INDEXED:
613
	    for (x = tx; x < tx+ox; x++) {
614
	      *row++ = 0xFF000000
615
		| ((Uint32) (head->cm_map [*p8*3]) << 16)
616
		| ((Uint32) (head->cm_map [*p8*3+1]) << 8)
617
		| ((Uint32) (head->cm_map [*p8*3+2]) << 0);
618
	      p8++;
619
	    }
620
	    break;
621
	  case IMAGE_GREYSCALE:
622
	    for (x=tx; x < tx+ox; x++) {
623
	      *row++ = 0xFF000000
624
		| (((Uint32) (*p8)) << 16)
625
		| (((Uint32) (*p8)) << 8)
626
		| (((Uint32) (*p8++)) << 0);
627
	    }
628
	    break;
629
	  default:
630
	    fprintf (stderr, "Unknown Gimp image type (%d)\n", head->image_type);
631
	    return 1;
632
	  }
633
	  break;
634
	}
635
      }
636
      tx += 64;
637
      if (tx >= level->width) {
638
	tx = 0;
639
	ty += 64;
640
      }
641
      if (ty >= level->height) {
642
	break;
643
      }
644
 
645
      free_xcf_tile (tile);
646
    }
647
    free_xcf_level (level);
648
  }
649
 
650
  free_xcf_hierarchy (hierarchy);
651
}
652
 
653
SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src) {
654
  SDL_Surface *surface, *lays;
655
  xcf_header * head;
656
  xcf_layer  * layer;
657
  xcf_channel ** channel;
658
  int read_error, chnls, i, offsets;
659
  Uint32 offset, fp;
660
 
661
  unsigned char * (* load_tile) (SDL_RWops *, Uint32, int, int, int);
662
 
663
  /* Initialize the data we will clean up when we're done */
664
  surface = NULL;
665
  read_error = 0;
666
 
667
  /* Check to make sure we have something to do */
668
  if ( ! src ) {
669
    goto done;
670
  }
671
 
672
  head = read_xcf_header (src);
673
 
674
  switch (head->compr) {
675
  case COMPR_NONE:
676
    load_tile = load_xcf_tile_none;
677
    break;
678
  case COMPR_RLE:
679
    load_tile = load_xcf_tile_rle;
680
    break;
681
  default:
682
    fprintf (stderr, "Unsupported Compression.\n");
683
    free_xcf_header (head);
684
    return NULL;
685
  }
686
 
687
  /* Create the surface of the appropriate type */
688
  surface = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32,
689
			     0x00FF0000,0x0000FF00,0x000000FF,0xFF000000);
690
 
691
  if ( surface == NULL ) {
692
    IMG_SetError("Out of memory");
693
    goto done;
694
  }
695
 
696
  head->layer_file_offsets = NULL;
697
  offsets = 0;
698
 
699
  while (offset = SDL_ReadBE32 (src)) {
700
    head->layer_file_offsets = (Uint32 *) realloc (head->layer_file_offsets, sizeof (Uint32) * (offsets+1));
701
    head->layer_file_offsets [offsets] = offset;
702
    offsets++;
703
  }
704
  fp = SDL_RWtell (src);
705
 
706
  lays = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32,
707
			  0x00FF0000,0x0000FF00,0x000000FF,0xFF000000);
708
 
709
  if ( lays == NULL ) {
710
    IMG_SetError("Out of memory");
711
    goto done;
712
  }
713
 
714
  // Blit layers backwards, because Gimp saves them highest first
715
  for (i = offsets; i > 0; i--) {
716
    SDL_Rect rs, rd;
717
    SDL_RWseek (src, head->layer_file_offsets [i-1], SEEK_SET);
718
 
719
    layer = read_xcf_layer (src);
720
    do_layer_surface (lays, src, head, layer, load_tile);
721
    rs.x = 0;
722
    rs.y = 0;
723
    rs.w = layer->width;
724
    rs.h = layer->height;
725
    rd.x = layer->offset_x;
726
    rd.y = layer->offset_y;
727
    rd.w = layer->width;
728
    rd.h = layer->height;
729
    free_xcf_layer (layer);
730
 
731
    SDL_BlitSurface (lays, &rs, surface, &rd);
732
  }
733
 
734
  SDL_FreeSurface (lays);
735
 
736
  SDL_RWseek (src, fp, SEEK_SET);
737
 
738
  // read channels
739
  channel = NULL;
740
  chnls   = 0;
741
  while (offset = SDL_ReadBE32 (src)) {
742
    channel = (xcf_channel **) realloc (channel, sizeof (xcf_channel *) * (chnls+1));
743
    fp = SDL_RWtell (src);
744
    SDL_RWseek (src, offset, SEEK_SET);
745
    channel [chnls++] = (read_xcf_channel (src));
746
    SDL_RWseek (src, fp, SEEK_SET);
747
  }
748
 
749
  if (chnls) {
750
    SDL_Surface * chs;
751
 
752
    chs = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32,
753
			   0x00FF0000,0x0000FF00,0x000000FF,0xFF000000);
754
 
755
    if (chs == NULL) {
756
      IMG_SetError("Out of memory");
757
      goto done;
758
    }
759
    for (i = 0; i < chnls; i++) {
760
      //      printf ("CNLBLT %i\n", i);
761
      if (!channel [i]->selection) {
762
	create_channel_surface (chs, head->image_type, channel [i]->color, channel [i]->opacity);
763
	SDL_BlitSurface (chs, NULL, surface, NULL);
764
      }
765
      free_xcf_channel (channel [i]);
766
    }
767
 
768
    SDL_FreeSurface (chs);
769
  }
770
 
771
 done:
772
  free_xcf_header (head);
773
  if ( read_error ) {
774
    SDL_FreeSurface(surface);
775
    IMG_SetError("Error reading XCF data");
776
    surface = NULL;
777
  }
778
 
779
  return(surface);
780
}
781
 
782
#else
783
 
784
/* See if an image is contained in a data source */
785
int IMG_isXCF(SDL_RWops *src)
786
{
787
  return(0);
788
}
789
 
790
/* Load a XCF type image from an SDL datasource */
791
SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src)
792
{
793
  return(NULL);
794
}
795
 
796
#endif /* LOAD_XCF */