Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/libjpeg/wrrle.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /* | |
| 2 * wrrle.c | |
| 3 * | |
| 4 * Copyright (C) 1991-1996, Thomas G. Lane. | |
| 5 * Modified 2017-2019 by Guido Vollbeding. | |
| 6 * This file is part of the Independent JPEG Group's software. | |
| 7 * For conditions of distribution and use, see the accompanying README file. | |
| 8 * | |
| 9 * This file contains routines to write output images in RLE format. | |
| 10 * The Utah Raster Toolkit library is required (version 3.1 or later). | |
| 11 * | |
| 12 * These routines may need modification for non-Unix environments or | |
| 13 * specialized applications. As they stand, they assume output to | |
| 14 * an ordinary stdio stream. | |
| 15 * | |
| 16 * Based on code contributed by Mike Lijewski, | |
| 17 * with updates from Robert Hutchinson. | |
| 18 */ | |
| 19 | |
| 20 #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ | |
| 21 | |
| 22 #ifdef RLE_SUPPORTED | |
| 23 | |
| 24 /* rle.h is provided by the Utah Raster Toolkit. */ | |
| 25 | |
| 26 #include <rle.h> | |
| 27 | |
| 28 /* | |
| 29 * We assume that JSAMPLE has the same representation as rle_pixel, | |
| 30 * to wit, "unsigned char". Hence we can't cope with 12- or 16-bit samples. | |
| 31 */ | |
| 32 | |
| 33 #if BITS_IN_JSAMPLE != 8 | |
| 34 Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */ | |
| 35 #endif | |
| 36 | |
| 37 | |
| 38 /* | |
| 39 * Since RLE stores scanlines bottom-to-top, we have to invert the image | |
| 40 * from JPEG's top-to-bottom order. To do this, we save the outgoing data | |
| 41 * in a virtual array during put_pixel_row calls, then actually emit the | |
| 42 * RLE file during finish_output. | |
| 43 */ | |
| 44 | |
| 45 | |
| 46 /* | |
| 47 * For now, if we emit an RLE color map then it is always 256 entries long, | |
| 48 * though not all of the entries need be used. | |
| 49 */ | |
| 50 | |
| 51 #define CMAPBITS 8 | |
| 52 #define CMAPLENGTH (1<<(CMAPBITS)) | |
| 53 | |
| 54 typedef struct { | |
| 55 struct djpeg_dest_struct pub; /* public fields */ | |
| 56 | |
| 57 jvirt_sarray_ptr image; /* virtual array to store the output image */ | |
| 58 rle_map *colormap; /* RLE-style color map, or NULL if none */ | |
| 59 rle_pixel **rle_row; /* To pass rows to rle_putrow() */ | |
| 60 | |
| 61 } rle_dest_struct; | |
| 62 | |
| 63 typedef rle_dest_struct * rle_dest_ptr; | |
| 64 | |
| 65 | |
| 66 /* Forward declarations */ | |
| 67 METHODDEF(void) rle_put_pixel_rows | |
| 68 JPP((j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, | |
| 69 JDIMENSION rows_supplied)); | |
| 70 | |
| 71 | |
| 72 /* | |
| 73 * Write the file header. | |
| 74 * | |
| 75 * In this module it's easier to wait till finish_output to write anything. | |
| 76 */ | |
| 77 | |
| 78 METHODDEF(void) | |
| 79 start_output_rle (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) | |
| 80 { | |
| 81 rle_dest_ptr dest = (rle_dest_ptr) dinfo; | |
| 82 size_t cmapsize; | |
| 83 int ci, i; | |
| 84 #ifdef PROGRESS_REPORT | |
| 85 cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; | |
| 86 #endif | |
| 87 | |
| 88 /* | |
| 89 * Make sure the image can be stored in RLE format. | |
| 90 * | |
| 91 * - RLE stores image dimensions as *signed* 16 bit integers. JPEG | |
| 92 * uses unsigned, so we have to check the width. | |
| 93 * | |
| 94 * - Colorspace is expected to be grayscale or RGB. | |
| 95 * | |
| 96 * - The number of channels (components) is expected to be 1 (grayscale/ | |
| 97 * pseudocolor) or 3 (truecolor/directcolor). | |
| 98 * (could be 2 or 4 if using an alpha channel, but we aren't) | |
| 99 */ | |
| 100 | |
| 101 if (cinfo->output_width > 32767 || cinfo->output_height > 32767) | |
| 102 ERREXIT2(cinfo, JERR_RLE_DIMENSIONS, cinfo->output_width, | |
| 103 cinfo->output_height); | |
| 104 | |
| 105 if (cinfo->out_color_space != JCS_GRAYSCALE && | |
| 106 cinfo->out_color_space != JCS_RGB) | |
| 107 ERREXIT(cinfo, JERR_RLE_COLORSPACE); | |
| 108 | |
| 109 if (cinfo->output_components != 1 && cinfo->output_components != 3) | |
| 110 ERREXIT1(cinfo, JERR_RLE_TOOMANYCHANNELS, cinfo->num_components); | |
| 111 | |
| 112 /* Convert colormap, if any, to RLE format. */ | |
| 113 | |
| 114 dest->colormap = NULL; | |
| 115 | |
| 116 if (cinfo->quantize_colors) { | |
| 117 /* Allocate storage for RLE-style cmap, zero any extra entries */ | |
| 118 cmapsize = cinfo->out_color_components * CMAPLENGTH * SIZEOF(rle_map); | |
| 119 dest->colormap = (rle_map *) (*cinfo->mem->alloc_small) | |
| 120 ((j_common_ptr) cinfo, JPOOL_IMAGE, cmapsize); | |
| 121 MEMZERO(dest->colormap, cmapsize); | |
| 122 | |
| 123 /* Save away data in RLE format --- note 8-bit left shift! */ | |
| 124 /* Shifting would need adjustment for JSAMPLEs wider than 8 bits. */ | |
| 125 for (ci = 0; ci < cinfo->out_color_components; ci++) { | |
| 126 for (i = 0; i < cinfo->actual_number_of_colors; i++) { | |
| 127 dest->colormap[ci * CMAPLENGTH + i] = | |
| 128 GETJSAMPLE(cinfo->colormap[ci][i]) << 8; | |
| 129 } | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 /* Set the output buffer to the first row */ | |
| 134 dest->pub.buffer = (*cinfo->mem->access_virt_sarray) | |
| 135 ((j_common_ptr) cinfo, dest->image, (JDIMENSION) 0, (JDIMENSION) 1, TRUE); | |
| 136 dest->pub.buffer_height = 1; | |
| 137 | |
| 138 dest->pub.put_pixel_rows = rle_put_pixel_rows; | |
| 139 | |
| 140 #ifdef PROGRESS_REPORT | |
| 141 if (progress != NULL) { | |
| 142 progress->total_extra_passes++; /* count file writing as separate pass */ | |
| 143 } | |
| 144 #endif | |
| 145 } | |
| 146 | |
| 147 | |
| 148 /* | |
| 149 * Write some pixel data. | |
| 150 * | |
| 151 * This routine just saves the data away in a virtual array. | |
| 152 */ | |
| 153 | |
| 154 METHODDEF(void) | |
| 155 rle_put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, | |
| 156 JDIMENSION rows_supplied) | |
| 157 { | |
| 158 rle_dest_ptr dest = (rle_dest_ptr) dinfo; | |
| 159 | |
| 160 if (cinfo->output_scanline < cinfo->output_height) { | |
| 161 dest->pub.buffer = (*cinfo->mem->access_virt_sarray) | |
| 162 ((j_common_ptr) cinfo, dest->image, | |
| 163 cinfo->output_scanline, (JDIMENSION) 1, TRUE); | |
| 164 } | |
| 165 } | |
| 166 | |
| 167 | |
| 168 /* | |
| 169 * Finish up at the end of the file. | |
| 170 * | |
| 171 * Here is where we really output the RLE file. | |
| 172 */ | |
| 173 | |
| 174 METHODDEF(void) | |
| 175 finish_output_rle (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) | |
| 176 { | |
| 177 rle_dest_ptr dest = (rle_dest_ptr) dinfo; | |
| 178 rle_hdr header; /* Output file information */ | |
| 179 rle_pixel **rle_row, *red_ptr, *green_ptr, *blue_ptr; | |
| 180 JSAMPROW output_row; | |
| 181 char cmapcomment[80]; | |
| 182 int row, col; | |
| 183 int ci; | |
| 184 #ifdef PROGRESS_REPORT | |
| 185 cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; | |
| 186 #endif | |
| 187 | |
| 188 /* Initialize the header info */ | |
| 189 header = *rle_hdr_init(NULL); | |
| 190 header.rle_file = dest->pub.output_file; | |
| 191 header.xmin = 0; | |
| 192 header.xmax = cinfo->output_width - 1; | |
| 193 header.ymin = 0; | |
| 194 header.ymax = cinfo->output_height - 1; | |
| 195 header.alpha = 0; | |
| 196 header.ncolors = cinfo->output_components; | |
| 197 for (ci = 0; ci < cinfo->output_components; ci++) { | |
| 198 RLE_SET_BIT(header, ci); | |
| 199 } | |
| 200 if (cinfo->quantize_colors) { | |
| 201 header.ncmap = cinfo->out_color_components; | |
| 202 header.cmaplen = CMAPBITS; | |
| 203 header.cmap = dest->colormap; | |
| 204 /* Add a comment to the output image with the true colormap length. */ | |
| 205 sprintf(cmapcomment, "color_map_length=%d", cinfo->actual_number_of_colors); | |
| 206 rle_putcom(cmapcomment, &header); | |
| 207 } | |
| 208 | |
| 209 /* Emit the RLE header and color map (if any) */ | |
| 210 rle_put_setup(&header); | |
| 211 | |
| 212 /* Now output the RLE data from our virtual array. | |
| 213 * We assume here that (a) rle_pixel is represented the same as JSAMPLE, | |
| 214 * and (b) we are not on a machine where FAR pointers differ from regular. | |
| 215 */ | |
| 216 | |
| 217 #ifdef PROGRESS_REPORT | |
| 218 if (progress != NULL) { | |
| 219 progress->pub.pass_limit = cinfo->output_height; | |
| 220 progress->pub.pass_counter = 0; | |
| 221 (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); | |
| 222 } | |
| 223 #endif | |
| 224 | |
| 225 if (cinfo->output_components == 1) { | |
| 226 for (row = cinfo->output_height - 1; row >= 0; row--) { | |
| 227 rle_row = (rle_pixel **) (*cinfo->mem->access_virt_sarray) | |
| 228 ((j_common_ptr) cinfo, dest->image, | |
| 229 (JDIMENSION) row, (JDIMENSION) 1, FALSE); | |
| 230 rle_putrow(rle_row, (int) cinfo->output_width, &header); | |
| 231 #ifdef PROGRESS_REPORT | |
| 232 if (progress != NULL) { | |
| 233 progress->pub.pass_counter++; | |
| 234 (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); | |
| 235 } | |
| 236 #endif | |
| 237 } | |
| 238 } else { | |
| 239 for (row = cinfo->output_height - 1; row >= 0; row--) { | |
| 240 output_row = * (*cinfo->mem->access_virt_sarray) | |
| 241 ((j_common_ptr) cinfo, dest->image, | |
| 242 (JDIMENSION) row, (JDIMENSION) 1, FALSE); | |
| 243 rle_row = dest->rle_row; | |
| 244 red_ptr = rle_row[0]; | |
| 245 green_ptr = rle_row[1]; | |
| 246 blue_ptr = rle_row[2]; | |
| 247 for (col = cinfo->output_width; col > 0; col--) { | |
| 248 *red_ptr++ = GETJSAMPLE(*output_row++); | |
| 249 *green_ptr++ = GETJSAMPLE(*output_row++); | |
| 250 *blue_ptr++ = GETJSAMPLE(*output_row++); | |
| 251 } | |
| 252 rle_putrow(rle_row, (int) cinfo->output_width, &header); | |
| 253 #ifdef PROGRESS_REPORT | |
| 254 if (progress != NULL) { | |
| 255 progress->pub.pass_counter++; | |
| 256 (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); | |
| 257 } | |
| 258 #endif | |
| 259 } | |
| 260 } | |
| 261 | |
| 262 #ifdef PROGRESS_REPORT | |
| 263 if (progress != NULL) | |
| 264 progress->completed_extra_passes++; | |
| 265 #endif | |
| 266 | |
| 267 /* Emit file trailer */ | |
| 268 rle_puteof(&header); | |
| 269 JFFLUSH(dest->pub.output_file); | |
| 270 if (JFERROR(dest->pub.output_file)) | |
| 271 ERREXIT(cinfo, JERR_FILE_WRITE); | |
| 272 } | |
| 273 | |
| 274 | |
| 275 /* | |
| 276 * The module selection routine for RLE format output. | |
| 277 */ | |
| 278 | |
| 279 GLOBAL(djpeg_dest_ptr) | |
| 280 jinit_write_rle (j_decompress_ptr cinfo) | |
| 281 { | |
| 282 rle_dest_ptr dest; | |
| 283 | |
| 284 /* Create module interface object, fill in method pointers */ | |
| 285 dest = (rle_dest_ptr) (*cinfo->mem->alloc_small) | |
| 286 ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(rle_dest_struct)); | |
| 287 dest->pub.start_output = start_output_rle; | |
| 288 dest->pub.finish_output = finish_output_rle; | |
| 289 | |
| 290 /* Calculate output image dimensions so we can allocate space */ | |
| 291 jpeg_calc_output_dimensions(cinfo); | |
| 292 | |
| 293 /* Allocate a work array for output to the RLE library. */ | |
| 294 dest->rle_row = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, | |
| 295 JPOOL_IMAGE, cinfo->output_width, (JDIMENSION) cinfo->output_components); | |
| 296 | |
| 297 /* Allocate a virtual array to hold the image. */ | |
| 298 dest->image = (*cinfo->mem->request_virt_sarray) | |
| 299 ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, | |
| 300 cinfo->output_width * (JDIMENSION) cinfo->output_components, | |
| 301 cinfo->output_height, (JDIMENSION) 1); | |
| 302 | |
| 303 return &dest->pub; | |
| 304 } | |
| 305 | |
| 306 #endif /* RLE_SUPPORTED */ |
