/[pcsx2_0.9.7]/trunk/3rdparty/wxWidgets/src/common/imagbmp.cpp
ViewVC logotype

Annotation of /trunk/3rdparty/wxWidgets/src/common/imagbmp.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years, 4 months ago) by william
File size: 46264 byte(s)
committing r3113 initial commit again...
1 william 31 /////////////////////////////////////////////////////////////////////////////
2     // Name: src/common/imagbmp.cpp
3     // Purpose: wxImage BMP,ICO and CUR handlers
4     // Author: Robert Roebling, Chris Elliott
5     // RCS-ID: $Id: imagbmp.cpp 54942 2008-08-03 00:23:38Z VZ $
6     // Copyright: (c) Robert Roebling, Chris Elliott
7     // Licence: wxWindows licence
8     /////////////////////////////////////////////////////////////////////////////
9    
10     // For compilers that support precompilation, includes "wx.h".
11     #include "wx/wxprec.h"
12    
13     #ifdef __BORLANDC__
14     #pragma hdrstop
15     #endif
16    
17     #if wxUSE_IMAGE
18    
19     #include "wx/imagbmp.h"
20    
21     #ifndef WX_PRECOMP
22     #ifdef __WXMSW__
23     #include "wx/msw/wrapwin.h"
24     #endif
25     #include "wx/log.h"
26     #include "wx/app.h"
27     #include "wx/bitmap.h"
28     #include "wx/palette.h"
29     #include "wx/intl.h"
30     #endif
31    
32     #include "wx/filefn.h"
33     #include "wx/wfstream.h"
34     #include "wx/quantize.h"
35     #include "wx/anidecod.h"
36    
37     // For memcpy
38     #include <string.h>
39    
40     #ifdef __SALFORDC__
41     #ifdef FAR
42     #undef FAR
43     #endif
44     #endif
45    
46     //-----------------------------------------------------------------------------
47     // wxBMPHandler
48     //-----------------------------------------------------------------------------
49    
50     IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler,wxImageHandler)
51    
52     #if wxUSE_STREAMS
53    
54     #ifndef BI_RGB
55     #define BI_RGB 0
56     #endif
57    
58     #ifndef BI_RLE8
59     #define BI_RLE8 1
60     #endif
61    
62     #ifndef BI_RLE4
63     #define BI_RLE4 2
64     #endif
65    
66     #ifndef BI_BITFIELDS
67     #define BI_BITFIELDS 3
68     #endif
69    
70     #define poffset (line * width * 3 + column * 3)
71    
72     bool wxBMPHandler::SaveFile(wxImage *image,
73     wxOutputStream& stream,
74     bool verbose)
75     {
76     return SaveDib(image, stream, verbose, true/*IsBmp*/, false/*IsMask*/);
77     }
78    
79     bool wxBMPHandler::SaveDib(wxImage *image,
80     wxOutputStream& stream,
81     bool verbose,
82     bool IsBmp,
83     bool IsMask)
84    
85     {
86     wxCHECK_MSG( image, false, _T("invalid pointer in wxBMPHandler::SaveFile") );
87    
88     if ( !image->Ok() )
89     {
90     if ( verbose )
91     wxLogError(_("BMP: Couldn't save invalid image."));
92     return false;
93     }
94    
95     // get the format of the BMP file to save, else use 24bpp
96     unsigned format = wxBMP_24BPP;
97     if ( image->HasOption(wxIMAGE_OPTION_BMP_FORMAT) )
98     format = image->GetOptionInt(wxIMAGE_OPTION_BMP_FORMAT);
99    
100     wxUint16 bpp; // # of bits per pixel
101     int palette_size; // # of color map entries, ie. 2^bpp colors
102    
103     // set the bpp and appropriate palette_size, and do additional checks
104     if ( (format == wxBMP_1BPP) || (format == wxBMP_1BPP_BW) )
105     {
106     bpp = 1;
107     palette_size = 2;
108     }
109     else if ( format == wxBMP_4BPP )
110     {
111     bpp = 4;
112     palette_size = 16;
113     }
114     else if ( (format == wxBMP_8BPP) || (format == wxBMP_8BPP_GREY) ||
115     (format == wxBMP_8BPP_RED) || (format == wxBMP_8BPP_PALETTE) )
116     {
117     // need to set a wxPalette to use this, HOW TO CHECK IF VALID, SIZE?
118     if ((format == wxBMP_8BPP_PALETTE)
119     #if wxUSE_PALETTE
120     && !image->HasPalette()
121     #endif // wxUSE_PALETTE
122     )
123     {
124     if ( verbose )
125     wxLogError(_("BMP: wxImage doesn't have own wxPalette."));
126     return false;
127     }
128     bpp = 8;
129     palette_size = 256;
130     }
131     else // you get 24bpp
132     {
133     format = wxBMP_24BPP;
134     bpp = 24;
135     palette_size = 0;
136     }
137    
138     unsigned width = image->GetWidth();
139     unsigned row_padding = (4 - int(width*bpp/8.0) % 4) % 4; // # bytes to pad to dword
140     unsigned row_width = int(width * bpp/8.0) + row_padding; // # of bytes per row
141    
142     struct
143     {
144     // BitmapHeader:
145     wxUint16 magic; // format magic, always 'BM'
146     wxUint32 filesize; // total file size, inc. headers
147     wxUint32 reserved; // for future use
148     wxUint32 data_offset; // image data offset in the file
149    
150     // BitmapInfoHeader:
151     wxUint32 bih_size; // 2nd part's size
152     wxUint32 width, height; // bitmap's dimensions
153     wxUint16 planes; // num of planes
154     wxUint16 bpp; // bits per pixel
155     wxUint32 compression; // compression method
156     wxUint32 size_of_bmp; // size of the bitmap
157     wxUint32 h_res, v_res; // image resolution in dpi
158     wxUint32 num_clrs; // number of colors used
159     wxUint32 num_signif_clrs;// number of significant colors
160     } hdr;
161    
162     wxUint32 hdr_size = 14/*BitmapHeader*/ + 40/*BitmapInfoHeader*/;
163    
164     hdr.magic = wxUINT16_SWAP_ON_BE(0x4D42/*'BM'*/);
165     hdr.filesize = wxUINT32_SWAP_ON_BE( hdr_size + palette_size*4 +
166     row_width * image->GetHeight() );
167     hdr.reserved = 0;
168     hdr.data_offset = wxUINT32_SWAP_ON_BE(hdr_size + palette_size*4);
169    
170     hdr.bih_size = wxUINT32_SWAP_ON_BE(hdr_size - 14);
171     hdr.width = wxUINT32_SWAP_ON_BE(image->GetWidth());
172     if ( IsBmp )
173     {
174     hdr.height = wxUINT32_SWAP_ON_BE(image->GetHeight());
175     }
176     else
177     {
178     hdr.height = wxUINT32_SWAP_ON_BE(2 * image->GetHeight());
179     }
180     hdr.planes = wxUINT16_SWAP_ON_BE(1); // always 1 plane
181     hdr.bpp = wxUINT16_SWAP_ON_BE(bpp);
182     hdr.compression = 0; // RGB uncompressed
183     hdr.size_of_bmp = wxUINT32_SWAP_ON_BE(row_width * image->GetHeight());
184     hdr.h_res = hdr.v_res = wxUINT32_SWAP_ON_BE(72); // 72dpi is standard
185     hdr.num_clrs = wxUINT32_SWAP_ON_BE(palette_size); // # colors in colormap
186     hdr.num_signif_clrs = 0; // all colors are significant
187    
188     if ( IsBmp )
189     {
190     if (// VS: looks ugly but compilers tend to do ugly things with structs,
191     // like aligning hdr.filesize's ofset to dword :(
192     // VZ: we should add padding then...
193     !stream.Write(&hdr.magic, 2) ||
194     !stream.Write(&hdr.filesize, 4) ||
195     !stream.Write(&hdr.reserved, 4) ||
196     !stream.Write(&hdr.data_offset, 4)
197     )
198     {
199     if (verbose)
200     wxLogError(_("BMP: Couldn't write the file (Bitmap) header."));
201     return false;
202     }
203     }
204     if ( !IsMask )
205     {
206     if (
207     !stream.Write(&hdr.bih_size, 4) ||
208     !stream.Write(&hdr.width, 4) ||
209     !stream.Write(&hdr.height, 4) ||
210     !stream.Write(&hdr.planes, 2) ||
211     !stream.Write(&hdr.bpp, 2) ||
212     !stream.Write(&hdr.compression, 4) ||
213     !stream.Write(&hdr.size_of_bmp, 4) ||
214     !stream.Write(&hdr.h_res, 4) ||
215     !stream.Write(&hdr.v_res, 4) ||
216     !stream.Write(&hdr.num_clrs, 4) ||
217     !stream.Write(&hdr.num_signif_clrs, 4)
218     )
219     {
220     if (verbose)
221     wxLogError(_("BMP: Couldn't write the file (BitmapInfo) header."));
222     return false;
223     }
224     }
225    
226     wxPalette *palette = NULL; // entries for quantized images
227     wxUint8 *rgbquad = NULL; // for the RGBQUAD bytes for the colormap
228     wxImage *q_image = NULL; // destination for quantized image
229    
230     // if <24bpp use quantization to reduce colors for *some* of the formats
231     if ( (format == wxBMP_1BPP) || (format == wxBMP_4BPP) ||
232     (format == wxBMP_8BPP) || (format == wxBMP_8BPP_PALETTE) )
233     {
234     // make a new palette and quantize the image
235     if (format != wxBMP_8BPP_PALETTE)
236     {
237     q_image = new wxImage();
238    
239     // I get a delete error using Quantize when desired colors > 236
240     int quantize = ((palette_size > 236) ? 236 : palette_size);
241     // fill the destination too, it gives much nicer 4bpp images
242     wxQuantize::Quantize( *image, *q_image, &palette, quantize, 0,
243     wxQUANTIZE_FILL_DESTINATION_IMAGE );
244     }
245     else
246     {
247     #if wxUSE_PALETTE
248     palette = new wxPalette(image->GetPalette());
249     #endif // wxUSE_PALETTE
250     }
251    
252     int i;
253     unsigned char r, g, b;
254     rgbquad = new wxUint8 [palette_size*4];
255    
256     for (i = 0; i < palette_size; i++)
257     {
258     #if wxUSE_PALETTE
259     if ( !palette->GetRGB(i, &r, &g, &b) )
260     #endif // wxUSE_PALETTE
261     r = g = b = 0;
262    
263     rgbquad[i*4] = b;
264     rgbquad[i*4+1] = g;
265     rgbquad[i*4+2] = r;
266     rgbquad[i*4+3] = 0;
267     }
268     }
269     // make a 256 entry greyscale colormap or 2 entry black & white
270     else if ( (format == wxBMP_8BPP_GREY) || (format == wxBMP_8BPP_RED) ||
271     (format == wxBMP_1BPP_BW) )
272     {
273     rgbquad = new wxUint8 [palette_size*4];
274    
275     for ( int i = 0; i < palette_size; i++ )
276     {
277     // if 1BPP_BW then the value should be either 0 or 255
278     wxUint8 c = (wxUint8)((i > 0) && (format == wxBMP_1BPP_BW) ? 255 : i);
279    
280     rgbquad[i*4] =
281     rgbquad[i*4+1] =
282     rgbquad[i*4+2] = c;
283     rgbquad[i*4+3] = 0;
284     }
285     }
286    
287     // if the colormap was made, then it needs to be written
288     if (rgbquad)
289     {
290     if ( !IsMask )
291     {
292     if ( !stream.Write(rgbquad, palette_size*4) )
293     {
294     if (verbose)
295     wxLogError(_("BMP: Couldn't write RGB color map."));
296     delete[] rgbquad;
297     #if wxUSE_PALETTE
298     delete palette;
299     #endif // wxUSE_PALETTE
300     delete q_image;
301     return false;
302     }
303     }
304     delete []rgbquad;
305     }
306    
307     // pointer to the image data, use quantized if available
308     wxUint8 *data = (wxUint8*) image->GetData();
309     if (q_image) if (q_image->Ok()) data = (wxUint8*) q_image->GetData();
310    
311     wxUint8 *buffer = new wxUint8[row_width];
312     memset(buffer, 0, row_width);
313     int y; unsigned x;
314     long int pixel;
315    
316     for (y = image->GetHeight() -1; y >= 0; y--)
317     {
318     if ( format == wxBMP_24BPP ) // 3 bytes per pixel red,green,blue
319     {
320     for ( x = 0; x < width; x++ )
321     {
322     pixel = 3*(y*width + x);
323    
324     buffer[3*x ] = data[pixel+2];
325     buffer[3*x + 1] = data[pixel+1];
326     buffer[3*x + 2] = data[pixel];
327     }
328     }
329     else if ((format == wxBMP_8BPP) || // 1 byte per pixel in color
330     (format == wxBMP_8BPP_PALETTE))
331     {
332     for (x = 0; x < width; x++)
333     {
334     pixel = 3*(y*width + x);
335     #if wxUSE_PALETTE
336     buffer[x] = (wxUint8)palette->GetPixel( data[pixel],
337     data[pixel+1],
338     data[pixel+2] );
339     #else
340     // FIXME: what should this be? use some std palette maybe?
341     buffer[x] = 0;
342     #endif // wxUSE_PALETTE
343     }
344     }
345     else if ( format == wxBMP_8BPP_GREY ) // 1 byte per pix, rgb ave to grey
346     {
347     for (x = 0; x < width; x++)
348     {
349     pixel = 3*(y*width + x);
350     buffer[x] = (wxUint8)(.299*data[pixel] +
351     .587*data[pixel+1] +
352     .114*data[pixel+2]);
353     }
354     }
355     else if ( format == wxBMP_8BPP_RED ) // 1 byte per pixel, red as greys
356     {
357     for (x = 0; x < width; x++)
358     {
359     buffer[x] = (wxUint8)data[3*(y*width + x)];
360     }
361     }
362     else if ( format == wxBMP_4BPP ) // 4 bpp in color
363     {
364     for (x = 0; x < width; x+=2)
365     {
366     pixel = 3*(y*width + x);
367    
368     // fill buffer, ignore if > width
369     #if wxUSE_PALETTE
370     buffer[x/2] = (wxUint8)(
371     ((wxUint8)palette->GetPixel(data[pixel],
372     data[pixel+1],
373     data[pixel+2]) << 4) |
374     (((x+1) > width)
375     ? 0
376     : ((wxUint8)palette->GetPixel(data[pixel+3],
377     data[pixel+4],
378     data[pixel+5]) )) );
379     #else
380     // FIXME: what should this be? use some std palette maybe?
381     buffer[x/2] = 0;
382     #endif // wxUSE_PALETTE
383     }
384     }
385     else if ( format == wxBMP_1BPP ) // 1 bpp in "color"
386     {
387     for (x = 0; x < width; x+=8)
388     {
389     pixel = 3*(y*width + x);
390    
391     #if wxUSE_PALETTE
392     buffer[x/8] = (wxUint8)(
393     ((wxUint8)palette->GetPixel(data[pixel], data[pixel+1], data[pixel+2]) << 7) |
394     (((x+1) > width) ? 0 : ((wxUint8)palette->GetPixel(data[pixel+3], data[pixel+4], data[pixel+5]) << 6)) |
395     (((x+2) > width) ? 0 : ((wxUint8)palette->GetPixel(data[pixel+6], data[pixel+7], data[pixel+8]) << 5)) |
396     (((x+3) > width) ? 0 : ((wxUint8)palette->GetPixel(data[pixel+9], data[pixel+10], data[pixel+11]) << 4)) |
397     (((x+4) > width) ? 0 : ((wxUint8)palette->GetPixel(data[pixel+12], data[pixel+13], data[pixel+14]) << 3)) |
398     (((x+5) > width) ? 0 : ((wxUint8)palette->GetPixel(data[pixel+15], data[pixel+16], data[pixel+17]) << 2)) |
399     (((x+6) > width) ? 0 : ((wxUint8)palette->GetPixel(data[pixel+18], data[pixel+19], data[pixel+20]) << 1)) |
400     (((x+7) > width) ? 0 : ((wxUint8)palette->GetPixel(data[pixel+21], data[pixel+22], data[pixel+23]) )) );
401     #else
402     // FIXME: what should this be? use some std palette maybe?
403     buffer[x/8] = 0;
404     #endif // wxUSE_PALETTE
405     }
406     }
407     else if ( format == wxBMP_1BPP_BW ) // 1 bpp B&W colormap from red color ONLY
408     {
409     for (x = 0; x < width; x+=8)
410     {
411     pixel = 3*(y*width + x);
412    
413     buffer[x/8] = (wxUint8)(
414     (((wxUint8)(data[pixel] /128.)) << 7) |
415     (((x+1) > width) ? 0 : (((wxUint8)(data[pixel+3] /128.)) << 6)) |
416     (((x+2) > width) ? 0 : (((wxUint8)(data[pixel+6] /128.)) << 5)) |
417     (((x+3) > width) ? 0 : (((wxUint8)(data[pixel+9] /128.)) << 4)) |
418     (((x+4) > width) ? 0 : (((wxUint8)(data[pixel+12]/128.)) << 3)) |
419     (((x+5) > width) ? 0 : (((wxUint8)(data[pixel+15]/128.)) << 2)) |
420     (((x+6) > width) ? 0 : (((wxUint8)(data[pixel+18]/128.)) << 1)) |
421     (((x+7) > width) ? 0 : (((wxUint8)(data[pixel+21]/128.)) )) );
422     }
423     }
424    
425     if ( !stream.Write(buffer, row_width) )
426     {
427     if (verbose)
428     wxLogError(_("BMP: Couldn't write data."));
429     delete[] buffer;
430     #if wxUSE_PALETTE
431     delete palette;
432     #endif // wxUSE_PALETTE
433     delete q_image;
434     return false;
435     }
436     }
437     delete[] buffer;
438     #if wxUSE_PALETTE
439     delete palette;
440     #endif // wxUSE_PALETTE
441     delete q_image;
442    
443     return true;
444     }
445    
446    
447     typedef struct
448     {
449     unsigned char r, g, b;
450     } _cmap;
451    
452     bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height,
453     int bpp, int ncolors, int comp,
454     wxFileOffset bmpOffset, wxInputStream& stream,
455     bool verbose, bool IsBmp, bool hasPalette)
456     {
457     wxInt32 aDword, rmask = 0, gmask = 0, bmask = 0, amask = 0;
458     int rshift = 0, gshift = 0, bshift = 0, ashift = 0;
459     int rbits = 0, gbits = 0, bbits = 0, abits = 0;
460     wxInt32 dbuf[4];
461     wxInt8 bbuf[4];
462     wxUint8 aByte;
463     wxUint16 aWord;
464    
465     // allocate space for palette if needed:
466     _cmap *cmap;
467    
468     if ( bpp < 16 )
469     {
470     cmap = new _cmap[ncolors];
471     if ( !cmap )
472     {
473     if (verbose)
474     wxLogError(_("BMP: Couldn't allocate memory."));
475     return false;
476     }
477     }
478     else
479     cmap = NULL;
480    
481     // destroy existing here instead of:
482     image->Destroy();
483     image->Create(width, height);
484    
485     unsigned char *ptr = image->GetData();
486    
487     if ( !ptr )
488     {
489     if ( verbose )
490     wxLogError( _("BMP: Couldn't allocate memory.") );
491     delete[] cmap;
492     return false;
493     }
494    
495     unsigned char *alpha;
496     if ( bpp == 32 )
497     {
498     // tell the image to allocate an alpha buffer
499     image->SetAlpha();
500     alpha = image->GetAlpha();
501     if ( !alpha )
502     {
503     if ( verbose )
504     wxLogError(_("BMP: Couldn't allocate memory."));
505     delete[] cmap;
506     return false;
507     }
508     }
509     else // no alpha
510     {
511     alpha = NULL;
512     }
513    
514     // Reading the palette, if it exists:
515     if ( bpp < 16 && ncolors != 0 )
516     {
517     unsigned char* r = new unsigned char[ncolors];
518     unsigned char* g = new unsigned char[ncolors];
519     unsigned char* b = new unsigned char[ncolors];
520     for (int j = 0; j < ncolors; j++)
521     {
522     if (hasPalette)
523     {
524     stream.Read(bbuf, 4);
525     cmap[j].b = bbuf[0];
526     cmap[j].g = bbuf[1];
527     cmap[j].r = bbuf[2];
528    
529     r[j] = cmap[j].r;
530     g[j] = cmap[j].g;
531     b[j] = cmap[j].b;
532     }
533     else
534     {
535     //used in reading .ico file mask
536     r[j] = cmap[j].r =
537     g[j] = cmap[j].g =
538     b[j] = cmap[j].b = ( j ? 255 : 0 );
539     }
540     }
541    
542     #if wxUSE_PALETTE
543     // Set the palette for the wxImage
544     image->SetPalette(wxPalette(ncolors, r, g, b));
545     #endif // wxUSE_PALETTE
546    
547     delete[] r;
548     delete[] g;
549     delete[] b;
550     }
551     else if ( bpp == 16 || bpp == 32 )
552     {
553     if ( comp == BI_BITFIELDS )
554     {
555     int bit = 0;
556     stream.Read(dbuf, 4 * 3);
557     rmask = wxINT32_SWAP_ON_BE(dbuf[0]);
558     gmask = wxINT32_SWAP_ON_BE(dbuf[1]);
559     bmask = wxINT32_SWAP_ON_BE(dbuf[2]);
560     // find shift amount (Least significant bit of mask)
561     for (bit = bpp-1; bit>=0; bit--)
562     {
563     if (bmask & (1 << bit))
564     bshift = bit;
565     if (gmask & (1 << bit))
566     gshift = bit;
567     if (rmask & (1 << bit))
568     rshift = bit;
569     }
570     // Find number of bits in mask (MSB-LSB+1)
571     for (bit = 0; bit < bpp; bit++)
572     {
573     if (bmask & (1 << bit))
574     bbits = bit-bshift+1;
575     if (gmask & (1 << bit))
576     gbits = bit-gshift+1;
577     if (rmask & (1 << bit))
578     rbits = bit-rshift+1;
579     }
580     }
581     else if ( bpp == 16 )
582     {
583     rmask = 0x7C00;
584     gmask = 0x03E0;
585     bmask = 0x001F;
586     rshift = 10;
587     gshift = 5;
588     bshift = 0;
589     rbits = 5;
590     gbits = 5;
591     bbits = 5;
592     }
593     else if ( bpp == 32 )
594     {
595     rmask = 0x00FF0000;
596     gmask = 0x0000FF00;
597     bmask = 0x000000FF;
598     amask = 0xFF000000;
599    
600     ashift = 24;
601     rshift = 16;
602     gshift = 8;
603     bshift = 0;
604     abits = 8;
605     rbits = 8;
606     gbits = 8;
607     bbits = 8;
608     }
609     }
610    
611     /*
612     * Reading the image data
613     */
614     if ( IsBmp )
615     stream.SeekI(bmpOffset); // else icon, just carry on
616    
617     unsigned char *data = ptr;
618    
619     /* set the whole image to the background color */
620     if ( bpp < 16 && (comp == BI_RLE4 || comp == BI_RLE8) )
621     {
622     for (int i = 0; i < width * height; i++)
623     {
624     *ptr++ = cmap[0].r;
625     *ptr++ = cmap[0].g;
626     *ptr++ = cmap[0].b;
627     }
628     ptr = data;
629     }
630    
631     int linesize = ((width * bpp + 31) / 32) * 4;
632    
633     /* BMPs are stored upside down */
634     for ( int line = (height - 1); line >= 0; line-- )
635     {
636     int linepos = 0;
637     for ( int column = 0; column < width ; )
638     {
639     if ( bpp < 16 )
640     {
641     linepos++;
642     aByte = stream.GetC();
643     if ( bpp == 1 )
644     {
645     for (int bit = 0; bit < 8 && column < width; bit++)
646     {
647     int index = ((aByte & (0x80 >> bit)) ? 1 : 0);
648     ptr[poffset] = cmap[index].r;
649     ptr[poffset + 1] = cmap[index].g;
650     ptr[poffset + 2] = cmap[index].b;
651     column++;
652     }
653     }
654     else if ( bpp == 4 )
655     {
656     if ( comp == BI_RLE4 )
657     {
658     wxUint8 first;
659     first = aByte;
660     aByte = stream.GetC();
661     if ( first == 0 )
662     {
663     if ( aByte == 0 )
664     {
665     if ( column > 0 )
666     column = width;
667     }
668     else if ( aByte == 1 )
669     {
670     column = width;
671     line = -1;
672     }
673     else if ( aByte == 2 )
674     {
675     aByte = stream.GetC();
676     column += aByte;
677     linepos = column * bpp / 4;
678     aByte = stream.GetC();
679     line -= aByte; // upside down
680     }
681     else
682     {
683     int absolute = aByte;
684     wxUint8 nibble[2] ;
685     int readBytes = 0 ;
686     for (int k = 0; k < absolute; k++)
687     {
688     if ( !(k % 2 ) )
689     {
690     ++readBytes ;
691     aByte = stream.GetC();
692     nibble[0] = (wxUint8)( (aByte & 0xF0) >> 4 ) ;
693     nibble[1] = (wxUint8)( aByte & 0x0F ) ;
694     }
695     ptr[poffset ] = cmap[nibble[k%2]].r;
696     ptr[poffset + 1] = cmap[nibble[k%2]].g;
697     ptr[poffset + 2] = cmap[nibble[k%2]].b;
698     column++;
699     if ( k % 2 )
700     linepos++;
701     }
702     if ( readBytes & 0x01 )
703     aByte = stream.GetC();
704     }
705     }
706     else
707     {
708     wxUint8 nibble[2] ;
709     nibble[0] = (wxUint8)( (aByte & 0xF0) >> 4 ) ;
710     nibble[1] = (wxUint8)( aByte & 0x0F ) ;
711    
712     for ( int l = 0; l < first && column < width; l++ )
713     {
714     ptr[poffset ] = cmap[nibble[l%2]].r;
715     ptr[poffset + 1] = cmap[nibble[l%2]].g;
716     ptr[poffset + 2] = cmap[nibble[l%2]].b;
717     column++;
718     if ( l % 2 )
719     linepos++;
720     }
721     }
722     }
723     else
724     {
725     for (int nibble = 0; nibble < 2 && column < width; nibble++)
726     {
727     int index = ((aByte & (0xF0 >> nibble * 4)) >> (!nibble * 4));
728     if ( index >= 16 )
729     index = 15;
730     ptr[poffset] = cmap[index].r;
731     ptr[poffset + 1] = cmap[index].g;
732     ptr[poffset + 2] = cmap[index].b;
733     column++;
734     }
735     }
736     }
737     else if ( bpp == 8 )
738     {
739     if ( comp == BI_RLE8 )
740     {
741     unsigned char first;
742     first = aByte;
743     aByte = stream.GetC();
744     if ( first == 0 )
745     {
746     if ( aByte == 0 )
747     {
748     /* column = width; */
749     }
750     else if ( aByte == 1 )
751     {
752     column = width;
753     line = -1;
754     }
755     else if ( aByte == 2 )
756     {
757     aByte = stream.GetC();
758     column += aByte;
759     linepos = column * bpp / 8;
760     aByte = stream.GetC();
761     line += aByte;
762     }
763     else
764     {
765     int absolute = aByte;
766     for (int k = 0; k < absolute; k++)
767     {
768     linepos++;
769     aByte = stream.GetC();
770     ptr[poffset ] = cmap[aByte].r;
771     ptr[poffset + 1] = cmap[aByte].g;
772     ptr[poffset + 2] = cmap[aByte].b;
773     column++;
774     }
775     if ( absolute & 0x01 )
776     aByte = stream.GetC();
777     }
778     }
779     else
780     {
781     for ( int l = 0; l < first && column < width; l++ )
782     {
783     ptr[poffset ] = cmap[aByte].r;
784     ptr[poffset + 1] = cmap[aByte].g;
785     ptr[poffset + 2] = cmap[aByte].b;
786     column++;
787     linepos++;
788     }
789     }
790     }
791     else
792     {
793     ptr[poffset ] = cmap[aByte].r;
794     ptr[poffset + 1] = cmap[aByte].g;
795     ptr[poffset + 2] = cmap[aByte].b;
796     column++;
797     // linepos += size; seems to be wrong, RR
798     }
799     }
800     }
801     else if ( bpp == 24 )
802     {
803     stream.Read(bbuf, 3);
804     linepos += 3;
805     ptr[poffset ] = (unsigned char)bbuf[2];
806     ptr[poffset + 1] = (unsigned char)bbuf[1];
807     ptr[poffset + 2] = (unsigned char)bbuf[0];
808     column++;
809     }
810     else if ( bpp == 16 )
811     {
812     unsigned char temp;
813     stream.Read(&aWord, 2);
814     aWord = wxUINT16_SWAP_ON_BE(aWord);
815     linepos += 2;
816     /* use the masks and calculated amonut of shift
817     to retrieve the color data out of the word. Then
818     shift it left by (8 - number of bits) such that
819     the image has the proper dynamic range */
820     temp = (unsigned char)((aWord & rmask) >> rshift << (8-rbits));
821     ptr[poffset] = temp;
822     temp = (unsigned char)((aWord & gmask) >> gshift << (8-gbits));
823     ptr[poffset + 1] = temp;
824     temp = (unsigned char)((aWord & bmask) >> bshift << (8-bbits));
825     ptr[poffset + 2] = temp;
826     column++;
827     }
828     else
829     {
830     unsigned char temp;
831     stream.Read(&aDword, 4);
832     aDword = wxINT32_SWAP_ON_BE(aDword);
833     linepos += 4;
834     temp = (unsigned char)((aDword & rmask) >> rshift);
835     ptr[poffset] = temp;
836     temp = (unsigned char)((aDword & gmask) >> gshift);
837     ptr[poffset + 1] = temp;
838     temp = (unsigned char)((aDword & bmask) >> bshift);
839     ptr[poffset + 2] = temp;
840     if ( alpha )
841     {
842     temp = (unsigned char)((aDword & amask) >> ashift);
843     alpha[line * width + column] = temp;
844     }
845     column++;
846     }
847     }
848     while ( (linepos < linesize) && (comp != 1) && (comp != 2) )
849     {
850     stream.Read(&aByte, 1);
851     linepos += 1;
852     if ( !stream )
853     break;
854     }
855     }
856    
857     delete[] cmap;
858    
859     image->SetMask(false);
860    
861     const wxStreamError err = stream.GetLastError();
862     return err == wxSTREAM_NO_ERROR || err == wxSTREAM_EOF;
863     }
864    
865     bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream,
866     bool verbose, bool IsBmp)
867     {
868     wxUint16 aWord;
869     wxInt32 dbuf[4];
870     wxInt8 bbuf[4];
871    
872     wxFileOffset offset = 0; // keep gcc quiet
873     if ( IsBmp )
874     {
875     // read the header off the .BMP format file
876    
877     offset = stream.TellI();
878     if (offset == wxInvalidOffset)
879     offset = 0;
880    
881     stream.Read(bbuf, 2);
882     stream.Read(dbuf, 16);
883     }
884     else
885     {
886     stream.Read(dbuf, 4);
887     }
888     #if 0 // unused
889     wxInt32 size = wxINT32_SWAP_ON_BE(dbuf[0]);
890     #endif
891     offset = offset + wxINT32_SWAP_ON_BE(dbuf[2]);
892    
893     stream.Read(dbuf, 4 * 2);
894     int width = wxINT32_SWAP_ON_BE((int)dbuf[0]);
895     int height = wxINT32_SWAP_ON_BE((int)dbuf[1]);
896     if ( !IsBmp)height = height / 2; // for icons divide by 2
897    
898     if ( width > 32767 )
899     {
900     if (verbose)
901     wxLogError( _("DIB Header: Image width > 32767 pixels for file.") );
902     return false;
903     }
904     if ( height > 32767 )
905     {
906     if (verbose)
907     wxLogError( _("DIB Header: Image height > 32767 pixels for file.") );
908     return false;
909     }
910    
911     stream.Read(&aWord, 2);
912     /*
913     TODO
914     int planes = (int)wxUINT16_SWAP_ON_BE( aWord );
915     */
916     stream.Read(&aWord, 2);
917     int bpp = wxUINT16_SWAP_ON_BE((int)aWord);
918     if ( bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24 && bpp != 32 )
919     {
920     if (verbose)
921     wxLogError( _("DIB Header: Unknown bitdepth in file.") );
922     return false;
923     }
924    
925     stream.Read(dbuf, 4 * 4);
926     int comp = wxINT32_SWAP_ON_BE((int)dbuf[0]);
927     if ( comp != BI_RGB && comp != BI_RLE4 && comp != BI_RLE8 &&
928     comp != BI_BITFIELDS )
929     {
930     if (verbose)
931     wxLogError( _("DIB Header: Unknown encoding in file.") );
932     return false;
933     }
934    
935     stream.Read(dbuf, 4 * 2);
936     int ncolors = wxINT32_SWAP_ON_BE( (int)dbuf[0] );
937     if (ncolors == 0)
938     ncolors = 1 << bpp;
939     /* some more sanity checks */
940     if (((comp == BI_RLE4) && (bpp != 4)) ||
941     ((comp == BI_RLE8) && (bpp != 8)) ||
942     ((comp == BI_BITFIELDS) && (bpp != 16 && bpp != 32)))
943     {
944     if (verbose)
945     wxLogError( _("DIB Header: Encoding doesn't match bitdepth.") );
946     return false;
947     }
948    
949     //read DIB; this is the BMP image or the XOR part of an icon image
950     if ( !DoLoadDib(image, width, height, bpp, ncolors, comp, offset, stream,
951     verbose, IsBmp, true) )
952     {
953     if (verbose)
954     wxLogError( _("Error in reading image DIB.") );
955     return false;
956     }
957    
958     if ( !IsBmp )
959     {
960     //read Icon mask which is monochrome
961     //there is no palette, so we will create one
962     wxImage mask;
963     if ( !DoLoadDib(&mask, width, height, 1, 2, BI_RGB, offset, stream,
964     verbose, IsBmp, false) )
965     {
966     if (verbose)
967     wxLogError( _("ICO: Error in reading mask DIB.") );
968     return false;
969     }
970     image->SetMaskFromImage(mask, 255, 255, 255);
971    
972     }
973    
974     return true;
975     }
976    
977     bool wxBMPHandler::LoadFile(wxImage *image, wxInputStream& stream,
978     bool verbose, int WXUNUSED(index))
979     {
980     // Read a single DIB fom the file:
981     return LoadDib(image, stream, verbose, true/*isBmp*/);
982     }
983    
984     bool wxBMPHandler::DoCanRead(wxInputStream& stream)
985     {
986     unsigned char hdr[2];
987    
988     if ( !stream.Read(hdr, WXSIZEOF(hdr)) )
989     return false;
990    
991     // do we have the BMP file signature?
992     return hdr[0] == 'B' && hdr[1] == 'M';
993     }
994    
995     #endif // wxUSE_STREAMS
996    
997    
998     #if wxUSE_ICO_CUR
999     //-----------------------------------------------------------------------------
1000     // wxICOHandler
1001     //-----------------------------------------------------------------------------
1002    
1003     IMPLEMENT_DYNAMIC_CLASS(wxICOHandler, wxBMPHandler)
1004    
1005     #if wxUSE_STREAMS
1006    
1007     struct ICONDIRENTRY
1008     {
1009     wxUint8 bWidth; // Width of the image
1010     wxUint8 bHeight; // Height of the image (times 2)
1011     wxUint8 bColorCount; // Number of colors in image (0 if >=8bpp)
1012     wxUint8 bReserved; // Reserved
1013    
1014     // these two are different in icons and cursors:
1015     // icon or cursor
1016     wxUint16 wPlanes; // Color Planes or XHotSpot
1017     wxUint16 wBitCount; // Bits per pixel or YHotSpot
1018    
1019     wxUint32 dwBytesInRes; // how many bytes in this resource?
1020     wxUint32 dwImageOffset; // where in the file is this image
1021     };
1022    
1023     struct ICONDIR
1024     {
1025     wxUint16 idReserved; // Reserved
1026     wxUint16 idType; // resource type (1 for icons, 2 for cursors)
1027     wxUint16 idCount; // how many images?
1028     };
1029    
1030    
1031     bool wxICOHandler::SaveFile(wxImage *image,
1032     wxOutputStream& stream,
1033     bool verbose)
1034    
1035     {
1036     //sanity check; icon must be less than 127 pixels high and 255 wide
1037     if ( image->GetHeight () > 127 )
1038     {
1039     if ( verbose )
1040     wxLogError(_("ICO: Image too tall for an icon."));
1041     return false;
1042     }
1043     if ( image->GetWidth () > 255 )
1044     {
1045     if ( verbose )
1046     wxLogError(_("ICO: Image too wide for an icon."));
1047     return false;
1048     }
1049    
1050     const int images = 1; // only generate one image
1051    
1052     // VS: This is a hack of sort - since ICO and CUR files are almost
1053     // identical, we have all the meat in wxICOHandler and check for
1054     // the actual (handler) type when the code has to distinguish between
1055     // the two formats
1056     int type = (this->GetType() == wxBITMAP_TYPE_CUR) ? 2 : 1;
1057    
1058     // write a header, (ICONDIR)
1059     // Calculate the header size
1060     wxUint32 offset = 3 * sizeof(wxUint16);
1061    
1062     ICONDIR IconDir;
1063     IconDir.idReserved = 0;
1064     IconDir.idType = wxUINT16_SWAP_ON_BE((wxUint16)type);
1065     IconDir.idCount = wxUINT16_SWAP_ON_BE((wxUint16)images);
1066     stream.Write(&IconDir.idReserved, sizeof(IconDir.idReserved));
1067     stream.Write(&IconDir.idType, sizeof(IconDir.idType));
1068     stream.Write(&IconDir.idCount, sizeof(IconDir.idCount));
1069     if ( !stream.IsOk() )
1070     {
1071     if ( verbose )
1072     wxLogError(_("ICO: Error writing the image file!"));
1073     return false;
1074     }
1075    
1076     // for each iamage write a description ICONDIRENTRY:
1077     ICONDIRENTRY icondirentry;
1078     for (int img = 0; img < images; img++)
1079     {
1080     wxImage mask;
1081    
1082     if ( image->HasMask() )
1083     {
1084     // make another image with black/white:
1085     mask = image->ConvertToMono (image->GetMaskRed(), image->GetMaskGreen(), image->GetMaskBlue() );
1086    
1087     // now we need to change the masked regions to black:
1088     unsigned char r = image->GetMaskRed();
1089     unsigned char g = image->GetMaskGreen();
1090     unsigned char b = image->GetMaskBlue();
1091     if ( (r != 0) || (g != 0) || (b != 0) )
1092     {
1093     // Go round and apply black to the masked bits:
1094     int i, j;
1095     for (i = 0; i < mask.GetWidth(); i++)
1096     {
1097     for (j = 0; j < mask.GetHeight(); j++)
1098     {
1099     if ((r == mask.GetRed(i, j)) &&
1100     (g == mask.GetGreen(i, j))&&
1101     (b == mask.GetBlue(i, j)) )
1102     image->SetRGB(i, j, 0, 0, 0 );
1103     }
1104     }
1105     }
1106     }
1107     else
1108     {
1109     // just make a black mask all over:
1110     mask = image->Copy();
1111     int i, j;
1112     for (i = 0; i < mask.GetWidth(); i++)
1113     for (j = 0; j < mask.GetHeight(); j++)
1114     mask.SetRGB(i, j, 0, 0, 0 );
1115     }
1116     // Set the formats for image and mask
1117     // (Windows never saves with more than 8 colors):
1118     image->SetOption(wxIMAGE_OPTION_BMP_FORMAT, wxBMP_8BPP);
1119    
1120     // monochome bitmap:
1121     mask.SetOption(wxIMAGE_OPTION_BMP_FORMAT, wxBMP_1BPP_BW);
1122     bool IsBmp = false;
1123     bool IsMask = false;
1124    
1125     //calculate size and offset of image and mask
1126     wxCountingOutputStream cStream;
1127     bool bResult = SaveDib(image, cStream, verbose, IsBmp, IsMask);
1128     if ( !bResult )
1129     {
1130     if ( verbose )
1131     wxLogError(_("ICO: Error writing the image file!"));
1132     return false;
1133     }
1134     IsMask = true;
1135    
1136     bResult = SaveDib(&mask, cStream, verbose, IsBmp, IsMask);
1137     if ( !bResult )
1138     {
1139     if ( verbose )
1140     wxLogError(_("ICO: Error writing the image file!"));
1141     return false;
1142     }
1143     wxUint32 Size = cStream.GetSize();
1144    
1145     // wxCountingOutputStream::IsOk() always returns true for now and this
1146     // "if" provokes VC++ warnings in optimized build
1147     #if 0
1148     if ( !cStream.Ok() )
1149     {
1150     if ( verbose )
1151     wxLogError(_("ICO: Error writing the image file!"));
1152     return false;
1153     }
1154     #endif // 0
1155    
1156     offset = offset + sizeof(ICONDIRENTRY);
1157    
1158     icondirentry.bWidth = (wxUint8)image->GetWidth();
1159     icondirentry.bHeight = (wxUint8)(2 * image->GetHeight());
1160     icondirentry.bColorCount = 0;
1161     icondirentry.bReserved = 0;
1162     icondirentry.wPlanes = wxUINT16_SWAP_ON_BE(1);
1163     icondirentry.wBitCount = wxUINT16_SWAP_ON_BE(wxBMP_8BPP);
1164     if ( type == 2 /*CUR*/)
1165     {
1166     int hx = image->HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_X) ?
1167     image->GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X) :
1168     image->GetWidth() / 2;
1169     int hy = image->HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y) ?
1170     image->GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y) :
1171     image->GetHeight() / 2;
1172    
1173     // actually write the values of the hot spot here:
1174     icondirentry.wPlanes = wxUINT16_SWAP_ON_BE((wxUint16)hx);
1175     icondirentry.wBitCount = wxUINT16_SWAP_ON_BE((wxUint16)hy);
1176     }
1177     icondirentry.dwBytesInRes = wxUINT32_SWAP_ON_BE(Size);
1178     icondirentry.dwImageOffset = wxUINT32_SWAP_ON_BE(offset);
1179    
1180     // increase size to allow for the data written:
1181     offset += Size;
1182    
1183     // write to stream:
1184     stream.Write(&icondirentry.bWidth, sizeof(icondirentry.bWidth));
1185     stream.Write(&icondirentry.bHeight, sizeof(icondirentry.bHeight));
1186     stream.Write(&icondirentry.bColorCount, sizeof(icondirentry.bColorCount));
1187     stream.Write(&icondirentry.bReserved, sizeof(icondirentry.bReserved));
1188     stream.Write(&icondirentry.wPlanes, sizeof(icondirentry.wPlanes));
1189     stream.Write(&icondirentry.wBitCount, sizeof(icondirentry.wBitCount));
1190     stream.Write(&icondirentry.dwBytesInRes, sizeof(icondirentry.dwBytesInRes));
1191     stream.Write(&icondirentry.dwImageOffset, sizeof(icondirentry.dwImageOffset));
1192     if ( !stream.IsOk() )
1193     {
1194     if ( verbose )
1195     wxLogError(_("ICO: Error writing the image file!"));
1196     return false;
1197     }
1198    
1199     // actually save it:
1200     IsMask = false;
1201     bResult = SaveDib(image, stream, verbose, IsBmp, IsMask);
1202     if ( !bResult )
1203     {
1204     if ( verbose )
1205     wxLogError(_("ICO: Error writing the image file!"));
1206     return false;
1207     }
1208     IsMask = true;
1209    
1210     bResult = SaveDib(&mask, stream, verbose, IsBmp, IsMask);
1211     if ( !bResult )
1212     {
1213     if ( verbose )
1214     wxLogError(_("ICO: Error writing the image file!"));
1215     return false;
1216     }
1217    
1218     } // end of for loop
1219    
1220     return true;
1221     }
1222    
1223     bool wxICOHandler::LoadFile(wxImage *image, wxInputStream& stream,
1224     bool verbose, int index)
1225     {
1226     stream.SeekI(0);
1227     return DoLoadFile(image, stream, verbose, index);
1228     }
1229    
1230     bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream,
1231     bool WXUNUSED(verbose), int index)
1232     {
1233     bool bResult wxDUMMY_INITIALIZE(false);
1234     bool IsBmp = false;
1235    
1236     ICONDIR IconDir;
1237    
1238     wxFileOffset iPos = stream.TellI();
1239     stream.Read(&IconDir, sizeof(IconDir));
1240     wxUint16 nIcons = wxUINT16_SWAP_ON_BE(IconDir.idCount);
1241     // nType is 1 for Icons, 2 for Cursors:
1242     wxUint16 nType = wxUINT16_SWAP_ON_BE(IconDir.idType);
1243    
1244     // loop round the icons and choose the best one:
1245     ICONDIRENTRY *pIconDirEntry = new ICONDIRENTRY[nIcons];
1246     ICONDIRENTRY *pCurrentEntry = pIconDirEntry;
1247     int wMax = 0;
1248     int colmax = 0;
1249     int iSel = wxNOT_FOUND;
1250    
1251     for (int i = 0; i < nIcons; i++ )
1252     {
1253     stream.Read(pCurrentEntry, sizeof(ICONDIRENTRY));
1254     // bHeight and bColorCount are wxUint8
1255     if ( pCurrentEntry->bWidth >= wMax )
1256     {
1257     // see if we have more colors, ==0 indicates > 8bpp:
1258     if ( pCurrentEntry->bColorCount == 0 )
1259     pCurrentEntry->bColorCount = 255;
1260     if ( pCurrentEntry->bColorCount >= colmax )
1261     {
1262     iSel = i;
1263     wMax = pCurrentEntry->bWidth;
1264     colmax = pCurrentEntry->bColorCount;
1265     }
1266     }
1267     pCurrentEntry++;
1268     }
1269    
1270     if ( index != -1 )
1271     {
1272     // VS: Note that we *have* to run the loop above even if index != -1, because
1273     // it reads ICONDIRENTRies.
1274     iSel = index;
1275     }
1276    
1277     if ( iSel == wxNOT_FOUND || iSel < 0 || iSel >= nIcons )
1278     {
1279     wxLogError(_("ICO: Invalid icon index."));
1280     bResult = false;
1281     }
1282     else
1283     {
1284     // seek to selected icon:
1285     pCurrentEntry = pIconDirEntry + iSel;
1286     stream.SeekI(iPos + wxUINT32_SWAP_ON_BE(pCurrentEntry->dwImageOffset), wxFromStart);
1287     bResult = LoadDib(image, stream, true, IsBmp);
1288     bool bIsCursorType = (this->GetType() == wxBITMAP_TYPE_CUR) || (this->GetType() == wxBITMAP_TYPE_ANI);
1289     if ( bResult && bIsCursorType && nType == 2 )
1290     {
1291     // it is a cursor, so let's set the hotspot:
1292     image->SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, wxUINT16_SWAP_ON_BE(pCurrentEntry->wPlanes));
1293     image->SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, wxUINT16_SWAP_ON_BE(pCurrentEntry->wBitCount));
1294     }
1295     }
1296     delete[] pIconDirEntry;
1297     return bResult;
1298     }
1299    
1300     int wxICOHandler::GetImageCount(wxInputStream& stream)
1301     {
1302     ICONDIR IconDir;
1303     wxFileOffset iPos = stream.TellI();
1304     stream.SeekI(0);
1305     stream.Read(&IconDir, sizeof(IconDir));
1306     wxUint16 nIcons = wxUINT16_SWAP_ON_BE(IconDir.idCount);
1307     stream.SeekI(iPos);
1308     return (int)nIcons;
1309     }
1310    
1311     bool wxICOHandler::DoCanRead(wxInputStream& stream)
1312     {
1313     stream.SeekI(0);
1314     unsigned char hdr[4];
1315     if ( !stream.Read(hdr, WXSIZEOF(hdr)) )
1316     return false;
1317    
1318     // hdr[2] is one for an icon and two for a cursor
1319     return hdr[0] == '\0' && hdr[1] == '\0' && hdr[2] == '\1' && hdr[3] == '\0';
1320     }
1321    
1322     #endif // wxUSE_STREAMS
1323    
1324    
1325     //-----------------------------------------------------------------------------
1326     // wxCURHandler
1327     //-----------------------------------------------------------------------------
1328    
1329     IMPLEMENT_DYNAMIC_CLASS(wxCURHandler, wxICOHandler)
1330    
1331     #if wxUSE_STREAMS
1332    
1333     bool wxCURHandler::DoCanRead(wxInputStream& stream)
1334     {
1335     stream.SeekI(0);
1336     unsigned char hdr[4];
1337     if ( !stream.Read(hdr, WXSIZEOF(hdr)) )
1338     return false;
1339    
1340     // hdr[2] is one for an icon and two for a cursor
1341     return hdr[0] == '\0' && hdr[1] == '\0' && hdr[2] == '\2' && hdr[3] == '\0';
1342     }
1343    
1344     #endif // wxUSE_STREAMS
1345    
1346     //-----------------------------------------------------------------------------
1347     // wxANIHandler
1348     //-----------------------------------------------------------------------------
1349    
1350     IMPLEMENT_DYNAMIC_CLASS(wxANIHandler, wxCURHandler)
1351    
1352     #if wxUSE_STREAMS
1353    
1354     bool wxANIHandler::LoadFile(wxImage *image, wxInputStream& stream,
1355     bool WXUNUSED(verbose), int index)
1356     {
1357     wxANIDecoder decoder;
1358     if (!decoder.Load(stream))
1359     return false;
1360    
1361     return decoder.ConvertToImage(index != -1 ? (size_t)index : 0, image);
1362     }
1363    
1364     bool wxANIHandler::DoCanRead(wxInputStream& stream)
1365     {
1366     wxANIDecoder decod;
1367     return decod.CanRead(stream);
1368     }
1369    
1370     int wxANIHandler::GetImageCount(wxInputStream& stream)
1371     {
1372     wxANIDecoder decoder;
1373     if (!decoder.Load(stream))
1374     return wxNOT_FOUND;
1375    
1376     return decoder.GetFrameCount();
1377     }
1378    
1379     #endif // wxUSE_STREAMS
1380    
1381     #endif // wxUSE_ICO_CUR
1382    
1383     #endif // wxUSE_IMAGE

  ViewVC Help
Powered by ViewVC 1.1.22