source: trunk/third/jpeg/wrrle.c @ 15227

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