IMG_xcf.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  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 = SDL_RWread (src, t, 1, len);
  387. data = (unsigned char *) malloc (x*y*bpp);
  388. for (i = 0; i < bpp; i++) {
  389. d = data + i;
  390. size = x*y;
  391. count = 0;
  392. while (size > 0) {
  393. val = *t++;
  394. length = val;
  395. if (length >= 128) {
  396. length = 255 - (length - 1);
  397. if (length == 128) {
  398. length = (*t << 8) + t[1];
  399. t += 2;
  400. }
  401. count += length;
  402. size -= length;
  403. while (length-- > 0) {
  404. *d = *t++;
  405. d += bpp;
  406. }
  407. }
  408. else {
  409. length += 1;
  410. if (length == 128) {
  411. length = (*t << 8) + t[1];
  412. t += 2;
  413. }
  414. count += length;
  415. size -= length;
  416. val = *t++;
  417. for (j = 0; j < length; j++) {
  418. *d = val;
  419. d += bpp;
  420. }
  421. }
  422. }
  423. }
  424. free (load);
  425. return (data);
  426. }
  427. static Uint32 rgb2grey (Uint32 a) {
  428. Uint8 l;
  429. l = (Uint8)(0.2990 * ((a && 0x00FF0000) >> 16)
  430. + 0.5870 * ((a && 0x0000FF00) >> 8)
  431. + 0.1140 * ((a && 0x000000FF)));
  432. return (l << 16) | (l << 8) | l;
  433. }
  434. void create_channel_surface (SDL_Surface * surf, xcf_image_type itype, Uint32 color, Uint32 opacity) {
  435. Uint32 c = 0;
  436. switch (itype) {
  437. case IMAGE_RGB:
  438. case IMAGE_INDEXED:
  439. c = opacity | color;
  440. break;
  441. case IMAGE_GREYSCALE:
  442. c = opacity | rgb2grey (color);
  443. break;
  444. }
  445. SDL_FillRect (surf, NULL, c);
  446. }
  447. int do_layer_surface (SDL_Surface * surface, SDL_RWops * src, xcf_header * head, xcf_layer * layer, load_tile_type load_tile) {
  448. xcf_hierarchy * hierarchy;
  449. xcf_level * level;
  450. unsigned char * tile;
  451. Uint8 * p8;
  452. Uint16 * p16;
  453. Uint32 * p;
  454. unsigned int x, y, tx, ty, ox, oy, i, j;
  455. Uint32 *row;
  456. SDL_RWseek (src, layer->hierarchy_file_offset, SEEK_SET);
  457. hierarchy = read_xcf_hierarchy (src);
  458. level = NULL;
  459. for (i = 0; hierarchy->level_file_offsets [i]; i++) {
  460. SDL_RWseek (src, hierarchy->level_file_offsets [i], SEEK_SET);
  461. level = read_xcf_level (src);
  462. ty = tx = 0;
  463. for (j = 0; level->tile_file_offsets [j]; j++) {
  464. SDL_RWseek (src, level->tile_file_offsets [j], SEEK_SET);
  465. ox = tx+64 > level->width ? level->width % 64 : 64;
  466. oy = ty+64 > level->height ? level->height % 64 : 64;
  467. if (level->tile_file_offsets [j+1]) {
  468. tile = load_tile
  469. (src,
  470. level->tile_file_offsets [j+1] - level->tile_file_offsets [j],
  471. hierarchy->bpp,
  472. ox, oy);
  473. }
  474. else {
  475. tile = load_tile
  476. (src,
  477. ox*oy*6,
  478. hierarchy->bpp,
  479. ox, oy);
  480. }
  481. p8 = tile;
  482. p16 = (Uint16 *) p8;
  483. p = (Uint32 *) p8;
  484. for (y=ty; y < ty+oy; y++) {
  485. row = (Uint32 *)((Uint8 *)surface->pixels + y*surface->pitch + tx*4);
  486. switch (hierarchy->bpp) {
  487. case 4:
  488. for (x=tx; x < tx+ox; x++)
  489. *row++ = Swap32 (*p++);
  490. break;
  491. case 3:
  492. for (x=tx; x < tx+ox; x++) {
  493. *row = 0xFF000000;
  494. *row |= ((Uint32) *(p8++) << 16);
  495. *row |= ((Uint32) *(p8++) << 8);
  496. *row |= ((Uint32) *(p8++) << 0);
  497. row++;
  498. }
  499. break;
  500. case 2: // Indexed/Greyscale + Alpha
  501. switch (head->image_type) {
  502. case IMAGE_INDEXED:
  503. for (x=tx; x < tx+ox; x++) {
  504. *row = ((Uint32) (head->cm_map [*p8*3]) << 16);
  505. *row |= ((Uint32) (head->cm_map [*p8*3+1]) << 8);
  506. *row |= ((Uint32) (head->cm_map [*p8++*3+2]) << 0);
  507. *row |= ((Uint32) *p8++ << 24);;
  508. row++;
  509. }
  510. break;
  511. case IMAGE_GREYSCALE:
  512. for (x=tx; x < tx+ox; x++) {
  513. *row = ((Uint32) *p8 << 16);
  514. *row |= ((Uint32) *p8 << 8);
  515. *row |= ((Uint32) *p8++ << 0);
  516. *row |= ((Uint32) *p8++ << 24);;
  517. row++;
  518. }
  519. break;
  520. default:
  521. fprintf (stderr, "Unknown Gimp image type (%d)\n", head->image_type);
  522. return 1;
  523. }
  524. break;
  525. case 1: // Indexed/Greyscale
  526. switch (head->image_type) {
  527. case IMAGE_INDEXED:
  528. for (x = tx; x < tx+ox; x++) {
  529. *row++ = 0xFF000000
  530. | ((Uint32) (head->cm_map [*p8*3]) << 16)
  531. | ((Uint32) (head->cm_map [*p8*3+1]) << 8)
  532. | ((Uint32) (head->cm_map [*p8*3+2]) << 0);
  533. p8++;
  534. }
  535. break;
  536. case IMAGE_GREYSCALE:
  537. for (x=tx; x < tx+ox; x++) {
  538. *row++ = 0xFF000000
  539. | (((Uint32) (*p8)) << 16)
  540. | (((Uint32) (*p8)) << 8)
  541. | (((Uint32) (*p8++)) << 0);
  542. }
  543. break;
  544. default:
  545. fprintf (stderr, "Unknown Gimp image type (%d)\n", head->image_type);
  546. return 1;
  547. }
  548. break;
  549. }
  550. }
  551. tx += 64;
  552. if (tx >= level->width) {
  553. tx = 0;
  554. ty += 64;
  555. }
  556. if (ty >= level->height) {
  557. break;
  558. }
  559. free_xcf_tile (tile);
  560. }
  561. free_xcf_level (level);
  562. }
  563. free_xcf_hierarchy (hierarchy);
  564. return 0;
  565. }
  566. SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src) {
  567. SDL_Surface *surface, *lays;
  568. xcf_header * head;
  569. xcf_layer * layer;
  570. xcf_channel ** channel;
  571. int read_error, chnls, i, offsets;
  572. Uint32 offset, fp;
  573. unsigned char * (* load_tile) (SDL_RWops *, Uint32, int, int, int);
  574. /* Check to make sure we have something to do */
  575. if ( ! src ) {
  576. return NULL;
  577. }
  578. /* Initialize the data we will clean up when we're done */
  579. surface = NULL;
  580. read_error = 0;
  581. head = read_xcf_header (src);
  582. switch (head->compr) {
  583. case COMPR_NONE:
  584. load_tile = load_xcf_tile_none;
  585. break;
  586. case COMPR_RLE:
  587. load_tile = load_xcf_tile_rle;
  588. break;
  589. default:
  590. fprintf (stderr, "Unsupported Compression.\n");
  591. free_xcf_header (head);
  592. return NULL;
  593. }
  594. /* Create the surface of the appropriate type */
  595. surface = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32,
  596. 0x00FF0000,0x0000FF00,0x000000FF,0xFF000000);
  597. if ( surface == NULL ) {
  598. IMG_SetError("Out of memory");
  599. goto done;
  600. }
  601. head->layer_file_offsets = NULL;
  602. offsets = 0;
  603. while ((offset = SDL_ReadBE32 (src))) {
  604. head->layer_file_offsets = (Uint32 *) realloc (head->layer_file_offsets, sizeof (Uint32) * (offsets+1));
  605. head->layer_file_offsets [offsets] = offset;
  606. offsets++;
  607. }
  608. fp = SDL_RWtell (src);
  609. lays = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32,
  610. 0x00FF0000,0x0000FF00,0x000000FF,0xFF000000);
  611. if ( lays == NULL ) {
  612. IMG_SetError("Out of memory");
  613. goto done;
  614. }
  615. // Blit layers backwards, because Gimp saves them highest first
  616. for (i = offsets; i > 0; i--) {
  617. SDL_Rect rs, rd;
  618. SDL_RWseek (src, head->layer_file_offsets [i-1], SEEK_SET);
  619. layer = read_xcf_layer (src);
  620. do_layer_surface (lays, src, head, layer, load_tile);
  621. rs.x = 0;
  622. rs.y = 0;
  623. rs.w = layer->width;
  624. rs.h = layer->height;
  625. rd.x = layer->offset_x;
  626. rd.y = layer->offset_y;
  627. rd.w = layer->width;
  628. rd.h = layer->height;
  629. if (layer->visible)
  630. SDL_BlitSurface (lays, &rs, surface, &rd);
  631. free_xcf_layer (layer);
  632. }
  633. SDL_FreeSurface (lays);
  634. SDL_RWseek (src, fp, SEEK_SET);
  635. // read channels
  636. channel = NULL;
  637. chnls = 0;
  638. while ((offset = SDL_ReadBE32 (src))) {
  639. channel = (xcf_channel **) realloc (channel, sizeof (xcf_channel *) * (chnls+1));
  640. fp = SDL_RWtell (src);
  641. SDL_RWseek (src, offset, SEEK_SET);
  642. channel [chnls++] = (read_xcf_channel (src));
  643. SDL_RWseek (src, fp, SEEK_SET);
  644. }
  645. if (chnls) {
  646. SDL_Surface * chs;
  647. chs = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32,
  648. 0x00FF0000,0x0000FF00,0x000000FF,0xFF000000);
  649. if (chs == NULL) {
  650. IMG_SetError("Out of memory");
  651. goto done;
  652. }
  653. for (i = 0; i < chnls; i++) {
  654. // printf ("CNLBLT %i\n", i);
  655. if (!channel [i]->selection && channel [i]->visible) {
  656. create_channel_surface (chs, (xcf_image_type)(head->image_type), channel [i]->color, channel [i]->opacity);
  657. SDL_BlitSurface (chs, NULL, surface, NULL);
  658. }
  659. free_xcf_channel (channel [i]);
  660. }
  661. SDL_FreeSurface (chs);
  662. }
  663. done:
  664. free_xcf_header (head);
  665. if ( read_error ) {
  666. SDL_FreeSurface(surface);
  667. IMG_SetError("Error reading XCF data");
  668. surface = NULL;
  669. }
  670. return(surface);
  671. }