chiark / gitweb /
Fix compilation for Gtk with the new, stricter inheritance
[clg] / cairo / alien / cairo-jpeg.c
1 /* Modified for clg by esj */
2
3 /* Copyright 2005 Google Inc. All Rights Reserved.
4  * Author: yangzh@google.com (Zhonghao Yang)
5  *
6  * Google's own patch to add jpeg I/O support for cairo.
7  *
8  */
9
10 /* cairo - a vector graphics library with display and print output
11  *
12  * Copyright © 2003 University of Southern California
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it either under the terms of the GNU Lesser General Public
16  * License version 2.1 as published by the Free Software Foundation
17  * (the "LGPL") or, at your option, under the terms of the Mozilla
18  * Public License Version 1.1 (the "MPL"). If you do not alter this
19  * notice, a recipient may use your version of this file under either
20  * the MPL or the LGPL.
21  *
22  * You should have received a copy of the LGPL along with this library
23  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25  * You should have received a copy of the MPL along with this library
26  * in the file COPYING-MPL-1.1
27  *
28  * The contents of this file are subject to the Mozilla Public License
29  * Version 1.1 (the "License"); you may not use this file except in
30  * compliance with the License. You may obtain a copy of the License at
31  * http://www.mozilla.org/MPL/
32  *
33  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
34  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
35  * the specific language governing rights and limitations.
36  *
37  * The Original Code is the cairo graphics library.
38  *
39  * The Initial Developer of the Original Code is University of Southern
40  * California.
41  *
42  * Contributor(s):
43  *      Carl D. Worth <cworth@cworth.org>
44  *      Kristian Høgsberg <krh@redhat.com>
45  */
46
47 #include <stdio.h>
48 #include <stdint.h>
49 #include <string.h>
50 #include <stdlib.h>
51 #include <setjmp.h>
52 #include <errno.h>
53 #include <jpeglib.h>
54 #include <cairo.h>
55 #include "cairo-lut-private.h"
56 #include "cairo-prebuilt-lut.h"
57
58 #define BUF_SIZE_JPEG 4096
59
60 struct clg_error_mgr {
61   struct jpeg_error_mgr pub;
62   jmp_buf setjmp_buffer;
63 };
64         
65 typedef struct clg_error_mgr *error_ptr;
66         
67 static void
68 _error_exit (j_common_ptr cinfo)
69 {
70   error_ptr err = (error_ptr) cinfo->err;
71         
72   (*cinfo->err->output_message) (cinfo);
73   longjmp(err->setjmp_buffer, 1);
74 }
75
76
77 typedef unsigned int (*cairo_jpeg_read_func_t)
78                       (void *closure,
79                        unsigned char *data,
80                        unsigned int  length);
81
82 struct read_closure {
83   /**
84    * Model underlying system's read behavior:
85    * data can be read from stdio, stream, or anything.
86    */
87   cairo_jpeg_read_func_t jpeg_func;
88
89   /**
90    * Auxiliary data:
91    * For stdio, this should be struct file_closure *
92    */
93   void *user_data;
94   /*
95    * Buffer for reading from
96    */
97   unsigned char block[BUF_SIZE_JPEG];
98
99   cairo_status_t status;
100 };
101
102 /*
103  * Read function for stdio.
104  * Check length of read and return error if necessary.
105  */
106 static
107 unsigned int stdio_read_func (void *closure,
108                               unsigned char *data,
109                               unsigned int length)
110 {
111   return fread((void *)data, 1, length, (FILE *)closure);
112 }
113
114 /*
115  * Initialize source.
116  * called by jpeg_read_header before any data is actually read.
117  */
118 static void init_source_custom (j_decompress_ptr cinfo)
119 {
120   cinfo->src->bytes_in_buffer = 0;
121 }
122
123 /*
124  * Fill the input buffer.
125  * called whenever buffer is emptied.
126  */
127 static boolean fill_input_buffer_custom (j_decompress_ptr cinfo)
128 {
129   struct read_closure *closure = (struct read_closure*) (cinfo->client_data);
130   unsigned int len;
131
132   len = (*closure->jpeg_func) (closure->user_data,
133                                closure->block, BUF_SIZE_JPEG);
134
135   if (len == 0) {
136     /* really hit EOF in the beginning: insert a fake EOI marker. */
137     static const unsigned char jpeg_eof[] = { 0xFF, JPEG_EOI };
138     cinfo->src->bytes_in_buffer = 2;
139     cinfo->src->next_input_byte = jpeg_eof;
140   } else {
141       cinfo->src->bytes_in_buffer = len;
142       cinfo->src->next_input_byte = closure->block;
143   }
144   return TRUE;
145 }
146
147
148 /*
149  * Skip data.
150  * used to skip over a potentially large amount of uninteresting
151  * data (such as APPn marker).
152  * Writers of suspendable-input applications must note that skip_input_data
153  * is not granted the right to give a suspension return.  If the skip extends
154  * beyond the data currently in the buffer, the buffer can be marked empty so
155  * that the next read will cause a fill_input_buffer call that can suspend.
156  * Arranging for additional bytes to be discarded before reloading the input
157  * buffer is the application writer's problem.
158  */
159 static void skip_input_data_custom (j_decompress_ptr cinfo, long num_bytes)
160 {
161   while (num_bytes > (long) (cinfo->src->bytes_in_buffer)) {
162     num_bytes -= (long) (cinfo->src->bytes_in_buffer);
163     fill_input_buffer_custom (cinfo);
164   }
165
166   cinfo->src->next_input_byte += (size_t) num_bytes;
167   cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
168 }
169
170 /*
171  * Terminate source.
172  * called by jpeg_finish_decompress after all data has been read.
173  * Often a no-op.
174  */
175 static void term_source_custom (j_decompress_ptr cinfo)
176 {
177 }
178
179 /*
180  * read jpeg from any source.
181  */
182 static cairo_surface_t *
183 read_jpeg (struct read_closure *closure)
184 {
185   cairo_surface_t *surface = NULL;
186
187   struct jpeg_decompress_struct cinfo;
188   struct clg_error_mgr jerr;
189   struct jpeg_source_mgr src;
190
191   int channels;
192   uint8_t *data;
193   int stride;
194   
195   JSAMPROW row = NULL;
196   JSAMPROW rowptr[1];
197
198   register JSAMPROW src_pixel;
199   register uint32_t *dst_pixel;
200   unsigned int i, j;
201
202   closure->status = CAIRO_STATUS_SUCCESS;
203   
204   /* Step 1: Allocate and initialize a JPEG decompression object */
205   /* Step 2: Specify the source of the compressed data (eg, a file) */
206   memset (&cinfo, 0, sizeof (cinfo));
207   memset (&jerr, 0, sizeof (jerr));
208
209   cinfo.err = jpeg_std_error (&jerr.pub);
210   jerr.pub.error_exit = _error_exit;
211   if (setjmp(jerr.setjmp_buffer))
212     goto ERROR;
213
214   jpeg_create_decompress (&cinfo);
215
216   cinfo.client_data = closure;
217
218   src.init_source = init_source_custom;
219   src.fill_input_buffer = fill_input_buffer_custom;
220   src.skip_input_data = skip_input_data_custom;
221   src.resync_to_restart = jpeg_resync_to_restart;  /* JPEG library default */
222   src.term_source = term_source_custom;
223   src.bytes_in_buffer = 0;  /* forces fill_input_buffer on first read. */
224   src.next_input_byte = NULL;   /* until buffer loaded. */
225   cinfo.src = &src;
226
227   /* save the APP14 marker to check for Adobe Photoshop CMYK */
228   /* files with inverted components. */
229   jpeg_save_markers (&cinfo, JPEG_APP0 + 14, 256);
230
231   /* Step 3: Call jpeg_read_header() to obtain image info. */
232   if (jpeg_read_header (&cinfo, TRUE) != JPEG_HEADER_OK)
233     goto ERROR;
234
235   /* if (cinfo.image_height > INT_MAX || cinfo.image_width > INT_MAX) */
236   /*   goto BAIL1; */
237
238   /* NOTE(yangzh): do not support these two yet. */
239   if (cinfo.jpeg_color_space == JCS_CMYK || cinfo.jpeg_color_space == JCS_YCCK)
240     goto ERROR;
241     
242   cinfo.out_color_space = JCS_RGB;
243
244   /* the fastest, but less accurate integer method for DCT. */
245   /* not recommende if high quality is a concern. we do not have this issue. */
246   cinfo.dct_method = JDCT_IFAST;
247
248   /* Step 4: Set target cairo image.
249    * for CAIRO_FORMAT_ARGB32, every pixel will take 4 bytes.
250    */
251   surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
252                                         cinfo.image_width,
253                                         cinfo.image_height);
254   if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) {
255     closure->status = cairo_surface_status (surface);
256     goto ERROR;
257   }
258
259   /* Step 5: jpeg_start_decompress(...); */
260   jpeg_start_decompress (&cinfo);
261
262   /* Step 6: while (scan lines remain to be read) */
263   /*           jpeg_read_scanlines(...); */
264   channels = 3;
265   row = (JSAMPROW) malloc (cinfo.output_width * channels * sizeof (JSAMPLE));
266   if (row == NULL) {
267     closure->status = CAIRO_STATUS_NO_MEMORY;
268     goto ERROR;
269   }
270
271   data = cairo_image_surface_get_data (surface);
272   stride = cairo_image_surface_get_stride (surface);
273   
274   rowptr[0] = row;
275   for (i = 0; i < cinfo.output_height; i++) {
276     jpeg_read_scanlines (&cinfo, rowptr, 1);
277     src_pixel = row;
278     dst_pixel = (uint32_t*)(data + i * stride);
279     for (j = 0; j < cinfo.output_width; j++, src_pixel += channels, dst_pixel++) {
280       /* Store ARGB in native endian. */
281       *dst_pixel = (0xFF << 24)   /* always 0xFF in alpha channel. */
282                    + (src_pixel[0] << 16)
283                    + (src_pixel[1] << 8)
284                    + (src_pixel[2]);
285     }
286   }
287
288   /* Step 7: jpeg_finish_decompress(...); */
289   jpeg_finish_decompress (&cinfo);
290   goto EXIT;
291   
292  ERROR:
293   if (surface) {
294     cairo_surface_destroy (surface);
295     surface = NULL;
296   }
297   if (closure->status == CAIRO_STATUS_SUCCESS)
298     closure->status = CAIRO_STATUS_READ_ERROR;
299
300  EXIT:
301   /* Release other buffers used in this function. */
302   if (row)
303     free (row);
304
305   /* Step 8: Release the JPEG decompression object. */
306   jpeg_destroy_decompress (&cinfo);
307
308   return surface;
309 }
310
311 cairo_surface_t *
312 cairo_image_surface_create_from_jpeg (const char *filename,
313                                       cairo_status_t *status)
314 {
315   struct read_closure jpeg_closure;
316   FILE *fp;
317   cairo_surface_t *surface;
318
319   fp = fopen (filename, "rb");
320   if (fp == NULL) {
321     switch (errno) {
322       case ENOMEM:
323         *status = CAIRO_STATUS_NO_MEMORY;
324         return NULL;
325       case ENOENT:
326         *status = CAIRO_STATUS_FILE_NOT_FOUND;
327         return NULL;
328       default:
329         *status = CAIRO_STATUS_READ_ERROR;
330         return NULL;
331     }
332   }
333
334   jpeg_closure.jpeg_func = stdio_read_func;
335   jpeg_closure.user_data = (void*) fp;
336   
337   surface = read_jpeg (&jpeg_closure);
338   fclose (fp);
339
340   *status = jpeg_closure.status;
341   return surface;
342 }
343
344 cairo_surface_t *
345 cairo_image_surface_create_from_jpeg_stream (cairo_jpeg_read_func_t read_func,
346                                              void *closure,
347                                              cairo_status_t *status)
348 {
349   struct read_closure jpeg_closure;
350   jpeg_closure.jpeg_func = read_func;
351   jpeg_closure.user_data = closure;
352
353   cairo_surface_t *surface = read_jpeg (&jpeg_closure);
354
355   *status = jpeg_closure.status;
356   return surface;
357 }
358
359
360 typedef struct _cairo_jpeg_parameter {
361   int quality;
362   cairo_bool_t interlace;
363 } cairo_jpeg_parameter_t;
364
365 void cairo_get_default_jpeg_parameter (cairo_jpeg_parameter_t *param);
366
367 typedef unsigned int (*cairo_jpeg_write_func_t)
368                       (void *closure,
369                        const unsigned char *data,
370                        unsigned int length);
371
372 struct write_closure {
373   cairo_jpeg_write_func_t jpeg_func;
374
375   /**
376    * Auxiliary data:
377    * For stdio, this should be struct file_closure *
378    */
379   void *user_data;
380   /*
381    * Buffer for writing to.
382    */
383   unsigned char block[BUF_SIZE_JPEG];
384 };
385
386 /*
387  * write func for stdio.
388  * since closure_data->byte_written contains enough diagnostic information,
389  * we always return SUCCESS here.
390  */
391 static
392 cairo_status_t stdio_write_func (void *closure,
393                                  const unsigned char *data,
394                                  unsigned int length)
395 {
396   int bytes_written;
397   do {
398     bytes_written = fwrite(data, 1, length, (FILE *)closure);
399     data += bytes_written;
400     length -= bytes_written;
401   } while (bytes_written > 0 && length > 0);
402   
403   return CAIRO_STATUS_SUCCESS;  
404 }
405
406 /*
407  * Initialize destination.
408  * called by jpeg_start_compress before any data is actually written.
409  */
410 static void init_destination_jpeg_custom (j_compress_ptr cinfo)
411 {
412   struct write_closure *closure = (struct write_closure*) (cinfo->client_data);
413   cinfo->dest->next_output_byte = closure->block;
414   cinfo->dest->free_in_buffer = BUF_SIZE_JPEG;
415 }
416
417 /*
418  * Empty buffer.
419  * called whenever buffer fills up.
420  * In typical applications, this should write the entire output buffer
421  * (ignoring the current state of next_output_byte & free_in_buffer),
422  * reset the pointer & count to the start of the buffer, and return TRUE
423  * indicating that the buffer has been dumped.
424  *
425  * In applications that need to be able to suspend compression due to output
426  * overrun, a FALSE return indicates that the buffer cannot be emptied now.
427  * In this situation, the compressor will return to its caller (possibly with
428  * an indication that it has not accepted all the supplied scanlines).  The
429  * application should resume compression after it has made more room in the
430  * output buffer.  Note that there are substantial restrictions on the use of
431  * suspension --- see the documentation.
432  *
433  * When suspending, the compressor will back up to a convenient restart point
434  * (typically the start of the current MCU). next_output_byte & free_in_buffer
435  * indicate where the restart point will be if the current call returns FALSE.
436  * Data beyond this point will be regenerated after resumption, so do not
437  * write it out when emptying the buffer externally.
438  */
439 static boolean empty_output_buffer_jpeg_custom (j_compress_ptr cinfo)
440 {
441   struct write_closure *closure = (struct write_closure*) (cinfo->client_data);
442   int len;
443   len = (*closure->jpeg_func) (closure->user_data,
444                                closure->block, BUF_SIZE_JPEG);
445   if (len != BUF_SIZE_JPEG) {
446     /* seems not all remaining bytes in buffer has been dumped yet. */
447     /* by return FALSE, we reply on JPEG's error handling machnism?  */
448     return FALSE;
449   }
450   cinfo->dest->next_output_byte = closure->block;
451   cinfo->dest->free_in_buffer = BUF_SIZE_JPEG;
452   return TRUE;
453 }
454
455 /*
456  * Terminate destination.
457  * called by jpeg_finish_compress afer all data has been written.
458  * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
459  * application must deal with any cleanup that should happen even
460  * for error exit.
461  */
462 static void term_destination_jpeg_custom (j_compress_ptr cinfo)
463 {
464   struct write_closure *closure = (struct write_closure*) (cinfo->client_data);
465   unsigned int len;
466   len = BUF_SIZE_JPEG - cinfo->dest->free_in_buffer;
467   if (len > 0)
468     (*closure->jpeg_func) (closure->user_data, closure->block, len);
469 }
470
471 static cairo_status_t
472 write_jpeg (cairo_surface_t *surface, void* closure,
473             const cairo_jpeg_parameter_t *parameter)
474 {
475   cairo_status_t status = CAIRO_STATUS_SUCCESS;
476
477   struct jpeg_compress_struct cinfo;
478   struct clg_error_mgr jerr;
479   struct jpeg_destination_mgr dest;
480   cairo_jpeg_parameter_t *param, default_parameters;
481
482   JSAMPROW row = NULL;
483   JSAMPROW rowptr[1];
484
485   register uint32_t *src_pixel;
486   register uint8_t *src_pixel_gray;
487   register JSAMPROW dst_pixel;
488   unsigned int i, j;
489   int convert_alpha;
490
491   param = (cairo_jpeg_parameter_t *)parameter;
492   if (param == NULL) {
493       param = &default_parameters;
494       cairo_get_default_jpeg_parameter(param);
495   }
496
497
498   /* Step 1:  Allocate and initialize a JPEG compression object. */
499   memset (&cinfo, 0, sizeof (cinfo));
500   memset (&jerr, 0, sizeof (jerr));
501
502   cinfo.err = jpeg_std_error (&jerr.pub);
503   jerr.pub.error_exit = _error_exit;
504   if (setjmp(jerr.setjmp_buffer))
505     goto BAIL;
506
507   jpeg_create_compress (&cinfo);
508
509   /* Step 2:  Specify the destination for the compressed data. */
510   cinfo.client_data = closure;
511
512   dest.init_destination = init_destination_jpeg_custom;
513   dest.empty_output_buffer = empty_output_buffer_jpeg_custom;
514   dest.term_destination = term_destination_jpeg_custom;
515   dest.next_output_byte = NULL;
516   dest.free_in_buffer = 0;
517   cinfo.dest = &dest;
518
519   /* Step 3: Set parameters for compression, image size & colorspace, etc. */
520   cinfo.image_width = cairo_image_surface_get_width (surface);
521   cinfo.image_height = cairo_image_surface_get_height (surface);
522   convert_alpha = 0;
523
524   switch (cairo_image_surface_get_format (surface)) {
525     case CAIRO_FORMAT_RGB24:
526       cinfo.input_components = 3;       /* # of color components per pixel */
527       cinfo.in_color_space = JCS_RGB;   /* colorspace of input image */
528       break;
529     case CAIRO_FORMAT_ARGB32:
530       cinfo.input_components = 3;       /* # of color components per pixel */
531       cinfo.in_color_space = JCS_RGB;   /* colorspace of input image */
532       convert_alpha = 1;
533       break;
534     case CAIRO_FORMAT_A8: /* Put A channel into a grayscale JPEG image. */
535     case CAIRO_FORMAT_A1: /* Put A channel into a "binary" JPEG image. */
536       cinfo.input_components = 1;
537       cinfo.in_color_space = JCS_GRAYSCALE;
538     default:
539       status = CAIRO_STATUS_NULL_POINTER;
540       goto BAIL;
541   }
542
543   jpeg_set_defaults (&cinfo);  /* set compression parameters all default values. */
544
545   /* the fastest, but less accurate integer method for DCT. */
546   /* not recommende if high quality is a concern. we do not have this issue. */
547   cinfo.dct_method = JDCT_IFAST;
548
549   if (param->quality >= 0)
550     jpeg_set_quality(&cinfo, param->quality, TRUE);
551
552   /* If user requests interlace, translate that to progressive JPEG */
553   if (param->interlace)
554     jpeg_simple_progression(&cinfo);
555
556   row = (JSAMPROW) malloc (cinfo.image_width * cinfo.input_components
557                            * sizeof (JSAMPLE));
558   if (row == NULL) {
559     status = CAIRO_STATUS_NO_MEMORY;
560     goto BAIL;
561   }
562
563   rowptr[0] = row;
564
565   /* Step 4:  jpeg_start_compress(...); */
566   jpeg_start_compress (&cinfo, TRUE);
567
568   /* Step 5:  while (scan lines remain to be written) */
569   /*            jpeg_write_scanlines(...); */
570   uint8_t *data = cairo_image_surface_get_data (surface);
571   int stride = cairo_image_surface_get_stride (surface);
572   
573   if (cinfo.input_components == 3) {  /* truecolor JPEG. */
574     for (i = 0; i < cinfo.image_height; i++) {
575       src_pixel = (uint32_t *) (data + i * stride);
576       dst_pixel = row;
577       /*
578        * If the pixels have an alpha channel, convert
579        * the pixels to normal RGB
580        */
581       if (convert_alpha) {
582         for (j = 0; j < cinfo.image_width; j++, dst_pixel += 3) {
583           uint8_t r, g, b;
584           cairo_to_rgb(*src_pixel++, &r, &g, &b);
585           dst_pixel[0] = r;
586           dst_pixel[1] = g;
587           dst_pixel[2] = b;
588         }
589       } else {
590         for (j = 0; j < cinfo.image_width; j++, dst_pixel += 3) {
591           unsigned int pix;
592           pix = *src_pixel++;
593           dst_pixel[0] = _get_red(pix);
594           dst_pixel[1] = _get_green(pix);
595           dst_pixel[2] = _get_blue(pix);
596         }
597       }
598       jpeg_write_scanlines (&cinfo, rowptr, 1);
599     }
600   } else {  /* write to a grayscale JPEG. */
601     src_pixel_gray = (uint8_t *) data;
602     for (i = 0; i < cinfo.image_height; i++) {
603       memcpy (row, src_pixel_gray, cinfo.image_width);
604       src_pixel_gray += stride;
605       jpeg_write_scanlines (&cinfo, rowptr, 1);
606     }
607   }
608
609   /* Step 6:  jpeg_finish_compress(...); */
610   jpeg_finish_compress (&cinfo);
611
612  BAIL:
613   if (row)
614     free (row);
615
616   /* Step 7:  Release the JPEG compression object. */
617   jpeg_destroy_compress (&cinfo);
618
619   return status;
620 }
621
622 void
623 cairo_get_default_jpeg_parameter (cairo_jpeg_parameter_t *param)
624 {
625   param->quality = 75;
626   param->interlace = TRUE;
627 }
628
629 cairo_status_t
630 cairo_surface_write_to_jpeg (cairo_surface_t *surface,
631                              const char *filename,
632                              const cairo_jpeg_parameter_t *parameter)
633 {
634   FILE *fp;
635   struct write_closure jpeg_closure;
636   cairo_status_t status;
637
638   fp = fopen (filename, "wb");
639   if (fp == NULL)
640     return CAIRO_STATUS_WRITE_ERROR;
641
642   jpeg_closure.jpeg_func = stdio_write_func;
643   jpeg_closure.user_data = fp;
644
645   status = write_jpeg (surface, &jpeg_closure, parameter);
646   if (fclose(fp) < 0)
647     status = CAIRO_STATUS_WRITE_ERROR;
648
649   return status;
650 }
651
652 cairo_status_t
653 cairo_surface_write_to_jpeg_stream (cairo_surface_t *surface,
654                                     cairo_jpeg_write_func_t write_func,
655                                     void *closure,
656                                     const cairo_jpeg_parameter_t *parameter)
657 {
658   struct write_closure jpeg_closure;
659   jpeg_closure.jpeg_func = write_func;
660   jpeg_closure.user_data = closure;
661
662   return write_jpeg (surface, &jpeg_closure, parameter);
663 }