PageRenderTime 51ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/ExtLibs/wxWidgets/src/common/imagiff.cpp

https://bitbucket.org/lennonchan/cafu
C++ | 792 lines | 561 code | 137 blank | 94 comment | 145 complexity | 43788bfee99e3692a36cbbd01cf3fe4e MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: src/common/imagiff.cpp
  3. // Purpose: wxImage handler for Amiga IFF images
  4. // Author: Steffen Gutmann, Thomas Meyer
  5. // RCS-ID: $Id$
  6. // Copyright: (c) Steffen Gutmann, 2002
  7. // Licence: wxWindows licence
  8. /////////////////////////////////////////////////////////////////////////////
  9. // Parts of this source are based on the iff loading algorithm found
  10. // in xviff.c. Permission by the original author, Thomas Meyer, and
  11. // by the author of xv, John Bradley for using the iff loading part
  12. // in wxWidgets has been gratefully given.
  13. // For compilers that support precompilation, includes "wx.h".
  14. #include "wx/wxprec.h"
  15. #ifdef __BORLANDC__
  16. #pragma hdrstop
  17. #endif
  18. #if wxUSE_IMAGE && wxUSE_IFF
  19. #ifndef WX_PRECOMP
  20. #include "wx/log.h"
  21. #include "wx/intl.h"
  22. #endif
  23. #include "wx/imagiff.h"
  24. #include "wx/wfstream.h"
  25. #if wxUSE_PALETTE
  26. #include "wx/palette.h"
  27. #endif // wxUSE_PALETTE
  28. #include <stdlib.h>
  29. #include <string.h>
  30. // --------------------------------------------------------------------------
  31. // Constants
  32. // --------------------------------------------------------------------------
  33. // Error codes:
  34. // Note that the error code wxIFF_TRUNCATED means that the image itself
  35. // is most probably OK, but the decoder didn't reach the end of the data
  36. // stream; this means that if it was not reading directly from file,
  37. // the stream will not be correctly positioned.
  38. //
  39. enum
  40. {
  41. wxIFF_OK = 0, /* everything was OK */
  42. wxIFF_INVFORMAT, /* error in iff header */
  43. wxIFF_MEMERR, /* error allocating memory */
  44. wxIFF_TRUNCATED /* file appears to be truncated */
  45. };
  46. // --------------------------------------------------------------------------
  47. // wxIFFDecoder class
  48. // --------------------------------------------------------------------------
  49. // internal class for storing IFF image data
  50. class IFFImage
  51. {
  52. public:
  53. unsigned int w; /* width */
  54. unsigned int h; /* height */
  55. int transparent; /* transparent color (-1 = none) */
  56. int colors; /* number of colors */
  57. unsigned char *p; /* bitmap */
  58. unsigned char *pal; /* palette */
  59. IFFImage() : w(0), h(0), colors(0), p(0), pal(0) {}
  60. ~IFFImage() { delete [] p; delete [] pal; }
  61. };
  62. class WXDLLEXPORT wxIFFDecoder
  63. {
  64. private:
  65. IFFImage *m_image; // image data
  66. wxInputStream *m_f; // input stream
  67. unsigned char *databuf;
  68. unsigned char *picptr;
  69. unsigned char *decomp_mem;
  70. void Destroy();
  71. public:
  72. // get data of current frame
  73. unsigned char* GetData() const;
  74. unsigned char* GetPalette() const;
  75. int GetNumColors() const;
  76. unsigned int GetWidth() const;
  77. unsigned int GetHeight() const;
  78. int GetTransparentColour() const;
  79. // constructor, destructor, etc.
  80. wxIFFDecoder(wxInputStream *s);
  81. ~wxIFFDecoder() { Destroy(); }
  82. // NOTE: this function modifies the current stream position
  83. bool CanRead();
  84. int ReadIFF();
  85. bool ConvertToImage(wxImage *image) const;
  86. };
  87. //---------------------------------------------------------------------------
  88. // wxIFFDecoder constructor and destructor
  89. //---------------------------------------------------------------------------
  90. wxIFFDecoder::wxIFFDecoder(wxInputStream *s)
  91. {
  92. m_f = s;
  93. m_image = 0;
  94. databuf = 0;
  95. decomp_mem = 0;
  96. }
  97. void wxIFFDecoder::Destroy()
  98. {
  99. wxDELETE(m_image);
  100. wxDELETEA(databuf);
  101. wxDELETEA(decomp_mem);
  102. }
  103. //---------------------------------------------------------------------------
  104. // Convert this image to a wxImage object
  105. //---------------------------------------------------------------------------
  106. // This function was designed by Vaclav Slavik
  107. bool wxIFFDecoder::ConvertToImage(wxImage *image) const
  108. {
  109. // just in case...
  110. image->Destroy();
  111. // create the image
  112. image->Create(GetWidth(), GetHeight());
  113. if (!image->IsOk())
  114. return false;
  115. unsigned char *pal = GetPalette();
  116. unsigned char *src = GetData();
  117. unsigned char *dst = image->GetData();
  118. int colors = GetNumColors();
  119. int transparent = GetTransparentColour();
  120. long i;
  121. // set transparent colour mask
  122. if (transparent != -1)
  123. {
  124. for (i = 0; i < colors; i++)
  125. {
  126. if ((pal[3 * i + 0] == 255) &&
  127. (pal[3 * i + 1] == 0) &&
  128. (pal[3 * i + 2] == 255))
  129. {
  130. pal[3 * i + 2] = 254;
  131. }
  132. }
  133. pal[3 * transparent + 0] = 255,
  134. pal[3 * transparent + 1] = 0,
  135. pal[3 * transparent + 2] = 255;
  136. image->SetMaskColour(255, 0, 255);
  137. }
  138. else
  139. image->SetMask(false);
  140. #if wxUSE_PALETTE
  141. if (pal && colors > 0)
  142. {
  143. unsigned char* r = new unsigned char[colors];
  144. unsigned char* g = new unsigned char[colors];
  145. unsigned char* b = new unsigned char[colors];
  146. for (i = 0; i < colors; i++)
  147. {
  148. r[i] = pal[3*i + 0];
  149. g[i] = pal[3*i + 1];
  150. b[i] = pal[3*i + 2];
  151. }
  152. image->SetPalette(wxPalette(colors, r, g, b));
  153. delete [] r;
  154. delete [] g;
  155. delete [] b;
  156. }
  157. #endif // wxUSE_PALETTE
  158. // copy image data
  159. for (i = 0; i < (long)(GetWidth() * GetHeight()); i++, src += 3, dst += 3)
  160. {
  161. dst[0] = src[0];
  162. dst[1] = src[1];
  163. dst[2] = src[2];
  164. }
  165. return true;
  166. }
  167. //---------------------------------------------------------------------------
  168. // Data accessors
  169. //---------------------------------------------------------------------------
  170. // Get data for current frame
  171. unsigned char* wxIFFDecoder::GetData() const { return (m_image->p); }
  172. unsigned char* wxIFFDecoder::GetPalette() const { return (m_image->pal); }
  173. int wxIFFDecoder::GetNumColors() const { return m_image->colors; }
  174. unsigned int wxIFFDecoder::GetWidth() const { return (m_image->w); }
  175. unsigned int wxIFFDecoder::GetHeight() const { return (m_image->h); }
  176. int wxIFFDecoder::GetTransparentColour() const { return m_image->transparent; }
  177. //---------------------------------------------------------------------------
  178. // IFF reading and decoding
  179. //---------------------------------------------------------------------------
  180. //
  181. // CanRead:
  182. // Returns true if the file looks like a valid IFF, false otherwise.
  183. //
  184. bool wxIFFDecoder::CanRead()
  185. {
  186. unsigned char buf[12];
  187. if ( !m_f->Read(buf, WXSIZEOF(buf)) )
  188. return false;
  189. return (memcmp(buf, "FORM", 4) == 0) && (memcmp(buf+8, "ILBM", 4) == 0);
  190. }
  191. // ReadIFF:
  192. // Based on xv source code by Thomas Meyer
  193. // Permission for use in wxWidgets has been gratefully given.
  194. typedef unsigned char byte;
  195. #define IFFDEBUG 0
  196. /*************************************************************************
  197. void decomprle(source, destination, source length, buffer size)
  198. Decompress run-length encoded data from source to destination. Terminates
  199. when source is decoded completely or destination buffer is full.
  200. The decruncher is as optimized as I could make it, without risking
  201. safety in case of corrupt BODY chunks.
  202. **************************************************************************/
  203. static void decomprle(const byte *sptr, byte *dptr, long slen, long dlen)
  204. {
  205. byte codeByte, dataByte;
  206. while ((slen > 0) && (dlen > 0)) {
  207. // read control byte
  208. codeByte = *sptr++;
  209. if (codeByte < 0x80) {
  210. codeByte++;
  211. if ((slen > (long) codeByte) && (dlen >= (long) codeByte)) {
  212. slen -= codeByte + 1;
  213. dlen -= codeByte;
  214. while (codeByte > 0) {
  215. *dptr++ = *sptr++;
  216. codeByte--;
  217. }
  218. }
  219. else slen = 0;
  220. }
  221. else if (codeByte > 0x80) {
  222. codeByte = 0x81 - (codeByte & 0x7f);
  223. if ((slen > (long) 0) && (dlen >= (long) codeByte)) {
  224. dataByte = *sptr++;
  225. slen -= 2;
  226. dlen -= codeByte;
  227. while (codeByte > 0) {
  228. *dptr++ = dataByte;
  229. codeByte--;
  230. }
  231. }
  232. else slen = 0;
  233. }
  234. }
  235. }
  236. /******************************************/
  237. static unsigned int iff_getword(const byte *ptr)
  238. {
  239. unsigned int v;
  240. v = *ptr++;
  241. v = (v << 8) + *ptr;
  242. return v;
  243. }
  244. /******************************************/
  245. static unsigned long iff_getlong(const byte *ptr)
  246. {
  247. unsigned long l;
  248. l = *ptr++;
  249. l = (l << 8) + *ptr++;
  250. l = (l << 8) + *ptr++;
  251. l = (l << 8) + *ptr;
  252. return l;
  253. }
  254. // Define internal ILBM types
  255. #define ILBM_NORMAL 0
  256. #define ILBM_EHB 1
  257. #define ILBM_HAM 2
  258. #define ILBM_HAM8 3
  259. #define ILBM_24BIT 4
  260. int wxIFFDecoder::ReadIFF()
  261. {
  262. Destroy();
  263. m_image = new IFFImage();
  264. if (m_image == 0) {
  265. Destroy();
  266. return wxIFF_MEMERR;
  267. }
  268. // compute file length
  269. wxFileOffset currentPos = m_f->TellI();
  270. if (m_f->SeekI(0, wxFromEnd) == wxInvalidOffset) {
  271. Destroy();
  272. return wxIFF_MEMERR;
  273. }
  274. long filesize = m_f->TellI();
  275. if (m_f->SeekI(currentPos, wxFromStart) == wxInvalidOffset) {
  276. Destroy();
  277. return wxIFF_MEMERR;
  278. }
  279. // allocate memory for complete file
  280. if ((databuf = new byte[filesize]) == 0) {
  281. Destroy();
  282. return wxIFF_MEMERR;
  283. }
  284. m_f->Read(databuf, filesize);
  285. const byte *dataend = databuf + filesize;
  286. // initialize work pointer. used to trace the buffer for IFF chunks
  287. const byte *dataptr = databuf;
  288. // check for minmal size
  289. if (dataptr + 12 > dataend) {
  290. Destroy();
  291. return wxIFF_INVFORMAT;
  292. }
  293. // check if we really got an IFF file
  294. if (strncmp((char *)dataptr, "FORM", 4) != 0) {
  295. Destroy();
  296. return wxIFF_INVFORMAT;
  297. }
  298. dataptr = dataptr + 8; // skip ID and length of FORM
  299. // check if the IFF file is an ILBM (picture) file
  300. if (strncmp((char *) dataptr, "ILBM", 4) != 0) {
  301. Destroy();
  302. return wxIFF_INVFORMAT;
  303. }
  304. wxLogTrace(wxT("iff"), wxT("IFF ILBM file recognized"));
  305. dataptr = dataptr + 4; // skip ID
  306. //
  307. // main decoding loop. searches IFF chunks and handles them.
  308. // terminates when BODY chunk was found or dataptr ran over end of file
  309. //
  310. bool BMHDok = false, CAMGok = false;
  311. int bmhd_width = 0, bmhd_height = 0, bmhd_bitplanes = 0, bmhd_transcol = -1;
  312. byte bmhd_compression = 0;
  313. long camg_viewmode = 0;
  314. int colors = 0;
  315. while (dataptr + 8 <= dataend) {
  316. // get chunk length and make even
  317. long chunkLen = (iff_getlong(dataptr + 4) + 1) & 0xfffffffe;
  318. if (chunkLen < 0) { // format error?
  319. break;
  320. }
  321. bool truncated = (dataptr + 8 + chunkLen > dataend);
  322. if (strncmp((char *)dataptr, "BMHD", 4) == 0) { // BMHD chunk?
  323. if (chunkLen < 12 + 2 || truncated) {
  324. break;
  325. }
  326. bmhd_width = iff_getword(dataptr + 8); // width of picture
  327. bmhd_height= iff_getword(dataptr + 8 + 2); // height of picture
  328. bmhd_bitplanes = *(dataptr + 8 + 8); // # of bitplanes
  329. // bmhd_masking = *(dataptr + 8 + 9); -- unused currently
  330. bmhd_compression = *(dataptr + 8 + 10); // get compression
  331. bmhd_transcol = iff_getword(dataptr + 8 + 12);
  332. BMHDok = true; // got BMHD
  333. dataptr += 8 + chunkLen; // to next chunk
  334. }
  335. else if (strncmp((char *)dataptr, "CMAP", 4) == 0) { // CMAP ?
  336. if (truncated) {
  337. break;
  338. }
  339. const byte *cmapptr = dataptr + 8;
  340. colors = chunkLen / 3; // calc no of colors
  341. wxDELETE(m_image->pal);
  342. m_image->colors = colors;
  343. if (colors > 0) {
  344. m_image->pal = new byte[3*colors];
  345. if (!m_image->pal) {
  346. Destroy();
  347. return wxIFF_MEMERR;
  348. }
  349. // copy colors to color map
  350. for (int i=0; i < colors; i++) {
  351. m_image->pal[3*i + 0] = *cmapptr++;
  352. m_image->pal[3*i + 1] = *cmapptr++;
  353. m_image->pal[3*i + 2] = *cmapptr++;
  354. }
  355. }
  356. wxLogTrace(wxT("iff"), wxT("Read %d colors from IFF file."),
  357. colors);
  358. dataptr += 8 + chunkLen; // to next chunk
  359. } else if (strncmp((char *)dataptr, "CAMG", 4) == 0) { // CAMG ?
  360. if (chunkLen < 4 || truncated) {
  361. break;
  362. }
  363. camg_viewmode = iff_getlong(dataptr + 8); // get viewmodes
  364. CAMGok = true; // got CAMG
  365. dataptr += 8 + chunkLen; // to next chunk
  366. }
  367. else if (strncmp((char *)dataptr, "BODY", 4) == 0) { // BODY ?
  368. if (!BMHDok) { // BMHD found?
  369. break;
  370. }
  371. const byte *bodyptr = dataptr + 8; // -> BODY data
  372. if (truncated) {
  373. chunkLen = dataend - dataptr;
  374. }
  375. //
  376. // if BODY is compressed, allocate buffer for decrunched BODY
  377. // and decompress it (run length encoding)
  378. //
  379. if (bmhd_compression == 1) {
  380. // calc size of decrunch buffer - (size of the actual pic.
  381. // decompressed in interleaved Amiga bitplane format)
  382. size_t decomp_bufsize = (((bmhd_width + 15) >> 4) << 1)
  383. * bmhd_height * bmhd_bitplanes;
  384. if ((decomp_mem = new byte[decomp_bufsize]) == 0) {
  385. Destroy();
  386. return wxIFF_MEMERR;
  387. }
  388. decomprle(bodyptr, decomp_mem, chunkLen, decomp_bufsize);
  389. bodyptr = decomp_mem; // -> uncompressed BODY
  390. chunkLen = decomp_bufsize;
  391. wxDELETEA(databuf);
  392. }
  393. // the following determines the type of the ILBM file.
  394. // it's either NORMAL, EHB, HAM, HAM8 or 24BIT
  395. int fmt = ILBM_NORMAL; // assume normal ILBM
  396. if (bmhd_bitplanes == 24) {
  397. fmt = ILBM_24BIT;
  398. } else if (bmhd_bitplanes == 8) {
  399. if (CAMGok && (camg_viewmode & 0x800)) {
  400. fmt = ILBM_HAM8;
  401. }
  402. } else if ((bmhd_bitplanes > 5) && CAMGok) {
  403. if (camg_viewmode & 0x80) {
  404. fmt = ILBM_EHB;
  405. } else if (camg_viewmode & 0x800) {
  406. fmt = ILBM_HAM;
  407. }
  408. }
  409. wxLogTrace(wxT("iff"),
  410. wxT("LoadIFF: %s %dx%d, planes=%d (%d cols), comp=%d"),
  411. (fmt==ILBM_NORMAL) ? "Normal ILBM" :
  412. (fmt==ILBM_HAM) ? "HAM ILBM" :
  413. (fmt==ILBM_HAM8) ? "HAM8 ILBM" :
  414. (fmt==ILBM_EHB) ? "EHB ILBM" :
  415. (fmt==ILBM_24BIT) ? "24BIT ILBM" : "unknown ILBM",
  416. bmhd_width, bmhd_height, bmhd_bitplanes,
  417. 1<<bmhd_bitplanes, bmhd_compression);
  418. if ((fmt==ILBM_NORMAL) || (fmt==ILBM_EHB) || (fmt==ILBM_HAM)) {
  419. wxLogTrace(wxT("iff"),
  420. wxT("Converting CMAP from normal ILBM CMAP"));
  421. switch(fmt) {
  422. case ILBM_NORMAL: colors = 1 << bmhd_bitplanes; break;
  423. case ILBM_EHB: colors = 32*2; break;
  424. case ILBM_HAM: colors = 16; break;
  425. }
  426. if (colors > m_image->colors) {
  427. byte *pal = new byte[colors*3];
  428. if (!pal) {
  429. Destroy();
  430. return wxIFF_MEMERR;
  431. }
  432. int i;
  433. for (i = 0; i < m_image->colors; i++) {
  434. pal[3*i + 0] = m_image->pal[3*i + 0];
  435. pal[3*i + 1] = m_image->pal[3*i + 1];
  436. pal[3*i + 2] = m_image->pal[3*i + 2];
  437. }
  438. for (; i < colors; i++) {
  439. pal[3*i + 0] = 0;
  440. pal[3*i + 1] = 0;
  441. pal[3*i + 2] = 0;
  442. }
  443. delete m_image->pal;
  444. m_image->pal = pal;
  445. m_image->colors = colors;
  446. }
  447. for (int i=0; i < colors; i++) {
  448. m_image->pal[3*i + 0] = (m_image->pal[3*i + 0] >> 4) * 17;
  449. m_image->pal[3*i + 1] = (m_image->pal[3*i + 1] >> 4) * 17;
  450. m_image->pal[3*i + 2] = (m_image->pal[3*i + 2] >> 4) * 17;
  451. }
  452. }
  453. m_image->p = new byte[bmhd_width * bmhd_height * 3];
  454. byte *picptr = m_image->p;
  455. if (!picptr) {
  456. Destroy();
  457. return wxIFF_MEMERR;
  458. }
  459. byte *pal = m_image->pal;
  460. int lineskip = ((bmhd_width + 15) >> 4) << 1;
  461. int height = chunkLen / (lineskip * bmhd_bitplanes);
  462. if (bmhd_height < height) {
  463. height = bmhd_height;
  464. }
  465. if (fmt == ILBM_HAM || fmt == ILBM_HAM8 || fmt == ILBM_24BIT) {
  466. byte *pic = picptr;
  467. const byte *workptr = bodyptr;
  468. for (int i=0; i < height; i++) {
  469. byte bitmsk = 0x80;
  470. const byte *workptr2 = workptr;
  471. // at start of each line, init RGB values to background
  472. byte rval = pal[0];
  473. byte gval = pal[1];
  474. byte bval = pal[2];
  475. for (int j=0; j < bmhd_width; j++) {
  476. long col = 0;
  477. long colbit = 1;
  478. const byte *workptr3 = workptr2;
  479. for (int k=0; k < bmhd_bitplanes; k++) {
  480. if (*workptr3 & bitmsk) {
  481. col += colbit;
  482. }
  483. workptr3 += lineskip;
  484. colbit <<= 1;
  485. }
  486. if (fmt==ILBM_HAM) {
  487. int c = (col & 0x0f);
  488. switch (col & 0x30) {
  489. case 0x00: if (c >= 0 && c < colors) {
  490. rval = pal[3*c + 0];
  491. gval = pal[3*c + 1];
  492. bval = pal[3*c + 2];
  493. }
  494. break;
  495. case 0x10: bval = c * 17;
  496. break;
  497. case 0x20: rval = c * 17;
  498. break;
  499. case 0x30: gval = c * 17;
  500. break;
  501. }
  502. } else if (fmt == ILBM_HAM8) {
  503. int c = (col & 0x3f);
  504. switch(col & 0xc0) {
  505. case 0x00: if (c >= 0 && c < colors) {
  506. rval = pal[3*c + 0];
  507. gval = pal[3*c + 1];
  508. bval = pal[3*c + 2];
  509. }
  510. break;
  511. case 0x40: bval = (bval & 3) | (c << 2);
  512. break;
  513. case 0x80: rval = (rval & 3) | (c << 2);
  514. break;
  515. case 0xc0: gval = (rval & 3) | (c << 2);
  516. }
  517. } else {
  518. rval = col & 0xff;
  519. gval = (col >> 8) & 0xff;
  520. bval = (col >> 16) & 0xff;
  521. }
  522. *pic++ = rval;
  523. *pic++ = gval;
  524. *pic++ = bval;
  525. bitmsk = bitmsk >> 1;
  526. if (bitmsk == 0) {
  527. bitmsk = 0x80;
  528. workptr2++;
  529. }
  530. }
  531. workptr += lineskip * bmhd_bitplanes;
  532. }
  533. } else if ((fmt == ILBM_NORMAL) || (fmt == ILBM_EHB)) {
  534. if (fmt == ILBM_EHB) {
  535. wxLogTrace(wxT("iff"), wxT("Doubling CMAP for EHB mode"));
  536. for (int i=0; i<32; i++) {
  537. pal[3*(i + 32) + 0] = pal[3*i + 0] >> 1;
  538. pal[3*(i + 32) + 1] = pal[3*i + 1] >> 1;
  539. pal[3*(i + 32) + 2] = pal[3*i + 2] >> 1;
  540. }
  541. }
  542. byte *pic = picptr; // ptr to buffer
  543. const byte *workptr = bodyptr; // ptr to pic, planar format
  544. if (bmhd_height < height) {
  545. height = bmhd_height;
  546. }
  547. for (int i=0; i < height; i++) {
  548. byte bitmsk = 0x80; // left most bit (mask)
  549. const byte *workptr2 = workptr; // work ptr to source
  550. for (int j=0; j < bmhd_width; j++) {
  551. long col = 0;
  552. long colbit = 1;
  553. const byte *workptr3 = workptr2; // 1st byte in 1st pln
  554. for (int k=0; k < bmhd_bitplanes; k++) {
  555. if (*workptr3 & bitmsk) { // if bit set in this pln
  556. col = col + colbit; // add bit to chunky byte
  557. }
  558. workptr3 += lineskip; // go to next line
  559. colbit <<= 1; // shift color bit
  560. }
  561. if (col >= 0 && col < colors) {
  562. pic[0] = pal[3*col + 0];
  563. pic[1] = pal[3*col + 1];
  564. pic[2] = pal[3*col + 2];
  565. } else {
  566. pic[0] = pic[1] = pic[2] = 0;
  567. }
  568. pic += 3;
  569. bitmsk = bitmsk >> 1; // shift mask to next bit
  570. if (bitmsk == 0) { // if mask is zero
  571. bitmsk = 0x80; // reset mask
  572. workptr2++; // mv ptr to next byte
  573. }
  574. }
  575. workptr += lineskip * bmhd_bitplanes; // to next line
  576. }
  577. } else {
  578. break; // unknown format
  579. }
  580. m_image->w = bmhd_width;
  581. m_image->h = height;
  582. m_image->transparent = bmhd_transcol;
  583. wxLogTrace(wxT("iff"), wxT("Loaded IFF picture %s"),
  584. truncated? "truncated" : "completely");
  585. return (truncated? wxIFF_TRUNCATED : wxIFF_OK);
  586. } else {
  587. wxLogTrace(wxT("iff"), wxT("Skipping unknown chunk '%c%c%c%c'"),
  588. *dataptr, *(dataptr+1), *(dataptr+2), *(dataptr+3));
  589. dataptr = dataptr + 8 + chunkLen; // skip unknown chunk
  590. }
  591. }
  592. Destroy();
  593. return wxIFF_INVFORMAT;
  594. }
  595. //-----------------------------------------------------------------------------
  596. // wxIFFHandler
  597. //-----------------------------------------------------------------------------
  598. IMPLEMENT_DYNAMIC_CLASS(wxIFFHandler, wxImageHandler)
  599. #if wxUSE_STREAMS
  600. bool wxIFFHandler::LoadFile(wxImage *image, wxInputStream& stream,
  601. bool verbose, int WXUNUSED(index))
  602. {
  603. wxIFFDecoder *decod;
  604. int error;
  605. bool ok;
  606. decod = new wxIFFDecoder(&stream);
  607. error = decod->ReadIFF();
  608. if ((error != wxIFF_OK) && (error != wxIFF_TRUNCATED))
  609. {
  610. if (verbose)
  611. {
  612. switch (error)
  613. {
  614. case wxIFF_INVFORMAT:
  615. wxLogError(_("IFF: error in IFF image format."));
  616. break;
  617. case wxIFF_MEMERR:
  618. wxLogError(_("IFF: not enough memory."));
  619. break;
  620. default:
  621. wxLogError(_("IFF: unknown error!!!"));
  622. break;
  623. }
  624. }
  625. delete decod;
  626. return false;
  627. }
  628. if ((error == wxIFF_TRUNCATED) && verbose)
  629. {
  630. wxLogError(_("IFF: data stream seems to be truncated."));
  631. /* go on; image data is OK */
  632. }
  633. ok = decod->ConvertToImage(image);
  634. delete decod;
  635. return ok;
  636. }
  637. bool wxIFFHandler::SaveFile(wxImage * WXUNUSED(image),
  638. wxOutputStream& WXUNUSED(stream), bool verbose)
  639. {
  640. if (verbose)
  641. {
  642. wxLogDebug(wxT("IFF: the handler is read-only!!"));
  643. }
  644. return false;
  645. }
  646. bool wxIFFHandler::DoCanRead(wxInputStream& stream)
  647. {
  648. wxIFFDecoder decod(&stream);
  649. return decod.CanRead();
  650. // it's ok to modify the stream position here
  651. }
  652. #endif // wxUSE_STREAMS
  653. #endif // wxUSE_IFF