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