Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. #include "fitz.h"
  2.  
  3. #define OPJ_STATIC
  4. #include <openjpeg.h>
  5.  
  6. static void fz_opj_error_callback(const char *msg, void *client_data)
  7. {
  8.         fprintf(stderr, "openjpeg error: %s", msg);
  9. }
  10.  
  11. static void fz_opj_warning_callback(const char *msg, void *client_data)
  12. {
  13.         fprintf(stderr, "openjpeg warning: %s", msg);
  14. }
  15.  
  16. static void fz_opj_info_callback(const char *msg, void *client_data)
  17. {
  18.         /* fprintf(stderr, "openjpeg info: %s", msg); */
  19. }
  20.  
  21. fz_error
  22. fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size, fz_colorspace *defcs)
  23. {
  24.         fz_pixmap *img;
  25.         opj_event_mgr_t evtmgr;
  26.         opj_dparameters_t params;
  27.         opj_dinfo_t *info;
  28.         opj_cio_t *cio;
  29.         opj_image_t *jpx;
  30.         fz_colorspace *colorspace;
  31.         unsigned char *p;
  32.         int format;
  33.         int a, n, w, h, depth, sgnd;
  34.         int x, y, k, v;
  35.  
  36.         if (size < 2)
  37.                 return fz_throw("not enough data to determine image format");
  38.  
  39.         /* Check for SOC marker -- if found we have a bare J2K stream */
  40.         if (data[0] == 0xFF && data[1] == 0x4F)
  41.                 format = CODEC_J2K;
  42.         else
  43.                 format = CODEC_JP2;
  44.  
  45.         memset(&evtmgr, 0, sizeof(evtmgr));
  46.         evtmgr.error_handler = fz_opj_error_callback;
  47.         evtmgr.warning_handler = fz_opj_warning_callback;
  48.         evtmgr.info_handler = fz_opj_info_callback;
  49.  
  50.         opj_set_default_decoder_parameters(&params);
  51.  
  52.         info = opj_create_decompress(format);
  53.         opj_set_event_mgr((opj_common_ptr)info, &evtmgr, stderr);
  54.         opj_setup_decoder(info, &params);
  55.  
  56.         cio = opj_cio_open((opj_common_ptr)info, data, size);
  57.  
  58.         jpx = opj_decode(info, cio);
  59.  
  60.         opj_cio_close(cio);
  61.         opj_destroy_decompress(info);
  62.  
  63.         if (!jpx)
  64.                 return fz_throw("opj_decode failed");
  65.  
  66.         for (k = 1; k < jpx->numcomps; k++)
  67.         {
  68.                 if (jpx->comps[k].w != jpx->comps[0].w)
  69.                         return fz_throw("image components have different width");
  70.                 if (jpx->comps[k].h != jpx->comps[0].h)
  71.                         return fz_throw("image components have different height");
  72.                 if (jpx->comps[k].prec != jpx->comps[0].prec)
  73.                         return fz_throw("image components have different precision");
  74.         }
  75.  
  76.         n = jpx->numcomps;
  77.         w = jpx->comps[0].w;
  78.         h = jpx->comps[0].h;
  79.         depth = jpx->comps[0].prec;
  80.         sgnd = jpx->comps[0].sgnd;
  81.  
  82.         if (jpx->color_space == CLRSPC_SRGB && n == 4) { n = 3; a = 1; }
  83.         else if (jpx->color_space == CLRSPC_SYCC && n == 4) { n = 3; a = 1; }
  84.         else if (n == 2) { n = 1; a = 1; }
  85.         else if (n > 4) { n = 4; a = 1; }
  86.         else { a = 0; }
  87.  
  88.         if (defcs)
  89.         {
  90.                 if (defcs->n == n)
  91.                 {
  92.                         colorspace = defcs;
  93.                 }
  94.                 else
  95.                 {
  96.                         fz_warn("jpx file and dict colorspaces do not match");
  97.                         defcs = NULL;
  98.                 }
  99.         }
  100.  
  101.         if (!defcs)
  102.         {
  103.                 switch (n)
  104.                 {
  105.                 case 1: colorspace = fz_device_gray; break;
  106.                 case 3: colorspace = fz_device_rgb; break;
  107.                 case 4: colorspace = fz_device_cmyk; break;
  108.                 }
  109.         }
  110.  
  111.         img = fz_new_pixmap_with_limit(colorspace, w, h);
  112.         if (!img)
  113.         {
  114.                 opj_image_destroy(jpx);
  115.                 return fz_throw("out of memory");
  116.         }
  117.  
  118.         p = img->samples;
  119.         for (y = 0; y < h; y++)
  120.         {
  121.                 for (x = 0; x < w; x++)
  122.                 {
  123.                         for (k = 0; k < n + a; k++)
  124.                         {
  125.                                 v = jpx->comps[k].data[y * w + x];
  126.                                 if (sgnd)
  127.                                         v = v + (1 << (depth - 1));
  128.                                 if (depth > 8)
  129.                                         v = v >> (depth - 8);
  130.                                 *p++ = v;
  131.                         }
  132.                         if (!a)
  133.                                 *p++ = 255;
  134.                 }
  135.         }
  136.  
  137.         if (a)
  138.         {
  139.                 if (n == 4)
  140.                 {
  141.                         fz_pixmap *tmp = fz_new_pixmap(fz_device_rgb, w, h);
  142.                         fz_convert_pixmap(img, tmp);
  143.                         fz_drop_pixmap(img);
  144.                         img = tmp;
  145.                 }
  146.                 fz_premultiply_pixmap(img);
  147.         }
  148.  
  149.         opj_image_destroy(jpx);
  150.  
  151.         *imgp = img;
  152.         return fz_okay;
  153. }
  154.