1 /*====================================================================*
2  -  Copyright (C) 2001 Leptonica.  All rights reserved.
3  -
4  -  Redistribution and use in source and binary forms, with or without
5  -  modification, are permitted provided that the following conditions
6  -  are met:
7  -  1. Redistributions of source code must retain the above copyright
8  -     notice, this list of conditions and the following disclaimer.
9  -  2. Redistributions in binary form must reproduce the above
10  -     copyright notice, this list of conditions and the following
11  -     disclaimer in the documentation and/or other materials
12  -     provided with the distribution.
13  -
14  -  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  -  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  -  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  -  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ANY
18  -  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  -  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  -  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  -  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  -  OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  -  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  -  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *====================================================================*/
26 
27 /*!
28  * \file bmpio.c
29  * <pre>
30  *
31  *      Read bmp
32  *           PIX          *pixReadStreamBmp()
33  *           PIX          *pixReadMemBmp()
34  *
35  *      Write bmp
36  *           l_int32       pixWriteStreamBmp()
37  *           l_int32       pixWriteMemBmp()
38  *
39  * </pre>
40  */
41 
42 #ifdef HAVE_CONFIG_H
43 #include "config_auto.h"
44 #endif  /* HAVE_CONFIG_H */
45 
46 #include <string.h>
47 #include "allheaders.h"
48 #include "bmp.h"
49 
50 /* --------------------------------------------*/
51 #if  USE_BMPIO   /* defined in environ.h */
52 /* --------------------------------------------*/
53 
54     /* Here we're setting the pixel value 0 to white (255) and the
55      * value 1 to black (0).  This is the convention for grayscale, but
56      * the opposite of the convention for 1 bpp, where 0 is white
57      * and 1 is black.  Both colormap entries are opaque (alpha = 255) */
58 RGBA_QUAD   bwmap[2] = { {255,255,255,255}, {0,0,0,255} };
59 
60     /* Colormap size limit */
61 static const l_int32  L_MAX_ALLOWED_NUM_COLORS = 256;
62 
63     /* Image dimension limits */
64 static const l_int32  L_MAX_ALLOWED_WIDTH = 1000000;
65 static const l_int32  L_MAX_ALLOWED_HEIGHT = 1000000;
66 static const l_int64  L_MAX_ALLOWED_PIXELS = 400000000LL;
67 
68 #ifndef  NO_CONSOLE_IO
69 #define  DEBUG     0
70 #endif  /* ~NO_CONSOLE_IO */
71 
72 /*--------------------------------------------------------------*
73  *                              Read bmp                        *
74  *--------------------------------------------------------------*/
75 /*!
76  * \brief   pixReadStreamBmp()
77  *
78  * \param[in]    fp file stream opened for read
79  * \return  pix, or NULL on error
80  *
81  * <pre>
82  * Notes:
83  *      (1) Here are references on the bmp file format:
84  *          http://en.wikipedia.org/wiki/BMP_file_format
85  *          http://www.fortunecity.com/skyscraper/windows/364/bmpffrmt.html
86  * </pre>
87  */
88 PIX *
pixReadStreamBmp(FILE * fp)89 pixReadStreamBmp(FILE  *fp)
90 {
91 l_uint8  *data;
92 size_t    size;
93 PIX      *pix;
94 
95     PROCNAME("pixReadStreamBmp");
96 
97     if (!fp)
98         return (PIX *)ERROR_PTR("fp not defined", procName, NULL);
99 
100         /* Read data from file and decode into Y,U,V arrays */
101     rewind(fp);
102     if ((data = l_binaryReadStream(fp, &size)) == NULL)
103         return (PIX *)ERROR_PTR("data not read", procName, NULL);
104 
105     pix = pixReadMemBmp(data, size);
106     LEPT_FREE(data);
107     return pix;
108 }
109 
110 
111 /*!
112  * \brief   pixReadMemBmp()
113  *
114  * \param[in]    cdata    bmp data
115  * \param[in]    size     number of bytes of bmp-formatted data
116  * \return  pix, or NULL on error
117  */
118 PIX *
pixReadMemBmp(const l_uint8 * cdata,size_t size)119 pixReadMemBmp(const l_uint8  *cdata,
120               size_t          size)
121 {
122 l_uint8    pel[4];
123 l_uint8   *cmapBuf, *fdata, *data;
124 l_int16    bftype, offset, depth, d;
125 l_int32    width, height, height_neg, xres, yres, compression, imagebytes;
126 l_int32    cmapbytes, cmapEntries;
127 l_int32    fdatabpl, extrabytes, pixWpl, pixBpl, i, j, k;
128 l_uint32  *line, *pixdata, *pword;
129 l_int64    npixels;
130 BMP_FH    *bmpfh;
131 BMP_IH    *bmpih;
132 PIX       *pix, *pix1;
133 PIXCMAP   *cmap;
134 
135     PROCNAME("pixReadMemBmp");
136 
137     if (!cdata)
138         return (PIX *)ERROR_PTR("cdata not defined", procName, NULL);
139     if (size < sizeof(BMP_FH) + sizeof(BMP_IH))
140         return (PIX *)ERROR_PTR("bmf size error", procName, NULL);
141 
142         /* Verify this is an uncompressed bmp */
143     bmpfh = (BMP_FH *)cdata;
144     bftype = convertOnBigEnd16(bmpfh->bfType);
145     if (bftype != BMP_ID)
146         return (PIX *)ERROR_PTR("not bmf format", procName, NULL);
147     bmpih = (BMP_IH *)(cdata + BMP_FHBYTES);
148     if (!bmpih)
149         return (PIX *)ERROR_PTR("bmpih not defined", procName, NULL);
150     compression = convertOnBigEnd32(bmpih->biCompression);
151     if (compression != 0)
152         return (PIX *)ERROR_PTR("cannot read compressed BMP files",
153                                 procName, NULL);
154 
155         /* Read the rest of the useful header information */
156     offset = convertOnBigEnd16(bmpfh->bfOffBits);
157     width = convertOnBigEnd32(bmpih->biWidth);
158     height = convertOnBigEnd32(bmpih->biHeight);
159     depth = convertOnBigEnd16(bmpih->biBitCount);
160     imagebytes = convertOnBigEnd32(bmpih->biSizeImage);
161     xres = convertOnBigEnd32(bmpih->biXPelsPerMeter);
162     yres = convertOnBigEnd32(bmpih->biYPelsPerMeter);
163 
164         /* Some sanity checking.  We impose limits on the image
165          * dimensions and number of pixels.  We make sure the file
166          * is the correct size to hold the amount of uncompressed data
167          * that is specified in the header.  The number of colormap
168          * entries is checked: it can be either 0 (no cmap) or some
169          * number between 2 and 256.
170          * Note that the imagebytes for uncompressed images is either
171          * 0 or the size of the file data.  (The fact that it can
172          * be 0 is perhaps some legacy glitch). */
173     if (width < 1)
174         return (PIX *)ERROR_PTR("width < 1", procName, NULL);
175     if (width > L_MAX_ALLOWED_WIDTH)
176         return (PIX *)ERROR_PTR("width too large", procName, NULL);
177     height_neg = 0;
178     if (height < 0) {
179         height_neg = 1;
180         height = -height;
181     }
182     if (height == 0 || height > L_MAX_ALLOWED_HEIGHT)
183         return (PIX *)ERROR_PTR("invalid height", procName, NULL);
184     npixels = 1LL * width * height;
185     if (npixels > L_MAX_ALLOWED_PIXELS)
186         return (PIX *)ERROR_PTR("npixels too large", procName, NULL);
187     if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
188         depth != 16 && depth != 24 && depth != 32)
189         return (PIX *)ERROR_PTR("depth not in {1, 2, 4, 8, 16, 24, 32}",
190                                 procName,NULL);
191     fdatabpl = 4 * ((1LL * width * depth + 31)/32);
192     if (imagebytes != 0 && imagebytes != fdatabpl * height)
193         return (PIX *)ERROR_PTR("invalid imagebytes", procName, NULL);
194     cmapbytes = offset - BMP_FHBYTES - BMP_IHBYTES;
195     cmapEntries = cmapbytes / sizeof(RGBA_QUAD);
196     if (cmapEntries < 0 || cmapEntries == 1)
197         return (PIX *)ERROR_PTR("invalid: cmap size < 0 or 1", procName, NULL);
198     if (cmapEntries > L_MAX_ALLOWED_NUM_COLORS)
199         return (PIX *)ERROR_PTR("invalid cmap: too large", procName,NULL);
200     if (size != 1LL * offset + 1LL * fdatabpl * height)
201         return (PIX *)ERROR_PTR("size incommensurate with image data",
202                                 procName,NULL);
203 
204         /* Handle the colormap */
205     cmapBuf = NULL;
206     if (cmapEntries > 0) {
207         if ((cmapBuf = (l_uint8 *)LEPT_CALLOC(cmapEntries, sizeof(RGBA_QUAD)))
208                  == NULL)
209             return (PIX *)ERROR_PTR("cmapBuf alloc fail", procName, NULL );
210 
211             /* Read the colormap entry data from bmp. The RGBA_QUAD colormap
212              * entries are used for both bmp and leptonica colormaps. */
213         memcpy(cmapBuf, cdata + BMP_FHBYTES + BMP_IHBYTES,
214                sizeof(RGBA_QUAD) * cmapEntries);
215     }
216 
217         /* Make a 32 bpp pix if depth is 24 bpp */
218     d = (depth == 24) ? 32 : depth;
219     if ((pix = pixCreate(width, height, d)) == NULL) {
220         LEPT_FREE(cmapBuf);
221         return (PIX *)ERROR_PTR( "pix not made", procName, NULL);
222     }
223     pixSetXRes(pix, (l_int32)((l_float32)xres / 39.37 + 0.5));  /* to ppi */
224     pixSetYRes(pix, (l_int32)((l_float32)yres / 39.37 + 0.5));  /* to ppi */
225     pixSetInputFormat(pix, IFF_BMP);
226     pixWpl = pixGetWpl(pix);
227     pixBpl = 4 * pixWpl;
228 
229         /* Convert the bmp colormap to a pixcmap */
230     cmap = NULL;
231     if (cmapEntries > 0) {  /* import the colormap to the pix cmap */
232         cmap = pixcmapCreate(L_MIN(d, 8));
233         LEPT_FREE(cmap->array);  /* remove generated cmap array */
234         cmap->array  = (void *)cmapBuf;  /* and replace */
235         cmap->n = L_MIN(cmapEntries, 256);
236         for (i = 0; i < cmap->n; i++)   /* set all colors opaque */
237             pixcmapSetAlpha (cmap, i, 255);
238     }
239     pixSetColormap(pix, cmap);
240 
241         /* Acquire the image data.  Image origin for bmp is at lower right. */
242     fdata = (l_uint8 *)cdata + offset;  /* start of the bmp image data */
243     pixdata = pixGetData(pix);
244     if (depth != 24) {  /* typ. 1 or 8 bpp */
245         data = (l_uint8 *)pixdata + pixBpl * (height - 1);
246         for (i = 0; i < height; i++) {
247             memcpy(data, fdata, fdatabpl);
248             fdata += fdatabpl;
249             data -= pixBpl;
250         }
251     } else {  /*  24 bpp file; 32 bpp pix
252              *  Note: for bmp files, pel[0] is blue, pel[1] is green,
253              *  and pel[2] is red.  This is opposite to the storage
254              *  in the pix, which puts the red pixel in the 0 byte,
255              *  the green in the 1 byte and the blue in the 2 byte.
256              *  Note also that all words are endian flipped after
257              *  assignment on L_LITTLE_ENDIAN platforms.
258              *
259              *  We can then make these assignments for little endians:
260              *      SET_DATA_BYTE(pword, 1, pel[0]);      blue
261              *      SET_DATA_BYTE(pword, 2, pel[1]);      green
262              *      SET_DATA_BYTE(pword, 3, pel[2]);      red
263              *  This looks like:
264              *          3  (R)     2  (G)        1  (B)        0
265              *      |-----------|------------|-----------|-----------|
266              *  and after byte flipping:
267              *           3          2  (B)     1  (G)        0  (R)
268              *      |-----------|------------|-----------|-----------|
269              *
270              *  For big endians we set:
271              *      SET_DATA_BYTE(pword, 2, pel[0]);      blue
272              *      SET_DATA_BYTE(pword, 1, pel[1]);      green
273              *      SET_DATA_BYTE(pword, 0, pel[2]);      red
274              *  This looks like:
275              *          0  (R)     1  (G)        2  (B)        3
276              *      |-----------|------------|-----------|-----------|
277              *  so in both cases we get the correct assignment in the PIX.
278              *
279              *  Can we do a platform-independent assignment?
280              *  Yes, set the bytes without using macros:
281              *      *((l_uint8 *)pword) = pel[2];           red
282              *      *((l_uint8 *)pword + 1) = pel[1];       green
283              *      *((l_uint8 *)pword + 2) = pel[0];       blue
284              *  For little endians, before flipping, this looks again like:
285              *          3  (R)     2  (G)        1  (B)        0
286              *      |-----------|------------|-----------|-----------|
287              */
288         extrabytes = fdatabpl - 3 * width;
289         line = pixdata + pixWpl * (height - 1);
290         for (i = 0; i < height; i++) {
291             for (j = 0; j < width; j++) {
292                 pword = line + j;
293                 memcpy(&pel, fdata, 3);
294                 fdata += 3;
295                 *((l_uint8 *)pword + COLOR_RED) = pel[2];
296                 *((l_uint8 *)pword + COLOR_GREEN) = pel[1];
297                 *((l_uint8 *)pword + COLOR_BLUE) = pel[0];
298             }
299             if (extrabytes) {
300                 for (k = 0; k < extrabytes; k++) {
301                     memcpy(&pel, fdata, 1);
302                     fdata++;
303                 }
304             }
305             line -= pixWpl;
306         }
307     }
308 
309     pixEndianByteSwap(pix);
310     if (height_neg)
311         pixFlipTB(pix, pix);
312 
313         /* ----------------------------------------------
314          * The bmp colormap determines the values of black
315          * and white pixels for binary in the following way:
316          * (a) white = 0 [255], black = 1 [0]
317          *      255, 255, 255, 255, 0, 0, 0, 255
318          * (b) black = 0 [0], white = 1 [255]
319          *      0, 0, 0, 255, 255, 255, 255, 255
320          * We have no need for a 1 bpp pix with a colormap!
321          * Note: the alpha component here is 255 (opaque)
322          * ---------------------------------------------- */
323     if (depth == 1 && cmap) {
324         pix1 = pixRemoveColormap(pix, REMOVE_CMAP_TO_BINARY);
325         pixDestroy(&pix);
326         pix = pix1;  /* rename */
327     }
328 
329     return pix;
330 }
331 
332 
333 /*--------------------------------------------------------------*
334  *                            Write bmp                         *
335  *--------------------------------------------------------------*/
336 /*!
337  * \brief   pixWriteStreamBmp()
338  *
339  * \param[in]    fp     file stream
340  * \param[in]    pix    all depths
341  * \return  0 if OK, 1 on error
342  */
343 l_int32
pixWriteStreamBmp(FILE * fp,PIX * pix)344 pixWriteStreamBmp(FILE  *fp,
345                   PIX   *pix)
346 {
347 l_uint8  *data;
348 size_t    size, nbytes;
349 
350     PROCNAME("pixWriteStreamBmp");
351 
352     if (!fp)
353         return ERROR_INT("stream not defined", procName, 1);
354     if (!pix)
355         return ERROR_INT("pix not defined", procName, 1);
356 
357     pixWriteMemBmp(&data, &size, pix);
358     rewind(fp);
359     nbytes = fwrite(data, 1, size, fp);
360     free(data);
361     if (nbytes != size)
362         return ERROR_INT("Write error", procName, 1);
363     return 0;
364 }
365 
366 
367 /*!
368  * \brief   pixWriteMemBmp()
369  *
370  * \param[out]   pfdata   data of bmp formatted image
371  * \param[out]   pfsize    size of returned data
372  * \param[in]    pixs      1, 2, 4, 8, 16, 32 bpp
373  * \return  0 if OK, 1 on error
374  *
375  * <pre>
376  * Notes:
377  *      (1) 2 bpp bmp files are not valid in the spec, and are
378  *          written as 8 bpp.
379  *      (2) pix with depth <= 8 bpp are written with a colormap.
380  *          16 bpp gray and 32 bpp rgb pix are written without a colormap.
381  *      (3) The transparency component in an rgb pix is ignored.
382  *          All 32 bpp pix have the bmp alpha component set to 255 (opaque).
383  *      (4) The bmp colormap entries, RGBA_QUAD, are the same as
384  *          the ones used for colormaps in leptonica.  This allows
385  *          a simple memcpy for bmp output.
386  * </pre>
387  */
388 l_int32
pixWriteMemBmp(l_uint8 ** pfdata,size_t * pfsize,PIX * pixs)389 pixWriteMemBmp(l_uint8  **pfdata,
390                size_t    *pfsize,
391                PIX       *pixs)
392 {
393 l_uint8     pel[4];
394 l_uint8    *cta = NULL;     /* address of the bmp color table array */
395 l_uint8    *fdata, *data, *fmdata;
396 l_int32     cmaplen;      /* number of bytes in the bmp colormap */
397 l_int32     ncolors, val, stepsize;
398 l_int32     w, h, d, fdepth, xres, yres;
399 l_int32     pixWpl, pixBpl, extrabytes, fBpl, fWpl, i, j, k;
400 l_int32     heapcm;  /* extra copy of cta on the heap ? 1 : 0 */
401 l_uint32    offbytes, fimagebytes;
402 l_uint32   *line, *pword;
403 size_t      fsize;
404 BMP_FH     *bmpfh;
405 BMP_IH     *bmpih;
406 PIX        *pix;
407 PIXCMAP    *cmap;
408 RGBA_QUAD  *pquad;
409 
410     PROCNAME("pixWriteMemBmp");
411 
412     if (pfdata) *pfdata = NULL;
413     if (pfsize) *pfsize = 0;
414     if (!pfdata)
415         return ERROR_INT("&fdata not defined", procName, 1 );
416     if (!pfsize)
417         return ERROR_INT("&fsize not defined", procName, 1 );
418     if (!pixs)
419         return ERROR_INT("pixs not defined", procName, 1);
420 
421     pixGetDimensions(pixs, &w, &h, &d);
422     if (d == 2) {
423         L_WARNING("2 bpp files can't be read; converting to 8 bpp\n", procName);
424         pix = pixConvert2To8(pixs, 0, 85, 170, 255, 1);
425         d = 8;
426     } else {
427         pix = pixCopy(NULL, pixs);
428     }
429     fdepth = (d == 32) ? 24 : d;
430 
431         /* Resolution is given in pixels/meter */
432     xres = (l_int32)(39.37 * (l_float32)pixGetXRes(pix) + 0.5);
433     yres = (l_int32)(39.37 * (l_float32)pixGetYRes(pix) + 0.5);
434 
435     pixWpl = pixGetWpl(pix);
436     pixBpl = 4 * pixWpl;
437     fWpl = (w * fdepth + 31) / 32;
438     fBpl = 4 * fWpl;
439     fimagebytes = h * fBpl;
440     if (fimagebytes > 4LL * L_MAX_ALLOWED_PIXELS) {
441         pixDestroy(&pix);
442         return ERROR_INT("image data is too large", procName, 1);
443     }
444 
445         /* If not rgb or 16 bpp, the bmp data is required to have a colormap */
446     heapcm = 0;
447     if (d == 32 || d == 16) {   /* 24 bpp rgb or 16 bpp: no colormap */
448         ncolors = 0;
449         cmaplen = 0;
450     } else if ((cmap = pixGetColormap(pix))) {   /* existing colormap */
451         ncolors = pixcmapGetCount(cmap);
452         cmaplen = ncolors * sizeof(RGBA_QUAD);
453         cta = (l_uint8 *)cmap->array;
454     } else {   /* no existing colormap; d <= 8; make a binary or gray one */
455         if (d == 1) {
456             cmaplen  = sizeof(bwmap);
457             ncolors = 2;
458             cta = (l_uint8 *)bwmap;
459         } else {   /* d = 2,4,8; use a grayscale output colormap */
460             ncolors = 1 << fdepth;
461             cmaplen = ncolors * sizeof(RGBA_QUAD);
462             heapcm = 1;
463             cta = (l_uint8 *)LEPT_CALLOC(cmaplen, 1);
464             stepsize = 255 / (ncolors - 1);
465             for (i = 0, val = 0, pquad = (RGBA_QUAD *)cta;
466                  i < ncolors;
467                  i++, val += stepsize, pquad++) {
468                 pquad->blue = pquad->green = pquad->red = val;
469                 pquad->alpha = 255;  /* opaque */
470             }
471         }
472     }
473 
474 #if DEBUG
475     {l_uint8  *pcmptr;
476         pcmptr = (l_uint8 *)pixGetColormap(pix)->array;
477         fprintf(stderr, "Pix colormap[0] = %c%c%c%d\n",
478             pcmptr[0], pcmptr[1], pcmptr[2], pcmptr[3]);
479         fprintf(stderr, "Pix colormap[1] = %c%c%c%d\n",
480             pcmptr[4], pcmptr[5], pcmptr[6], pcmptr[7]);
481     }
482 #endif  /* DEBUG */
483 
484     offbytes = BMP_FHBYTES + BMP_IHBYTES + cmaplen;
485     fsize = offbytes + fimagebytes;
486     fdata = (l_uint8 *)LEPT_CALLOC(fsize, 1);
487     *pfdata = fdata;
488     *pfsize = fsize;
489 
490         /* Convert to little-endian and write the file header data */
491     bmpfh = (BMP_FH *)fdata;
492     bmpfh->bfType = convertOnBigEnd16(BMP_ID);
493     bmpfh->bfSize = convertOnBigEnd16(fsize & 0x0000ffff);
494     bmpfh->bfFill1 = convertOnBigEnd16((fsize >> 16) & 0x0000ffff);
495     bmpfh->bfOffBits = convertOnBigEnd16(offbytes & 0x0000ffff);
496     bmpfh->bfFill2 = convertOnBigEnd16((offbytes >> 16) & 0x0000ffff);
497 
498         /* Convert to little-endian and write the info header data */
499     bmpih = (BMP_IH *)(fdata + BMP_FHBYTES);
500     bmpih->biSize = convertOnBigEnd32(BMP_IHBYTES);
501     bmpih->biWidth = convertOnBigEnd32(w);
502     bmpih->biHeight = convertOnBigEnd32(h);
503     bmpih->biPlanes = convertOnBigEnd16(1);
504     bmpih->biBitCount = convertOnBigEnd16(fdepth);
505     bmpih->biSizeImage = convertOnBigEnd32(fimagebytes);
506     bmpih->biXPelsPerMeter = convertOnBigEnd32(xres);
507     bmpih->biYPelsPerMeter = convertOnBigEnd32(yres);
508     bmpih->biClrUsed = convertOnBigEnd32(ncolors);
509     bmpih->biClrImportant = convertOnBigEnd32(ncolors);
510 
511         /* Copy the colormap data and free the cta if necessary */
512     if (ncolors > 0) {
513         memcpy(fdata + BMP_FHBYTES + BMP_IHBYTES, cta, cmaplen);
514         if (heapcm) LEPT_FREE(cta);
515     }
516 
517         /* When you write a binary image with a colormap
518          * that sets BLACK to 0, you must invert the data */
519     if (fdepth == 1 && cmap && ((l_uint8 *)(cmap->array))[0] == 0x0) {
520         pixInvert(pix, pix);
521     }
522 
523         /* An endian byte swap is also required */
524     pixEndianByteSwap(pix);
525 
526         /* Transfer the image data.  Image origin for bmp is at lower right. */
527     fmdata = fdata + offbytes;
528     if (fdepth != 24) {   /* typ 1 or 8 bpp */
529         data = (l_uint8 *)pixGetData(pix) + pixBpl * (h - 1);
530         for (i = 0; i < h; i++) {
531             memcpy(fmdata, data, fBpl);
532             data -= pixBpl;
533             fmdata += fBpl;
534         }
535     } else {  /* 32 bpp pix; 24 bpp file
536              * See the comments in pixReadStreamBmp() to
537              * understand the logic behind the pixel ordering below.
538              * Note that we have again done an endian swap on
539              * little endian machines before arriving here, so that
540              * the bytes are ordered on both platforms as:
541                         Red         Green        Blue         --
542                     |-----------|------------|-----------|-----------|
543              */
544         extrabytes = fBpl - 3 * w;
545         line = pixGetData(pix) + pixWpl * (h - 1);
546         for (i = 0; i < h; i++) {
547             for (j = 0; j < w; j++) {
548                 pword = line + j;
549                 pel[2] = *((l_uint8 *)pword + COLOR_RED);
550                 pel[1] = *((l_uint8 *)pword + COLOR_GREEN);
551                 pel[0] = *((l_uint8 *)pword + COLOR_BLUE);
552                 memcpy(fmdata, &pel, 3);
553                 fmdata += 3;
554             }
555             if (extrabytes) {
556                 for (k = 0; k < extrabytes; k++) {
557                     memcpy(fmdata, &pel, 1);
558                     fmdata++;
559                 }
560             }
561             line -= pixWpl;
562         }
563     }
564 
565     pixDestroy(&pix);
566     return 0;
567 }
568 
569 /* --------------------------------------------*/
570 #endif  /* USE_BMPIO */
571