Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. #include "fitz.h"
  2. #include "muxps.h"
  3.  
  4. #include <jpeglib.h>
  5. #include <setjmp.h>
  6.  
  7. struct jpeg_error_mgr_jmp
  8. {
  9.         struct jpeg_error_mgr super;
  10.         jmp_buf env;
  11.         char msg[JMSG_LENGTH_MAX];
  12. };
  13.  
  14. static void error_exit(j_common_ptr cinfo)
  15. {
  16.         struct jpeg_error_mgr_jmp *err = (struct jpeg_error_mgr_jmp *)cinfo->err;
  17.         cinfo->err->format_message(cinfo, err->msg);
  18.         longjmp(err->env, 1);
  19. }
  20.  
  21. static void init_source(j_decompress_ptr cinfo)
  22. {
  23.         /* nothing to do */
  24. }
  25.  
  26. static void term_source(j_decompress_ptr cinfo)
  27. {
  28.         /* nothing to do */
  29. }
  30.  
  31. static boolean fill_input_buffer(j_decompress_ptr cinfo)
  32. {
  33.         static unsigned char eoi[2] = { 0xFF, JPEG_EOI };
  34.         struct jpeg_source_mgr *src = cinfo->src;
  35.         src->next_input_byte = eoi;
  36.         src->bytes_in_buffer = 2;
  37.         return 1;
  38. }
  39.  
  40. static void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
  41. {
  42.         struct jpeg_source_mgr *src = cinfo->src;
  43.         if (num_bytes > 0)
  44.         {
  45.                 src->next_input_byte += num_bytes;
  46.                 src->bytes_in_buffer -= num_bytes;
  47.         }
  48. }
  49.  
  50. int
  51. xps_decode_jpeg(fz_pixmap **imagep, byte *rbuf, int rlen)
  52. {
  53.         struct jpeg_decompress_struct cinfo;
  54.         struct jpeg_error_mgr_jmp err;
  55.         struct jpeg_source_mgr src;
  56.         unsigned char *row[1], *sp, *dp;
  57.         fz_colorspace *colorspace;
  58.         unsigned int x;
  59.         int k;
  60.  
  61.         fz_pixmap *image = NULL;
  62.  
  63.         if (setjmp(err.env))
  64.         {
  65.                 if (image)
  66.                         fz_drop_pixmap(image);
  67.                 return fz_throw("jpeg error: %s", err.msg);
  68.         }
  69.  
  70.         cinfo.err = jpeg_std_error(&err.super);
  71.         err.super.error_exit = error_exit;
  72.  
  73.         jpeg_create_decompress(&cinfo);
  74.  
  75.         cinfo.src = &src;
  76.         src.init_source = init_source;
  77.         src.fill_input_buffer = fill_input_buffer;
  78.         src.skip_input_data = skip_input_data;
  79.         src.resync_to_restart = jpeg_resync_to_restart;
  80.         src.term_source = term_source;
  81.         src.next_input_byte = rbuf;
  82.         src.bytes_in_buffer = rlen;
  83.  
  84.         jpeg_read_header(&cinfo, 1);
  85.  
  86.         jpeg_start_decompress(&cinfo);
  87.  
  88.         if (cinfo.output_components == 1)
  89.                 colorspace = fz_device_gray;
  90.         else if (cinfo.output_components == 3)
  91.                 colorspace = fz_device_rgb;
  92.         else if (cinfo.output_components == 4)
  93.                 colorspace = fz_device_cmyk;
  94.         else
  95.                 return fz_throw("bad number of components in jpeg: %d", cinfo.output_components);
  96.  
  97.         image = fz_new_pixmap_with_limit(colorspace, cinfo.output_width, cinfo.output_height);
  98.         if (!image)
  99.         {
  100.                 jpeg_finish_decompress(&cinfo);
  101.                 jpeg_destroy_decompress(&cinfo);
  102.                 return fz_throw("out of memory");
  103.         }
  104.  
  105.         if (cinfo.density_unit == 1)
  106.         {
  107.                 image->xres = cinfo.X_density;
  108.                 image->yres = cinfo.Y_density;
  109.         }
  110.         else if (cinfo.density_unit == 2)
  111.         {
  112.                 image->xres = cinfo.X_density * 254 / 100;
  113.                 image->yres = cinfo.Y_density * 254 / 100;
  114.         }
  115.  
  116.         fz_clear_pixmap(image);
  117.  
  118.         row[0] = fz_malloc(cinfo.output_components * cinfo.output_width);
  119.         dp = image->samples;
  120.         while (cinfo.output_scanline < cinfo.output_height)
  121.         {
  122.                 jpeg_read_scanlines(&cinfo, row, 1);
  123.                 sp = row[0];
  124.                 for (x = 0; x < cinfo.output_width; x++)
  125.                 {
  126.                         for (k = 0; k < cinfo.output_components; k++)
  127.                                 *dp++ = *sp++;
  128.                         *dp++ = 255;
  129.                 }
  130.         }
  131.         fz_free(row[0]);
  132.  
  133.         jpeg_finish_decompress(&cinfo);
  134.         jpeg_destroy_decompress(&cinfo);
  135.  
  136.         *imagep = image;
  137.         return fz_okay;
  138. }
  139.