~ubuntu-branches/ubuntu/lucid/graphviz/lucid-security

« back to all changes in this revision

Viewing changes to gd/gd_jpeg.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen M Moraco
  • Date: 2002-02-05 18:52:12 UTC
  • Revision ID: james.westby@ubuntu.com-20020205185212-8i04c70te00rc40y
Tags: upstream-1.7.16
ImportĀ upstreamĀ versionĀ 1.7.16

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
 
 
3
/*
 
4
 * gd_jpeg.c: Read and write JPEG (JFIF) format image files using the
 
5
 * gd graphics library (http://www.boutell.com/gd/).
 
6
 * 
 
7
 * This software is based in part on the work of the Independent JPEG
 
8
 * Group.  For more information on the IJG JPEG software (and JPEG
 
9
 * documentation, etc.), see ftp://ftp.uu.net/graphics/jpeg/.
 
10
 *
 
11
 * NOTE: IJG 12-bit JSAMPLE (BITS_IN_JSAMPLE == 12) mode is not
 
12
 * supported at all on read in gd 2.0, and is not supported on write
 
13
 * except for palette images, which is sort of pointless (TBB). Even that
 
14
 * has never been tested according to DB.
 
15
 *
 
16
 * Copyright 2000 Doug Becker, mailto:thebeckers@home.com
 
17
 *
 
18
 * Modification 4/18/00 TBB: JPEG_DEBUG rather than just DEBUG,
 
19
 * so VC++ builds don't spew to standard output, causing
 
20
 * major CGI brain damage
 
21
 */
 
22
 
 
23
#include <stdio.h>
 
24
#include <stdlib.h>
 
25
#include <setjmp.h>
 
26
#include <limits.h>
 
27
#include <string.h>
 
28
 
 
29
#include "gd.h"
 
30
 
 
31
/* TBB: move this up so include files are not brought in */
 
32
/* JCE: HAVE_LIBJPEG is set by gvconfig.h in gd.h */
 
33
#ifdef HAVE_LIBJPEG
 
34
 
 
35
#include "gdhelpers.h"
 
36
/* 1.8.1: remove dependency on jinclude.h */
 
37
#include "jpeglib.h"
 
38
#include "jerror.h"
 
39
 
 
40
static const char *const GD_JPEG_VERSION = "1.0";
 
41
 
 
42
typedef struct _jmpbuf_wrapper
 
43
  {
 
44
    jmp_buf jmpbuf;
 
45
  }
 
46
jmpbuf_wrapper;
 
47
 
 
48
/* Called by the IJG JPEG library upon encountering a fatal error */
 
49
static void
 
50
fatal_jpeg_error (j_common_ptr cinfo)
 
51
{
 
52
  jmpbuf_wrapper *jmpbufw;
 
53
 
 
54
  fprintf (stderr, "gd-jpeg: JPEG library reports unrecoverable error: ");
 
55
  (*cinfo->err->output_message) (cinfo);
 
56
  fflush (stderr);
 
57
 
 
58
  jmpbufw = (jmpbuf_wrapper *) cinfo->client_data;
 
59
  jpeg_destroy (cinfo);
 
60
 
 
61
  if (jmpbufw != 0)
 
62
    {
 
63
      longjmp (jmpbufw->jmpbuf, 1);
 
64
      fprintf (stderr, "gd-jpeg: EXTREMELY fatal error: longjmp"
 
65
               " returned control; terminating\n");
 
66
    }
 
67
  else
 
68
    {
 
69
      fprintf (stderr, "gd-jpeg: EXTREMELY fatal error: jmpbuf"
 
70
               " unrecoverable; terminating\n");
 
71
    }
 
72
 
 
73
  fflush (stderr);
 
74
  exit (99);
 
75
}
 
76
 
 
77
/*
 
78
 * Write IM to OUTFILE as a JFIF-formatted JPEG image, using quality
 
79
 * QUALITY.  If QUALITY is in the range 0-100, increasing values
 
80
 * represent higher quality but also larger image size.  If QUALITY is
 
81
 * negative, the IJG JPEG library's default quality is used (which
 
82
 * should be near optimal for many applications).  See the IJG JPEG
 
83
 * library documentation for more details.  */
 
84
 
 
85
void
 
86
gdImageJpeg (gdImagePtr im, FILE * outFile, int quality)
 
87
{
 
88
  gdIOCtx *out = gdNewFileCtx (outFile);
 
89
  gdImageJpegCtx (im, out, quality);
 
90
  out->free (out);
 
91
}
 
92
 
 
93
void *
 
94
gdImageJpegPtr (gdImagePtr im, int *size, int quality)
 
95
{
 
96
  void *rv;
 
97
  gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
 
98
  gdImageJpegCtx (im, out, quality);
 
99
  rv = gdDPExtractData (out, size);
 
100
  out->free (out);
 
101
  return rv;
 
102
}
 
103
 
 
104
void jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile);
 
105
 
 
106
void
 
107
gdImageJpegCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
 
108
{
 
109
  struct jpeg_compress_struct cinfo;
 
110
  struct jpeg_error_mgr jerr;
 
111
  int i, j, jidx;
 
112
  /* volatile so we can gdFree it on return from longjmp */
 
113
  volatile JSAMPROW row = 0;
 
114
  JSAMPROW rowptr[1];
 
115
  jmpbuf_wrapper jmpbufw;
 
116
  JDIMENSION nlines;
 
117
  char comment[255];
 
118
 
 
119
#ifdef JPEG_DEBUG
 
120
  printf ("gd-jpeg: gd JPEG version %s\n", GD_JPEG_VERSION);
 
121
  printf ("gd-jpeg: JPEG library version %d, %d-bit sample values\n",
 
122
          JPEG_LIB_VERSION, BITS_IN_JSAMPLE);
 
123
  if (!im->trueColor)
 
124
    {
 
125
      for (i = 0; i < im->colorsTotal; i++)
 
126
        {
 
127
          if (!im->open[i])
 
128
            printf ("gd-jpeg: gd colormap index %d: (%d, %d, %d)\n", i,
 
129
                    im->red[i], im->green[i], im->blue[i]);
 
130
        }
 
131
    }
 
132
#endif /* JPEG_DEBUG */
 
133
 
 
134
  memset (&cinfo, 0, sizeof (cinfo));
 
135
  memset (&jerr, 0, sizeof (jerr));
 
136
 
 
137
  cinfo.err = jpeg_std_error (&jerr);
 
138
  cinfo.client_data = &jmpbufw;
 
139
  if (setjmp (jmpbufw.jmpbuf) != 0)
 
140
    {
 
141
      /* we're here courtesy of longjmp */
 
142
      if (row)
 
143
        gdFree (row);
 
144
      return;
 
145
    }
 
146
 
 
147
  cinfo.err->error_exit = fatal_jpeg_error;
 
148
 
 
149
  jpeg_create_compress (&cinfo);
 
150
 
 
151
  cinfo.image_width = im->sx;
 
152
  cinfo.image_height = im->sy;
 
153
  cinfo.input_components = 3;   /* # of color components per pixel */
 
154
  cinfo.in_color_space = JCS_RGB;       /* colorspace of input image */
 
155
  jpeg_set_defaults (&cinfo);
 
156
  if (quality >= 0)
 
157
    jpeg_set_quality (&cinfo, quality, TRUE);
 
158
 
 
159
  /* If user requests interlace, translate that to progressive JPEG */
 
160
  if (gdImageGetInterlaced (im))
 
161
    {
 
162
#ifdef JPEG_DEBUG
 
163
      printf ("gd-jpeg: interlace set, outputting progressive"
 
164
              " JPEG image\n");
 
165
#endif
 
166
      jpeg_simple_progression (&cinfo);
 
167
    }
 
168
 
 
169
  jpeg_gdIOCtx_dest (&cinfo, outfile);
 
170
 
 
171
  row = (JSAMPROW) gdCalloc (1, cinfo.image_width * cinfo.input_components
 
172
                             * sizeof (JSAMPLE));
 
173
  if (row == 0)
 
174
    {
 
175
      fprintf (stderr, "gd-jpeg: error: unable to allocate JPEG row "
 
176
               "structure: gdCalloc returns NULL\n");
 
177
      jpeg_destroy_compress (&cinfo);
 
178
      return;
 
179
    }
 
180
 
 
181
  rowptr[0] = row;
 
182
 
 
183
  jpeg_start_compress (&cinfo, TRUE);
 
184
 
 
185
  sprintf (comment, "CREATOR: gd-jpeg v%s (using IJG JPEG v%d),",
 
186
           GD_JPEG_VERSION, JPEG_LIB_VERSION);
 
187
  if (quality >= 0)
 
188
    sprintf (comment + strlen (comment), " quality = %d\n",
 
189
             quality);
 
190
  else
 
191
    strcat (comment + strlen (comment), " default quality\n");
 
192
  jpeg_write_marker (&cinfo, JPEG_COM, (unsigned char *) comment,
 
193
                     (unsigned int) strlen (comment));
 
194
  if (im->trueColor)
 
195
    {
 
196
#if BITS_IN_JSAMPLE == 12
 
197
      fprintf (stderr, "gd-jpeg: error: jpeg library was compiled for 12-bit\n"
 
198
         "precision. This is mostly useless, because JPEGs on the web are\n"
 
199
         "8-bit and such versions of the jpeg library won't read or write\n"
 
200
               "them. GD doesn't support these unusual images. Edit your\n"
 
201
         "jmorecfg.h file to specify the correct precision and completely\n"
 
202
               "'make clean' and 'make install' libjpeg again. Sorry.\n");
 
203
      goto error;
 
204
#endif /* BITS_IN_JSAMPLE == 12 */
 
205
      for (i = 0; i < im->sy; i++)
 
206
        {
 
207
          for (jidx = 0, j = 0; j < im->sx; j++)
 
208
            {
 
209
              int val = im->tpixels[i][j];
 
210
              row[jidx++] = gdTrueColorGetRed (val);
 
211
              row[jidx++] = gdTrueColorGetGreen (val);
 
212
              row[jidx++] = gdTrueColorGetBlue (val);
 
213
            }
 
214
 
 
215
          nlines = jpeg_write_scanlines (&cinfo, rowptr, 1);
 
216
          if (nlines != 1)
 
217
            fprintf (stderr, "gd_jpeg: warning: jpeg_write_scanlines"
 
218
                     " returns %u -- expected 1\n", nlines);
 
219
        }
 
220
    }
 
221
  else
 
222
    {
 
223
      for (i = 0; i < im->sy; i++)
 
224
        {
 
225
          for (jidx = 0, j = 0; j < im->sx; j++)
 
226
            {
 
227
              int idx = im->pixels[i][j];
 
228
 
 
229
              /*
 
230
               * NB: Although gd RGB values are ints, their max value is
 
231
               * 255 (see the documentation for gdImageColorAllocate())
 
232
               * -- perfect for 8-bit JPEG encoding (which is the norm)
 
233
               */
 
234
#if BITS_IN_JSAMPLE == 8
 
235
              row[jidx++] = im->red[idx];
 
236
              row[jidx++] = im->green[idx];
 
237
              row[jidx++] = im->blue[idx];
 
238
#elif BITS_IN_JSAMPLE == 12
 
239
              row[jidx++] = im->red[idx] << 4;
 
240
              row[jidx++] = im->green[idx] << 4;
 
241
              row[jidx++] = im->blue[idx] << 4;
 
242
#else
 
243
#error IJG JPEG library BITS_IN_JSAMPLE value must be 8 or 12
 
244
#endif
 
245
            }
 
246
 
 
247
          nlines = jpeg_write_scanlines (&cinfo, rowptr, 1);
 
248
          if (nlines != 1)
 
249
            fprintf (stderr, "gd_jpeg: warning: jpeg_write_scanlines"
 
250
                     " returns %u -- expected 1\n", nlines);
 
251
        }
 
252
    }
 
253
  jpeg_finish_compress (&cinfo);
 
254
error:
 
255
  jpeg_destroy_compress (&cinfo);
 
256
  gdFree (row);
 
257
}
 
258
 
 
259
gdImagePtr
 
260
gdImageCreateFromJpeg (FILE * inFile)
 
261
{
 
262
  gdImagePtr im;
 
263
  gdIOCtx *in = gdNewFileCtx (inFile);
 
264
  im = gdImageCreateFromJpegCtx (in);
 
265
  in->free (in);
 
266
  return im;
 
267
}
 
268
 
 
269
void
 
270
  jpeg_gdIOCtx_src (j_decompress_ptr cinfo,
 
271
                    gdIOCtx * infile);
 
272
 
 
273
/* 
 
274
 * Create a gd-format image from the JPEG-format INFILE.  Returns the
 
275
 * image, or NULL upon error.
 
276
 */
 
277
gdImagePtr
 
278
gdImageCreateFromJpegCtx (gdIOCtx * infile)
 
279
{
 
280
  struct jpeg_decompress_struct cinfo;
 
281
  struct jpeg_error_mgr jerr;
 
282
  jmpbuf_wrapper jmpbufw;
 
283
  /* volatile so we can gdFree them after longjmp */
 
284
  volatile JSAMPROW row = 0;
 
285
  volatile gdImagePtr im = 0;
 
286
  JSAMPROW rowptr[1];
 
287
  int i, j, retval;
 
288
  JDIMENSION nrows;
 
289
 
 
290
#ifdef JPEG_DEBUG
 
291
  printf ("gd-jpeg: gd JPEG version %s\n", GD_JPEG_VERSION);
 
292
  printf ("gd-jpeg: JPEG library version %d, %d-bit sample values\n",
 
293
          JPEG_LIB_VERSION, BITS_IN_JSAMPLE);
 
294
#endif
 
295
 
 
296
  memset (&cinfo, 0, sizeof (cinfo));
 
297
  memset (&jerr, 0, sizeof (jerr));
 
298
 
 
299
  cinfo.err = jpeg_std_error (&jerr);
 
300
  cinfo.client_data = &jmpbufw;
 
301
  if (setjmp (jmpbufw.jmpbuf) != 0)
 
302
    {
 
303
      /* we're here courtesy of longjmp */
 
304
      if (row)
 
305
        gdFree (row);
 
306
      if (im)
 
307
        gdImageDestroy (im);
 
308
      return 0;
 
309
    }
 
310
 
 
311
  cinfo.err->error_exit = fatal_jpeg_error;
 
312
 
 
313
  jpeg_create_decompress (&cinfo);
 
314
 
 
315
  jpeg_gdIOCtx_src (&cinfo, infile);
 
316
 
 
317
  retval = jpeg_read_header (&cinfo, TRUE);
 
318
  if (retval != JPEG_HEADER_OK)
 
319
    fprintf (stderr, "gd-jpeg: warning: jpeg_read_header returns"
 
320
             " %d, expected %d\n", retval, JPEG_HEADER_OK);
 
321
 
 
322
  if (cinfo.image_height > INT_MAX)
 
323
    fprintf (stderr, "gd-jpeg: warning: JPEG image height (%u) is"
 
324
             " greater than INT_MAX (%d) (and thus greater than"
 
325
             " gd can handle)", cinfo.image_height,
 
326
             INT_MAX);
 
327
 
 
328
  if (cinfo.image_width > INT_MAX)
 
329
    fprintf (stderr, "gd-jpeg: warning: JPEG image width (%u) is"
 
330
             " greater than INT_MAX (%d) (and thus greater than"
 
331
             " gd can handle)\n", cinfo.image_width, INT_MAX);
 
332
 
 
333
  im = gdImageCreateTrueColor ((int) cinfo.image_width,
 
334
                               (int) cinfo.image_height);
 
335
  if (im == 0)
 
336
    {
 
337
      fprintf (stderr, "gd-jpeg error: cannot allocate gdImage"
 
338
               " struct\n");
 
339
      goto error;
 
340
    }
 
341
 
 
342
  /*
 
343
   * Force the image into RGB colorspace, but don't 
 
344
   * reduce the number of colors anymore (GD 2.0) 
 
345
   */
 
346
  cinfo.out_color_space = JCS_RGB;
 
347
 
 
348
  if (jpeg_start_decompress (&cinfo) != TRUE)
 
349
    fprintf (stderr, "gd-jpeg: warning: jpeg_start_decompress"
 
350
             " reports suspended data source\n");
 
351
 
 
352
#ifdef JPEG_DEBUG
 
353
  printf ("gd-jpeg: JPEG image information:");
 
354
  if (cinfo.saw_JFIF_marker)
 
355
    printf (" JFIF version %d.%.2d",
 
356
            (int) cinfo.JFIF_major_version,
 
357
            (int) cinfo.JFIF_minor_version);
 
358
  else if (cinfo.saw_Adobe_marker)
 
359
    printf (" Adobe format");
 
360
  else
 
361
    printf (" UNKNOWN format");
 
362
 
 
363
  printf (" %ux%u (raw) / %ux%u (scaled) %d-bit", cinfo.image_width,
 
364
          cinfo.image_height, cinfo.output_width,
 
365
          cinfo.output_height, cinfo.data_precision);
 
366
  printf (" %s", (cinfo.progressive_mode ? "progressive" :
 
367
                  "baseline"));
 
368
  printf (" image, %d quantized colors, ",
 
369
          cinfo.actual_number_of_colors);
 
370
 
 
371
  switch (cinfo.jpeg_color_space)
 
372
    {
 
373
    case JCS_GRAYSCALE:
 
374
      printf ("grayscale");
 
375
      break;
 
376
 
 
377
    case JCS_RGB:
 
378
      printf ("RGB");
 
379
      break;
 
380
 
 
381
    case JCS_YCbCr:
 
382
      printf ("YCbCr (a.k.a. YUV)");
 
383
      break;
 
384
 
 
385
    case JCS_CMYK:
 
386
      printf ("CMYK");
 
387
      break;
 
388
 
 
389
    case JCS_YCCK:
 
390
      printf ("YCbCrK");
 
391
      break;
 
392
 
 
393
    default:
 
394
      printf ("UNKNOWN (value: %d)", (int) cinfo.jpeg_color_space);
 
395
      break;
 
396
    }
 
397
  printf (" colorspace\n");
 
398
  fflush (stdout);
 
399
#endif /* JPEG_DEBUG */
 
400
 
 
401
  /* REMOVED by TBB 2/12/01. This field of the structure is
 
402
     documented as private, and sure enough it's gone in the
 
403
     latest libjpeg, replaced by something else. Unfortunately
 
404
     there is still no right way to find out if the file was
 
405
     progressive or not; just declare your intent before you
 
406
     write one by calling gdImageInterlace(im, 1) yourself. 
 
407
     After all, we're not really supposed to rework JPEGs and
 
408
     write them out again anyway. Lossy compression, remember? */
 
409
#if 0
 
410
  gdImageInterlace (im, cinfo.progressive_mode != 0);
 
411
#endif
 
412
  if (cinfo.output_components != 3)
 
413
    {
 
414
      fprintf (stderr, "gd-jpeg: error: JPEG color quantization"
 
415
               " request resulted in output_components == %d"
 
416
               " (expected 3)\n", cinfo.output_components);
 
417
      goto error;
 
418
    }
 
419
 
 
420
#if BITS_IN_JSAMPLE == 12
 
421
  fprintf (stderr, "gd-jpeg: error: jpeg library was compiled for 12-bit\n"
 
422
         "precision. This is mostly useless, because JPEGs on the web are\n"
 
423
         "8-bit and such versions of the jpeg library won't read or write\n"
 
424
           "them. GD doesn't support these unusual images. Edit your\n"
 
425
         "jmorecfg.h file to specify the correct precision and completely\n"
 
426
           "'make clean' and 'make install' libjpeg again. Sorry.\n");
 
427
  goto error;
 
428
#endif /* BITS_IN_JSAMPLE == 12 */
 
429
 
 
430
  row = gdCalloc (cinfo.output_width * 3, sizeof (JSAMPLE));
 
431
  if (row == 0)
 
432
    {
 
433
      fprintf (stderr, "gd-jpeg: error: unable to allocate row for"
 
434
               " JPEG scanline: gdCalloc returns NULL\n");
 
435
      goto error;
 
436
    }
 
437
  rowptr[0] = row;
 
438
 
 
439
  for (i = 0; i < cinfo.output_height; i++)
 
440
    {
 
441
      nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
 
442
      if (nrows != 1)
 
443
        {
 
444
          fprintf (stderr, "gd-jpeg: error: jpeg_read_scanlines"
 
445
                   " returns %u, expected 1\n", nrows);
 
446
          goto error;
 
447
        }
 
448
 
 
449
      for (j = 0; j < cinfo.output_width; j++)
 
450
        im->tpixels[i][j] = gdTrueColor (row[j * 3], row[j * 3 + 1],
 
451
                                         row[j * 3 + 2]);
 
452
    }
 
453
 
 
454
  if (jpeg_finish_decompress (&cinfo) != TRUE)
 
455
    fprintf (stderr, "gd-jpeg: warning: jpeg_finish_decompress"
 
456
             " reports suspended data source\n");
 
457
 
 
458
 
 
459
  jpeg_destroy_decompress (&cinfo);
 
460
  gdFree (row);
 
461
  return im;
 
462
 
 
463
error:
 
464
  jpeg_destroy_decompress (&cinfo);
 
465
  if (row)
 
466
    gdFree (row);
 
467
  if (im)
 
468
    gdImageDestroy (im);
 
469
  return 0;
 
470
}
 
471
 
 
472
/*
 
473
 
 
474
 * gdIOCtx JPEG data sources and sinks, T. Boutell
 
475
 * almost a simple global replace from T. Lane's stdio versions.
 
476
 *
 
477
 */
 
478
 
 
479
/* Different versions of libjpeg use either 'jboolean' or 'boolean', and
 
480
   some platforms define 'boolean', and so forth. Deal with this
 
481
   madness by typedeffing 'safeboolean' to 'boolean' if HAVE_BOOLEAN
 
482
   is already set, because this is the test that libjpeg uses.
 
483
   Otherwise, typedef it to int, because that's what libjpeg does
 
484
   if HAVE_BOOLEAN is not defined. -TBB */
 
485
 
 
486
#ifdef HAVE_BOOLEAN
 
487
typedef boolean safeboolean;
 
488
#else
 
489
typedef int safeboolean;
 
490
#endif /* HAVE_BOOLEAN */
 
491
 
 
492
/* Expanded data source object for gdIOCtx input */
 
493
 
 
494
typedef struct
 
495
  {
 
496
    struct jpeg_source_mgr pub; /* public fields */
 
497
 
 
498
    gdIOCtx *infile;            /* source stream */
 
499
    unsigned char *buffer;      /* start of buffer */
 
500
    safeboolean start_of_file;  /* have we gotten any data yet? */
 
501
     
 
502
  }
 
503
my_source_mgr;
 
504
 
 
505
typedef my_source_mgr *my_src_ptr;
 
506
 
 
507
#define INPUT_BUF_SIZE  4096    /* choose an efficiently fread'able size */
 
508
 
 
509
/*
 
510
 * Initialize source --- called by jpeg_read_header
 
511
 * before any data is actually read.
 
512
 */
 
513
 
 
514
void
 
515
init_source (j_decompress_ptr cinfo)
 
516
{
 
517
  my_src_ptr src = (my_src_ptr) cinfo->src;
 
518
 
 
519
  /* We reset the empty-input-file flag for each image,
 
520
   * but we don't clear the input buffer.
 
521
   * This is correct behavior for reading a series of images from one source.
 
522
   */
 
523
  src->start_of_file = TRUE;
 
524
}
 
525
 
 
526
 
 
527
/*
 
528
 * Fill the input buffer --- called whenever buffer is emptied.
 
529
 *
 
530
 * In typical applications, this should read fresh data into the buffer
 
531
 * (ignoring the current state of next_input_byte & bytes_in_buffer),
 
532
 * reset the pointer & count to the start of the buffer, and return TRUE
 
533
 * indicating that the buffer has been reloaded.  It is not necessary to
 
534
 * fill the buffer entirely, only to obtain at least one more byte.
 
535
 *
 
536
 * There is no such thing as an EOF return.  If the end of the file has been
 
537
 * reached, the routine has a choice of ERREXIT() or inserting fake data into
 
538
 * the buffer.  In most cases, generating a warning message and inserting a
 
539
 * fake EOI marker is the best course of action --- this will allow the
 
540
 * decompressor to output however much of the image is there.  However,
 
541
 * the resulting error message is misleading if the real problem is an empty
 
542
 * input file, so we handle that case specially.
 
543
 *
 
544
 * In applications that need to be able to suspend compression due to input
 
545
 * not being available yet, a FALSE return indicates that no more data can be
 
546
 * obtained right now, but more may be forthcoming later.  In this situation,
 
547
 * the decompressor will return to its caller (with an indication of the
 
548
 * number of scanlines it has read, if any).  The application should resume
 
549
 * decompression after it has loaded more data into the input buffer.  Note
 
550
 * that there are substantial restrictions on the use of suspension --- see
 
551
 * the documentation.
 
552
 *
 
553
 * When suspending, the decompressor will back up to a convenient restart point
 
554
 * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
 
555
 * indicate where the restart point will be if the current call returns FALSE.
 
556
 * Data beyond this point must be rescanned after resumption, so move it to
 
557
 * the front of the buffer rather than discarding it.
 
558
 */
 
559
 
 
560
#define END_JPEG_SEQUENCE "\r\n[*]--:END JPEG:--[*]\r\n"
 
561
 
 
562
safeboolean
 
563
fill_input_buffer (j_decompress_ptr cinfo)
 
564
{
 
565
  my_src_ptr src = (my_src_ptr) cinfo->src;
 
566
  size_t nbytes = 0;
 
567
  
 
568
  /* size_t got; */
 
569
  /* char *s; */
 
570
    memset (src->buffer, 0, INPUT_BUF_SIZE);
 
571
  
 
572
    while (nbytes < INPUT_BUF_SIZE)
 
573
    {
 
574
      
 
575
        int got = gdGetBuf (src->buffer + nbytes, 
 
576
                            INPUT_BUF_SIZE - nbytes,
 
577
                            src->infile);
 
578
      
 
579
        if ((got == EOF) || (got == 0))
 
580
        {
 
581
          
 
582
          /* EOF or error. If we got any data, don't worry about it.
 
583
             If we didn't, then this is unexpected. */ 
 
584
            if (!nbytes)
 
585
            {
 
586
              
 
587
                nbytes = -1;
 
588
              
 
589
            }
 
590
          
 
591
            break;
 
592
          
 
593
        }
 
594
      
 
595
        nbytes += got;
 
596
      
 
597
    }
 
598
  
 
599
    if (nbytes <= 0)
 
600
    {
 
601
      if (src->start_of_file)   /* Treat empty input file as fatal error */
 
602
        ERREXIT (cinfo, JERR_INPUT_EMPTY);
 
603
      WARNMS (cinfo, JWRN_JPEG_EOF);
 
604
      /* Insert a fake EOI marker */
 
605
      src->buffer[0] = (unsigned char) 0xFF;
 
606
      src->buffer[1] = (unsigned char) JPEG_EOI;
 
607
      nbytes = 2;
 
608
    }
 
609
 
 
610
  src->pub.next_input_byte = src->buffer;
 
611
  src->pub.bytes_in_buffer = nbytes;
 
612
  src->start_of_file = FALSE;
 
613
 
 
614
  return TRUE;
 
615
}
 
616
 
 
617
 
 
618
/*
 
619
 * Skip data --- used to skip over a potentially large amount of
 
620
 * uninteresting data (such as an APPn marker).
 
621
 *
 
622
 * Writers of suspendable-input applications must note that skip_input_data
 
623
 * is not granted the right to give a suspension return.  If the skip extends
 
624
 * beyond the data currently in the buffer, the buffer can be marked empty so
 
625
 * that the next read will cause a fill_input_buffer call that can suspend.
 
626
 * Arranging for additional bytes to be discarded before reloading the input
 
627
 * buffer is the application writer's problem.
 
628
 */
 
629
 
 
630
void
 
631
skip_input_data (j_decompress_ptr cinfo, long num_bytes)
 
632
{
 
633
  my_src_ptr src = (my_src_ptr) cinfo->src;
 
634
 
 
635
  /* Just a dumb implementation for now. Not clear that being smart is worth
 
636
   * any trouble anyway --- large skips are infrequent.
 
637
   */
 
638
  if (num_bytes > 0)
 
639
    {
 
640
      while (num_bytes > (long) src->pub.bytes_in_buffer)
 
641
        {
 
642
          num_bytes -= (long) src->pub.bytes_in_buffer;
 
643
          (void) fill_input_buffer (cinfo);
 
644
          /* note we assume that fill_input_buffer will never return FALSE,
 
645
           * so suspension need not be handled.
 
646
           */
 
647
        }
 
648
      src->pub.next_input_byte += (size_t) num_bytes;
 
649
      src->pub.bytes_in_buffer -= (size_t) num_bytes;
 
650
    }
 
651
}
 
652
 
 
653
 
 
654
/*
 
655
 * An additional method that can be provided by data source modules is the
 
656
 * resync_to_restart method for error recovery in the presence of RST markers.
 
657
 * For the moment, this source module just uses the default resync method
 
658
 * provided by the JPEG library.  That method assumes that no backtracking
 
659
 * is possible.
 
660
 */
 
661
 
 
662
 
 
663
/*
 
664
 * Terminate source --- called by jpeg_finish_decompress
 
665
 * after all data has been read.  Often a no-op.
 
666
 *
 
667
 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
 
668
 * application must deal with any cleanup that should happen even
 
669
 * for error exit.
 
670
 */
 
671
 
 
672
void
 
673
term_source (j_decompress_ptr cinfo)
 
674
{
 
675
  
 
676
#if 0
 
677
/* never used */
 
678
    my_src_ptr src = (my_src_ptr) cinfo->src;
 
679
  
 
680
#endif
 
681
}
 
682
 
 
683
 
 
684
/*
 
685
 * Prepare for input from a gdIOCtx stream.
 
686
 * The caller must have already opened the stream, and is responsible
 
687
 * for closing it after finishing decompression.
 
688
 */
 
689
 
 
690
void
 
691
jpeg_gdIOCtx_src (j_decompress_ptr cinfo,
 
692
                  gdIOCtx * infile)
 
693
{
 
694
  my_src_ptr src;
 
695
 
 
696
  /* The source object and input buffer are made permanent so that a series
 
697
   * of JPEG images can be read from the same file by calling jpeg_gdIOCtx_src
 
698
   * only before the first one.  (If we discarded the buffer at the end of
 
699
   * one image, we'd likely lose the start of the next one.)
 
700
   * This makes it unsafe to use this manager and a different source
 
701
   * manager serially with the same JPEG object.  Caveat programmer.
 
702
   */
 
703
  if (cinfo->src == NULL)
 
704
    {                           /* first time for this JPEG object? */
 
705
      cinfo->src = (struct jpeg_source_mgr *)
 
706
        (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
 
707
                                    sizeof (my_source_mgr));
 
708
      src = (my_src_ptr) cinfo->src;
 
709
      src->buffer = (unsigned char *)
 
710
        (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
 
711
                                    INPUT_BUF_SIZE * sizeof (unsigned char));
 
712
      
 
713
    }
 
714
 
 
715
  src = (my_src_ptr) cinfo->src;
 
716
  src->pub.init_source = init_source;
 
717
  src->pub.fill_input_buffer = fill_input_buffer;
 
718
  src->pub.skip_input_data = skip_input_data;
 
719
  src->pub.resync_to_restart = jpeg_resync_to_restart;  /* use default method */
 
720
  src->pub.term_source = term_source;
 
721
  src->infile = infile;
 
722
  src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
 
723
  src->pub.next_input_byte = NULL;      /* until buffer loaded */
 
724
}
 
725
 
 
726
/* Expanded data destination object for stdio output */
 
727
 
 
728
typedef struct
 
729
{
 
730
  struct jpeg_destination_mgr pub;      /* public fields */
 
731
  gdIOCtx *outfile;             /* target stream */
 
732
  unsigned char *buffer;        /* start of buffer */
 
733
}
 
734
my_destination_mgr;
 
735
 
 
736
typedef my_destination_mgr *my_dest_ptr;
 
737
 
 
738
#define OUTPUT_BUF_SIZE  4096   /* choose an efficiently fwrite'able size */
 
739
 
 
740
/*
 
741
 * Initialize destination --- called by jpeg_start_compress
 
742
 * before any data is actually written.
 
743
 */
 
744
 
 
745
void
 
746
init_destination (j_compress_ptr cinfo)
 
747
{
 
748
  my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
 
749
 
 
750
  /* Allocate the output buffer --- it will be released when done with image */
 
751
  dest->buffer = (unsigned char *)
 
752
    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
 
753
                                OUTPUT_BUF_SIZE * sizeof (unsigned char));
 
754
 
 
755
  dest->pub.next_output_byte = dest->buffer;
 
756
  dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
 
757
}
 
758
 
 
759
 
 
760
/*
 
761
 * Empty the output buffer --- called whenever buffer fills up.
 
762
 *
 
763
 * In typical applications, this should write the entire output buffer
 
764
 * (ignoring the current state of next_output_byte & free_in_buffer),
 
765
 * reset the pointer & count to the start of the buffer, and return TRUE
 
766
 * indicating that the buffer has been dumped.
 
767
 *
 
768
 * In applications that need to be able to suspend compression due to output
 
769
 * overrun, a FALSE return indicates that the buffer cannot be emptied now.
 
770
 * In this situation, the compressor will return to its caller (possibly with
 
771
 * an indication that it has not accepted all the supplied scanlines).  The
 
772
 * application should resume compression after it has made more room in the
 
773
 * output buffer.  Note that there are substantial restrictions on the use of
 
774
 * suspension --- see the documentation.
 
775
 *
 
776
 * When suspending, the compressor will back up to a convenient restart point
 
777
 * (typically the start of the current MCU). next_output_byte & free_in_buffer
 
778
 * indicate where the restart point will be if the current call returns FALSE.
 
779
 * Data beyond this point will be regenerated after resumption, so do not
 
780
 * write it out when emptying the buffer externally.
 
781
 */
 
782
 
 
783
safeboolean
 
784
empty_output_buffer (j_compress_ptr cinfo)
 
785
{
 
786
  my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
 
787
 
 
788
  if (gdPutBuf (dest->buffer, OUTPUT_BUF_SIZE, dest->outfile) !=
 
789
      (size_t) OUTPUT_BUF_SIZE)
 
790
    ERREXIT (cinfo, JERR_FILE_WRITE);
 
791
 
 
792
  dest->pub.next_output_byte = dest->buffer;
 
793
  dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
 
794
 
 
795
  return TRUE;
 
796
}
 
797
 
 
798
 
 
799
/*
 
800
 * Terminate destination --- called by jpeg_finish_compress
 
801
 * after all data has been written.  Usually needs to flush buffer.
 
802
 *
 
803
 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
 
804
 * application must deal with any cleanup that should happen even
 
805
 * for error exit.
 
806
 */
 
807
 
 
808
void
 
809
term_destination (j_compress_ptr cinfo)
 
810
{
 
811
  my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
 
812
  size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
 
813
 
 
814
  /* Write any data remaining in the buffer */
 
815
  if (datacount > 0)
 
816
    {
 
817
      if (gdPutBuf (dest->buffer, datacount, dest->outfile) != datacount)
 
818
        ERREXIT (cinfo, JERR_FILE_WRITE);
 
819
    }
 
820
}
 
821
 
 
822
 
 
823
/*
 
824
 * Prepare for output to a stdio stream.
 
825
 * The caller must have already opened the stream, and is responsible
 
826
 * for closing it after finishing compression.
 
827
 */
 
828
 
 
829
void
 
830
jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile)
 
831
{
 
832
  my_dest_ptr dest;
 
833
 
 
834
  /* The destination object is made permanent so that multiple JPEG images
 
835
   * can be written to the same file without re-executing jpeg_stdio_dest.
 
836
   * This makes it dangerous to use this manager and a different destination
 
837
   * manager serially with the same JPEG object, because their private object
 
838
   * sizes may be different.  Caveat programmer.
 
839
   */
 
840
  if (cinfo->dest == NULL)
 
841
    {                           /* first time for this JPEG object? */
 
842
      cinfo->dest = (struct jpeg_destination_mgr *)
 
843
        (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
 
844
                                    sizeof (my_destination_mgr));
 
845
    }
 
846
 
 
847
  dest = (my_dest_ptr) cinfo->dest;
 
848
  dest->pub.init_destination = init_destination;
 
849
  dest->pub.empty_output_buffer = empty_output_buffer;
 
850
  dest->pub.term_destination = term_destination;
 
851
  dest->outfile = outfile;
 
852
}
 
853
 
 
854
#endif /* HAVE_JPEG */