diff options
author | Chris Blume <cblume@chromium.org> | 2019-03-01 01:09:50 -0800 |
---|---|---|
committer | Chris Blume <cblume@chromium.org> | 2019-03-01 01:09:50 -0800 |
commit | cca8c4dec783a048da6933c86028556622d7c355 (patch) | |
tree | 8a7ff526cd8cbe3bf1bfaa4ec1c29fe3268ed51b /rdbmp.c | |
parent | 61a2bbaa9aec89cb2c882d87ace6aba9aee49bb9 (diff) |
Update libjpeg-turbo to v2.0.1
In order to apply some performance updates from ARM, we need to update
libjpeg-turbo. These performance updates have yielded a 50% speedup on
some devices.
This CL updates our copy of libjpeg-turbo to v2.0.1 and re-applies our
local patches. This patch also deletes some extra files which were not
being used locally.
Update our local patch that was applied to fix http://crbug.com/398235
(https://codereview.appspot.com/229430043/). The original patch
incorrectly removed "& 0xFF" which limited an array index to within
that array's bounds (effectively reverting
https://github.com/libjpeg-turbo/libjpeg-turbo/commit/fa1d18385d904d530b4aec83ab7757a33397de6e).
Restore the mask, making the array access safe and fixing a graphical
glitch which would otherwise be introduced by this change.
Bug:922430
Change-Id: I3860fdb424deecf7a17818ed09a640e632e71f8d
Diffstat (limited to 'rdbmp.c')
-rw-r--r-- | rdbmp.c | 452 |
1 files changed, 329 insertions, 123 deletions
@@ -3,10 +3,10 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. - * Modified 2009-2010 by Guido Vollbeding. + * Modified 2009-2017 by Guido Vollbeding. * libjpeg-turbo Modifications: * Modified 2011 by Siarhei Siamashka. - * Copyright (C) 2015, D. R. Commander. + * Copyright (C) 2015, 2017-2018, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -26,6 +26,7 @@ * This code contributed by James Arthur Boucher. */ +#include "cmyk.h" #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #ifdef BMP_SUPPORTED @@ -35,19 +36,24 @@ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char U_CHAR; -#define UCH(x) ((int) (x)) +#define UCH(x) ((int)(x)) #else /* !HAVE_UNSIGNED_CHAR */ #ifdef __CHAR_UNSIGNED__ typedef char U_CHAR; -#define UCH(x) ((int) (x)) +#define UCH(x) ((int)(x)) #else typedef char U_CHAR; -#define UCH(x) ((int) (x) & 0xFF) +#define UCH(x) ((int)(x) & 0xFF) #endif #endif /* HAVE_UNSIGNED_CHAR */ -#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len))) +#define ReadOK(file, buffer, len) \ + (JFREAD(file, buffer, len) == ((size_t)(len))) + +static int alpha_index[JPEG_NUMCS] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 3, 0, 0, -1 +}; /* Private version of data source object */ @@ -66,11 +72,23 @@ typedef struct _bmp_source_struct { JDIMENSION row_width; /* Physical width of scanlines in file */ int bits_per_pixel; /* remembers 8- or 24-bit format */ + int cmap_length; /* colormap length */ + + boolean use_inversion_array; /* TRUE = preload the whole image, which is + stored in bottom-up order, and feed it to + the calling program in top-down order + + FALSE = the calling program will maintain + its own image buffer and read the rows in + bottom-up order */ + + U_CHAR *iobuffer; /* I/O buffer (used to buffer a single row from + disk if use_inversion_array == FALSE) */ } bmp_source_struct; LOCAL(int) -read_byte (bmp_source_ptr sinfo) +read_byte(bmp_source_ptr sinfo) /* Read next byte from BMP file */ { register FILE *infile = sinfo->pub.input_file; @@ -83,33 +101,45 @@ read_byte (bmp_source_ptr sinfo) LOCAL(void) -read_colormap (bmp_source_ptr sinfo, int cmaplen, int mapentrysize) +read_colormap(bmp_source_ptr sinfo, int cmaplen, int mapentrysize) /* Read the colormap from a BMP file */ { - int i; + int i, gray = 1; switch (mapentrysize) { case 3: /* BGR format (occurs in OS/2 files) */ for (i = 0; i < cmaplen; i++) { - sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo); - sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo); - sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo); + sinfo->colormap[2][i] = (JSAMPLE)read_byte(sinfo); + sinfo->colormap[1][i] = (JSAMPLE)read_byte(sinfo); + sinfo->colormap[0][i] = (JSAMPLE)read_byte(sinfo); + if (sinfo->colormap[2][i] != sinfo->colormap[1][i] || + sinfo->colormap[1][i] != sinfo->colormap[0][i]) + gray = 0; } break; case 4: /* BGR0 format (occurs in MS Windows files) */ for (i = 0; i < cmaplen; i++) { - sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo); - sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo); - sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo); - (void) read_byte(sinfo); + sinfo->colormap[2][i] = (JSAMPLE)read_byte(sinfo); + sinfo->colormap[1][i] = (JSAMPLE)read_byte(sinfo); + sinfo->colormap[0][i] = (JSAMPLE)read_byte(sinfo); + (void)read_byte(sinfo); + if (sinfo->colormap[2][i] != sinfo->colormap[1][i] || + sinfo->colormap[1][i] != sinfo->colormap[0][i]) + gray = 0; } break; default: ERREXIT(sinfo->cinfo, JERR_BMP_BADCMAP); break; } + + if (sinfo->cinfo->in_color_space == JCS_UNKNOWN && gray) + sinfo->cinfo->in_color_space = JCS_GRAYSCALE; + + if (sinfo->cinfo->in_color_space == JCS_GRAYSCALE && !gray) + ERREXIT(sinfo->cinfo, JERR_BAD_IN_COLORSPACE); } @@ -121,30 +151,77 @@ read_colormap (bmp_source_ptr sinfo, int cmaplen, int mapentrysize) */ METHODDEF(JDIMENSION) -get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +get_8bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* This version is for reading 8-bit colormap indexes */ { - bmp_source_ptr source = (bmp_source_ptr) sinfo; + bmp_source_ptr source = (bmp_source_ptr)sinfo; register JSAMPARRAY colormap = source->colormap; + int cmaplen = source->cmap_length; JSAMPARRAY image_ptr; register int t; register JSAMPROW inptr, outptr; register JDIMENSION col; - /* Fetch next row from virtual array */ - source->source_row--; - image_ptr = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, source->whole_image, - source->source_row, (JDIMENSION) 1, FALSE); + if (source->use_inversion_array) { + /* Fetch next row from virtual array */ + source->source_row--; + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, source->whole_image, + source->source_row, (JDIMENSION)1, FALSE); + inptr = image_ptr[0]; + } else { + if (!ReadOK(source->pub.input_file, source->iobuffer, source->row_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + inptr = source->iobuffer; + } /* Expand the colormap indexes to real data */ - inptr = image_ptr[0]; outptr = source->pub.buffer[0]; - for (col = cinfo->image_width; col > 0; col--) { - t = GETJSAMPLE(*inptr++); - *outptr++ = colormap[0][t]; /* can omit GETJSAMPLE() safely */ - *outptr++ = colormap[1][t]; - *outptr++ = colormap[2][t]; + if (cinfo->in_color_space == JCS_GRAYSCALE) { + for (col = cinfo->image_width; col > 0; col--) { + t = GETJSAMPLE(*inptr++); + if (t >= cmaplen) + ERREXIT(cinfo, JERR_BMP_OUTOFRANGE); + *outptr++ = colormap[0][t]; + } + } else if (cinfo->in_color_space == JCS_CMYK) { + for (col = cinfo->image_width; col > 0; col--) { + t = GETJSAMPLE(*inptr++); + if (t >= cmaplen) + ERREXIT(cinfo, JERR_BMP_OUTOFRANGE); + rgb_to_cmyk(colormap[0][t], colormap[1][t], colormap[2][t], outptr, + outptr + 1, outptr + 2, outptr + 3); + outptr += 4; + } + } else { + register int rindex = rgb_red[cinfo->in_color_space]; + register int gindex = rgb_green[cinfo->in_color_space]; + register int bindex = rgb_blue[cinfo->in_color_space]; + register int aindex = alpha_index[cinfo->in_color_space]; + register int ps = rgb_pixelsize[cinfo->in_color_space]; + + if (aindex >= 0) { + for (col = cinfo->image_width; col > 0; col--) { + t = GETJSAMPLE(*inptr++); + if (t >= cmaplen) + ERREXIT(cinfo, JERR_BMP_OUTOFRANGE); + outptr[rindex] = colormap[0][t]; + outptr[gindex] = colormap[1][t]; + outptr[bindex] = colormap[2][t]; + outptr[aindex] = 0xFF; + outptr += ps; + } + } else { + for (col = cinfo->image_width; col > 0; col--) { + t = GETJSAMPLE(*inptr++); + if (t >= cmaplen) + ERREXIT(cinfo, JERR_BMP_OUTOFRANGE); + outptr[rindex] = colormap[0][t]; + outptr[gindex] = colormap[1][t]; + outptr[bindex] = colormap[2][t]; + outptr += ps; + } + } } return 1; @@ -152,30 +229,63 @@ get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) METHODDEF(JDIMENSION) -get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +get_24bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* This version is for reading 24-bit pixels */ { - bmp_source_ptr source = (bmp_source_ptr) sinfo; + bmp_source_ptr source = (bmp_source_ptr)sinfo; JSAMPARRAY image_ptr; register JSAMPROW inptr, outptr; register JDIMENSION col; - /* Fetch next row from virtual array */ - source->source_row--; - image_ptr = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, source->whole_image, - source->source_row, (JDIMENSION) 1, FALSE); + if (source->use_inversion_array) { + /* Fetch next row from virtual array */ + source->source_row--; + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, source->whole_image, + source->source_row, (JDIMENSION)1, FALSE); + inptr = image_ptr[0]; + } else { + if (!ReadOK(source->pub.input_file, source->iobuffer, source->row_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + inptr = source->iobuffer; + } /* Transfer data. Note source values are in BGR order * (even though Microsoft's own documents say the opposite). */ - inptr = image_ptr[0]; outptr = source->pub.buffer[0]; - for (col = cinfo->image_width; col > 0; col--) { - outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */ - outptr[1] = *inptr++; - outptr[0] = *inptr++; - outptr += 3; + if (cinfo->in_color_space == JCS_EXT_BGR) { + MEMCOPY(outptr, inptr, source->row_width); + } else if (cinfo->in_color_space == JCS_CMYK) { + for (col = cinfo->image_width; col > 0; col--) { + /* can omit GETJSAMPLE() safely */ + JSAMPLE b = *inptr++, g = *inptr++, r = *inptr++; + rgb_to_cmyk(r, g, b, outptr, outptr + 1, outptr + 2, outptr + 3); + outptr += 4; + } + } else { + register int rindex = rgb_red[cinfo->in_color_space]; + register int gindex = rgb_green[cinfo->in_color_space]; + register int bindex = rgb_blue[cinfo->in_color_space]; + register int aindex = alpha_index[cinfo->in_color_space]; + register int ps = rgb_pixelsize[cinfo->in_color_space]; + + if (aindex >= 0) { + for (col = cinfo->image_width; col > 0; col--) { + outptr[bindex] = *inptr++; /* can omit GETJSAMPLE() safely */ + outptr[gindex] = *inptr++; + outptr[rindex] = *inptr++; + outptr[aindex] = 0xFF; + outptr += ps; + } + } else { + for (col = cinfo->image_width; col > 0; col--) { + outptr[bindex] = *inptr++; /* can omit GETJSAMPLE() safely */ + outptr[gindex] = *inptr++; + outptr[rindex] = *inptr++; + outptr += ps; + } + } } return 1; @@ -183,30 +293,66 @@ get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) METHODDEF(JDIMENSION) -get_32bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +get_32bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* This version is for reading 32-bit pixels */ { - bmp_source_ptr source = (bmp_source_ptr) sinfo; + bmp_source_ptr source = (bmp_source_ptr)sinfo; JSAMPARRAY image_ptr; register JSAMPROW inptr, outptr; register JDIMENSION col; - /* Fetch next row from virtual array */ - source->source_row--; - image_ptr = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, source->whole_image, - source->source_row, (JDIMENSION) 1, FALSE); + if (source->use_inversion_array) { + /* Fetch next row from virtual array */ + source->source_row--; + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr)cinfo, source->whole_image, + source->source_row, (JDIMENSION)1, FALSE); + inptr = image_ptr[0]; + } else { + if (!ReadOK(source->pub.input_file, source->iobuffer, source->row_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + inptr = source->iobuffer; + } + /* Transfer data. Note source values are in BGR order * (even though Microsoft's own documents say the opposite). */ - inptr = image_ptr[0]; outptr = source->pub.buffer[0]; - for (col = cinfo->image_width; col > 0; col--) { - outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */ - outptr[1] = *inptr++; - outptr[0] = *inptr++; - inptr++; /* skip the 4th byte (Alpha channel) */ - outptr += 3; + if (cinfo->in_color_space == JCS_EXT_BGRX || + cinfo->in_color_space == JCS_EXT_BGRA) { + MEMCOPY(outptr, inptr, source->row_width); + } else if (cinfo->in_color_space == JCS_CMYK) { + for (col = cinfo->image_width; col > 0; col--) { + /* can omit GETJSAMPLE() safely */ + JSAMPLE b = *inptr++, g = *inptr++, r = *inptr++; + rgb_to_cmyk(r, g, b, outptr, outptr + 1, outptr + 2, outptr + 3); + inptr++; /* skip the 4th byte (Alpha channel) */ + outptr += 4; + } + } else { + register int rindex = rgb_red[cinfo->in_color_space]; + register int gindex = rgb_green[cinfo->in_color_space]; + register int bindex = rgb_blue[cinfo->in_color_space]; + register int aindex = alpha_index[cinfo->in_color_space]; + register int ps = rgb_pixelsize[cinfo->in_color_space]; + + if (aindex >= 0) { + for (col = cinfo->image_width; col > 0; col--) { + outptr[bindex] = *inptr++; /* can omit GETJSAMPLE() safely */ + outptr[gindex] = *inptr++; + outptr[rindex] = *inptr++; + outptr[aindex] = *inptr++; + outptr += ps; + } + } else { + for (col = cinfo->image_width; col > 0; col--) { + outptr[bindex] = *inptr++; /* can omit GETJSAMPLE() safely */ + outptr[gindex] = *inptr++; + outptr[rindex] = *inptr++; + inptr++; /* skip the 4th byte (Alpha channel) */ + outptr += ps; + } + } } return 1; @@ -220,25 +366,24 @@ get_32bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) */ METHODDEF(JDIMENSION) -preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +preload_image(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) { - bmp_source_ptr source = (bmp_source_ptr) sinfo; + bmp_source_ptr source = (bmp_source_ptr)sinfo; register FILE *infile = source->pub.input_file; register JSAMPROW out_ptr; JSAMPARRAY image_ptr; JDIMENSION row; - cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; + cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress; /* Read the data into a virtual array in input-file row order. */ for (row = 0; row < cinfo->image_height; row++) { if (progress != NULL) { - progress->pub.pass_counter = (long) row; - progress->pub.pass_limit = (long) cinfo->image_height; - (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + progress->pub.pass_counter = (long)row; + progress->pub.pass_limit = (long)cinfo->image_height; + (*progress->pub.progress_monitor) ((j_common_ptr)cinfo); } image_ptr = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, source->whole_image, - row, (JDIMENSION) 1, TRUE); + ((j_common_ptr)cinfo, source->whole_image, row, (JDIMENSION)1, TRUE); out_ptr = image_ptr[0]; if (fread(out_ptr, 1, source->row_width, infile) != source->row_width) { if (feof(infile)) @@ -276,55 +421,59 @@ preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) */ METHODDEF(void) -start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +start_input_bmp(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) { - bmp_source_ptr source = (bmp_source_ptr) sinfo; + bmp_source_ptr source = (bmp_source_ptr)sinfo; U_CHAR bmpfileheader[14]; U_CHAR bmpinfoheader[64]; -#define GET_2B(array,offset) ((unsigned short) UCH(array[offset]) + \ - (((unsigned short) UCH(array[offset+1])) << 8)) -#define GET_4B(array,offset) ((unsigned int) UCH(array[offset]) + \ - (((unsigned int) UCH(array[offset+1])) << 8) + \ - (((unsigned int) UCH(array[offset+2])) << 16) + \ - (((unsigned int) UCH(array[offset+3])) << 24)) + +#define GET_2B(array, offset) \ + ((unsigned short)UCH(array[offset]) + \ + (((unsigned short)UCH(array[offset + 1])) << 8)) +#define GET_4B(array, offset) \ + ((unsigned int)UCH(array[offset]) + \ + (((unsigned int)UCH(array[offset + 1])) << 8) + \ + (((unsigned int)UCH(array[offset + 2])) << 16) + \ + (((unsigned int)UCH(array[offset + 3])) << 24)) + unsigned int bfOffBits; unsigned int headerSize; int biWidth; int biHeight; unsigned short biPlanes; unsigned int biCompression; - int biXPelsPerMeter,biYPelsPerMeter; + int biXPelsPerMeter, biYPelsPerMeter; unsigned int biClrUsed = 0; int mapentrysize = 0; /* 0 indicates no colormap */ int bPad; - JDIMENSION row_width; + JDIMENSION row_width = 0; /* Read and verify the bitmap file header */ - if (! ReadOK(source->pub.input_file, bmpfileheader, 14)) + if (!ReadOK(source->pub.input_file, bmpfileheader, 14)) ERREXIT(cinfo, JERR_INPUT_EOF); - if (GET_2B(bmpfileheader,0) != 0x4D42) /* 'BM' */ + if (GET_2B(bmpfileheader, 0) != 0x4D42) /* 'BM' */ ERREXIT(cinfo, JERR_BMP_NOT); - bfOffBits = GET_4B(bmpfileheader,10); + bfOffBits = GET_4B(bmpfileheader, 10); /* We ignore the remaining fileheader fields */ /* The infoheader might be 12 bytes (OS/2 1.x), 40 bytes (Windows), * or 64 bytes (OS/2 2.x). Check the first 4 bytes to find out which. */ - if (! ReadOK(source->pub.input_file, bmpinfoheader, 4)) + if (!ReadOK(source->pub.input_file, bmpinfoheader, 4)) ERREXIT(cinfo, JERR_INPUT_EOF); - headerSize = GET_4B(bmpinfoheader,0); + headerSize = GET_4B(bmpinfoheader, 0); if (headerSize < 12 || headerSize > 64) ERREXIT(cinfo, JERR_BMP_BADHEADER); - if (! ReadOK(source->pub.input_file, bmpinfoheader+4, headerSize-4)) + if (!ReadOK(source->pub.input_file, bmpinfoheader + 4, headerSize - 4)) ERREXIT(cinfo, JERR_INPUT_EOF); switch (headerSize) { case 12: /* Decode OS/2 1.x header (Microsoft calls this a BITMAPCOREHEADER) */ - biWidth = (int) GET_2B(bmpinfoheader,4); - biHeight = (int) GET_2B(bmpinfoheader,6); - biPlanes = GET_2B(bmpinfoheader,8); - source->bits_per_pixel = (int) GET_2B(bmpinfoheader,10); + biWidth = (int)GET_2B(bmpinfoheader, 4); + biHeight = (int)GET_2B(bmpinfoheader, 6); + biPlanes = GET_2B(bmpinfoheader, 8); + source->bits_per_pixel = (int)GET_2B(bmpinfoheader, 10); switch (source->bits_per_pixel) { case 8: /* colormapped image */ @@ -343,14 +492,14 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) case 64: /* Decode Windows 3.x header (Microsoft calls this a BITMAPINFOHEADER) */ /* or OS/2 2.x header, which has additional fields that we ignore */ - biWidth = (int) GET_4B(bmpinfoheader,4); - biHeight = (int) GET_4B(bmpinfoheader,8); - biPlanes = GET_2B(bmpinfoheader,12); - source->bits_per_pixel = (int) GET_2B(bmpinfoheader,14); - biCompression = GET_4B(bmpinfoheader,16); - biXPelsPerMeter = (int) GET_4B(bmpinfoheader,24); - biYPelsPerMeter = (int) GET_4B(bmpinfoheader,28); - biClrUsed = GET_4B(bmpinfoheader,32); + biWidth = (int)GET_4B(bmpinfoheader, 4); + biHeight = (int)GET_4B(bmpinfoheader, 8); + biPlanes = GET_2B(bmpinfoheader, 12); + source->bits_per_pixel = (int)GET_2B(bmpinfoheader, 14); + biCompression = GET_4B(bmpinfoheader, 16); + biXPelsPerMeter = (int)GET_4B(bmpinfoheader, 24); + biYPelsPerMeter = (int)GET_4B(bmpinfoheader, 28); + biClrUsed = GET_4B(bmpinfoheader, 32); /* biSizeImage, biClrImportant fields are ignored */ switch (source->bits_per_pixel) { @@ -373,8 +522,8 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) { /* Set JFIF density parameters from the BMP data */ - cinfo->X_density = (UINT16) (biXPelsPerMeter/100); /* 100 cm per meter */ - cinfo->Y_density = (UINT16) (biYPelsPerMeter/100); + cinfo->X_density = (UINT16)(biXPelsPerMeter / 100); /* 100 cm per meter */ + cinfo->Y_density = (UINT16)(biYPelsPerMeter / 100); cinfo->density_unit = 2; /* dots/cm */ } break; @@ -399,10 +548,10 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) ERREXIT(cinfo, JERR_BMP_BADCMAP); /* Allocate space to store the colormap */ source->colormap = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) biClrUsed, (JDIMENSION) 3); + ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)biClrUsed, (JDIMENSION)3); + source->cmap_length = (int)biClrUsed; /* and read it from the file */ - read_colormap(source, (int) biClrUsed, mapentrysize); + read_colormap(source, (int)biClrUsed, mapentrysize); /* account for size of colormap */ bPad -= biClrUsed * mapentrysize; } @@ -411,40 +560,95 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) if (bPad < 0) /* incorrect bfOffBits value? */ ERREXIT(cinfo, JERR_BMP_BADHEADER); while (--bPad >= 0) { - (void) read_byte(source); + (void)read_byte(source); } /* Compute row width in file, including padding to 4-byte boundary */ - if (source->bits_per_pixel == 24) - row_width = (JDIMENSION) (biWidth * 3); - else if (source->bits_per_pixel == 32) - row_width = (JDIMENSION) (biWidth * 4); - else - row_width = (JDIMENSION) biWidth; + switch (source->bits_per_pixel) { + case 8: + if (cinfo->in_color_space == JCS_UNKNOWN) + cinfo->in_color_space = JCS_EXT_RGB; + if (IsExtRGB(cinfo->in_color_space)) + cinfo->input_components = rgb_pixelsize[cinfo->in_color_space]; + else if (cinfo->in_color_space == JCS_GRAYSCALE) + cinfo->input_components = 1; + else if (cinfo->in_color_space == JCS_CMYK) + cinfo->input_components = 4; + else + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + row_width = (JDIMENSION)biWidth; + break; + case 24: + if (cinfo->in_color_space == JCS_UNKNOWN) + cinfo->in_color_space = JCS_EXT_BGR; + if (IsExtRGB(cinfo->in_color_space)) + cinfo->input_components = rgb_pixelsize[cinfo->in_color_space]; + else if (cinfo->in_color_space == JCS_CMYK) + cinfo->input_components = 4; + else + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + row_width = (JDIMENSION)(biWidth * 3); + break; + case 32: + if (cinfo->in_color_space == JCS_UNKNOWN) + cinfo->in_color_space = JCS_EXT_BGRA; + if (IsExtRGB(cinfo->in_color_space)) + cinfo->input_components = rgb_pixelsize[cinfo->in_color_space]; + else if (cinfo->in_color_space == JCS_CMYK) + cinfo->input_components = 4; + else + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + row_width = (JDIMENSION)(biWidth * 4); + break; + default: + ERREXIT(cinfo, JERR_BMP_BADDEPTH); + } while ((row_width & 3) != 0) row_width++; source->row_width = row_width; - /* Allocate space for inversion array, prepare for preload pass */ - source->whole_image = (*cinfo->mem->request_virt_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, - row_width, (JDIMENSION) biHeight, (JDIMENSION) 1); - source->pub.get_pixel_rows = preload_image; - if (cinfo->progress != NULL) { - cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; - progress->total_extra_passes++; /* count file input as separate pass */ + if (source->use_inversion_array) { + /* Allocate space for inversion array, prepare for preload pass */ + source->whole_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE, + row_width, (JDIMENSION)biHeight, (JDIMENSION)1); + source->pub.get_pixel_rows = preload_image; + if (cinfo->progress != NULL) { + cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress; + progress->total_extra_passes++; /* count file input as separate pass */ + } + } else { + source->iobuffer = (U_CHAR *) + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, row_width); + switch (source->bits_per_pixel) { + case 8: + source->pub.get_pixel_rows = get_8bit_row; + break; + case 24: + source->pub.get_pixel_rows = get_24bit_row; + break; + case 32: + source->pub.get_pixel_rows = get_32bit_row; + break; + default: + ERREXIT(cinfo, JERR_BMP_BADDEPTH); + } } + /* Ensure that biWidth * cinfo->input_components doesn't exceed the maximum + value of the JDIMENSION type. This is only a danger with BMP files, since + their width and height fields are 32-bit integers. */ + if ((unsigned long long)biWidth * + (unsigned long long)cinfo->input_components > 0xFFFFFFFFULL) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); /* Allocate one-row buffer for returned data */ source->pub.buffer = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) (biWidth * 3), (JDIMENSION) 1); + ((j_common_ptr)cinfo, JPOOL_IMAGE, + (JDIMENSION)(biWidth * cinfo->input_components), (JDIMENSION)1); source->pub.buffer_height = 1; - cinfo->in_color_space = JCS_RGB; - cinfo->input_components = 3; cinfo->data_precision = 8; - cinfo->image_width = (JDIMENSION) biWidth; - cinfo->image_height = (JDIMENSION) biHeight; + cinfo->image_width = (JDIMENSION)biWidth; + cinfo->image_height = (JDIMENSION)biHeight; } @@ -453,7 +657,7 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) */ METHODDEF(void) -finish_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +finish_input_bmp(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) { /* no work */ } @@ -464,20 +668,22 @@ finish_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) */ GLOBAL(cjpeg_source_ptr) -jinit_read_bmp (j_compress_ptr cinfo) +jinit_read_bmp(j_compress_ptr cinfo, boolean use_inversion_array) { bmp_source_ptr source; /* Create module interface object */ source = (bmp_source_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - sizeof(bmp_source_struct)); + (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, + sizeof(bmp_source_struct)); source->cinfo = cinfo; /* make back link for subroutines */ /* Fill in method ptrs, except get_pixel_rows which start_input sets */ source->pub.start_input = start_input_bmp; source->pub.finish_input = finish_input_bmp; - return (cjpeg_source_ptr) source; + source->use_inversion_array = use_inversion_array; + + return (cjpeg_source_ptr)source; } #endif /* BMP_SUPPORTED */ |