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