IMG_xcf.c 18 KB

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