~ubuntu-branches/ubuntu/raring/wxwidgets2.8/raring

« back to all changes in this revision

Viewing changes to .pc/ico-saving-buffer-overrun.patch/src/common/imagbmp.cpp

  • Committer: Package Import Robot
  • Author(s): Benjamin Drung
  • Date: 2012-06-02 12:33:00 UTC
  • mfrom: (5.1.15 sid)
  • Revision ID: package-import@ubuntu.com-20120602123300-cmj36sgxk0zi6k0h
Tags: 2.8.12.1-11ubuntu1
* Merge from Debian unstable. Remaining changes:
  - debian/rules: re-enable mediactrl. This allows libwx_gtk2u_media-2.8 to be
    built, as this is required by some applications (LP: #632984)
  - debian/control:
    - Build-dep on libxt-dev, libgstreamer-plugins-base0.10-dev,
      and libgconf2-dev for mediactrl.
    - Add conflict on python-wxgtk2.8 (<< 2.8.12.1-6ubuntu1~) to
      python-wxversion to guarantee upgrade ordering when moving from
      pycentral to dh_python2.
* Drop fix-bashism-in-example.patch. (LP: #1005609)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/////////////////////////////////////////////////////////////////////////////
 
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