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