int EMSCRIPTEN_KEEPALIVE jp2_decode()

in src/decoder.c [70:262]


int EMSCRIPTEN_KEEPALIVE jp2_decode(OPJ_UINT8 *data, OPJ_SIZE_T data_size,
                                    OPJ_UINT32 pdf_numcomps,
                                    OPJ_BOOL pdf_is_indexed_colormap,
                                    OPJ_BOOL pdf_smaks_in_data,
                                    OPJ_UINT32 pdf_reduce_factor) {
  opj_dparameters_t parameters;
  opj_codec_t *l_codec = NULL;
  opj_image_t *image = NULL;
  opj_stream_t *l_stream = NULL;

  OPJ_UINT32 *int32data = (OPJ_UINT32 *)data;
  if (int32data[0] == JP2_MAGIC || (int32data[0] == JP2_RFC3745_MAGIC_0 &&
                                    int32data[1] == JP2_RFC3745_MAGIC_1 &&
                                    int32data[2] == JP2_RFC3745_MAGIC_2)) {
    l_codec = opj_create_decompress(OPJ_CODEC_JP2);
  } else if (int32data[0] == J2K_CODESTREAM_MAGIC) {
    l_codec = opj_create_decompress(OPJ_CODEC_J2K);
  } else {
    storeErrorMessage("Unknown format");
    return 1;
  }

  opj_set_info_handler(l_codec, quiet_callback, 00);
  opj_set_warning_handler(l_codec, warning_callback, 00);
  opj_set_error_handler(l_codec, error_callback, 00);

  opj_set_default_decoder_parameters(&parameters);
  if (pdf_is_indexed_colormap) {
    parameters.flags |= OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG;
  }

  // set stream
  opj_buffer_info_t buffer_info;
  buffer_info.buf = data;
  buffer_info.cur = data;
  buffer_info.len = data_size;
  l_stream = opj_stream_create_buffer_stream(&buffer_info, OPJ_TRUE);

  /* Setup the decoder decoding parameters using user parameters */
  if (unlikely(!opj_setup_decoder(l_codec, &parameters))) {
    storeErrorMessage("Failed to setup the decoder");
    opj_stream_destroy(l_stream);
    opj_destroy_codec(l_codec);
    return 1;
  }

  /* Read the main header of the codestream and if necessary the JP2 boxes*/
  if (unlikely(!opj_read_header(l_stream, l_codec, &image))) {
    storeErrorMessage("Failed to read the header");
    opj_stream_destroy(l_stream);
    opj_destroy_codec(l_codec);
    opj_image_destroy(image);
    return 1;
  }

  if (pdf_reduce_factor && unlikely(!opj_set_decoded_resolution_factor(l_codec, pdf_reduce_factor))) {
    storeErrorMessage("Failed to setup the reduction factor");
    opj_stream_destroy(l_stream);
    opj_destroy_codec(l_codec);
    opj_image_destroy(image);
    return 1;
  }

#ifdef PDFJS_DEBUG
  printf("Arguments: numcomps: %d, is_indexed: %d, smask_in_data: %d, reduce_factor: %d %d\n",
         pdf_numcomps, pdf_is_indexed_colormap, pdf_smaks_in_data, pdf_reduce_factor, sizeof(OPJ_UINT32));
  printf("image X %d\n", image->x1);
  printf("image Y %d\n", image->y1);
  printf("image numcomps %d\n", image->numcomps);
#endif

  /* decode the image */
  if (unlikely(!opj_decode(l_codec, l_stream, image) ||
               !opj_end_decompress(l_codec, l_stream))) {
    storeErrorMessage("Failed to decode the image");
    opj_destroy_codec(l_codec);
    opj_stream_destroy(l_stream);
    opj_image_destroy(image);
    return 1;
  }

#ifdef PDFJS_DEBUG
  printf("image numcomps %d\n", image->numcomps);
  switch (image->color_space) {
  case OPJ_CLRSPC_UNKNOWN:
    printf("image colorspace unknown\n");
    break;
  case OPJ_CLRSPC_UNSPECIFIED:
    printf("image colorspace unspecified\n");
    break;
  case OPJ_CLRSPC_SRGB:
    printf("image colorspace sRGB\n");
    break;
  case OPJ_CLRSPC_GRAY:
    printf("image colorspace gray\n");
    break;
  case OPJ_CLRSPC_SYCC:
    printf("image colorspace sycc\n");
    break;
  case OPJ_CLRSPC_EYCC:
    printf("image colorspace eycc\n");
    break;
  case OPJ_CLRSPC_CMYK:
    printf("image colorspace cmyk\n");
    break;
  }
  printf("prec=%d, bpp=%d, sgnd=%d w=%d h=%d\n", image->comps[0].prec,
         image->comps[0].bpp, image->comps[0].sgnd, image->comps[0].w,
         image->comps[0].h);
  printf("prec=%d, bpp=%d, sgnd=%d w=%d h=%d\n", image->comps[1].prec,
         image->comps[1].bpp, image->comps[1].sgnd, image->comps[1].w,
         image->comps[1].h);
  printf("prec=%d, bpp=%d, sgnd=%d w=%d h=%d\n", image->comps[2].prec,
         image->comps[2].bpp, image->comps[2].sgnd, image->comps[2].w,
         image->comps[2].h);
#endif

  opj_stream_destroy(l_stream);
  opj_destroy_codec(l_codec);

  if (image->icc_profile_buf) {
    // Avoid a memory leak (see opj_decompress.c).
    free(image->icc_profile_buf);
    image->icc_profile_buf = NULL;
    image->icc_profile_len = 0;
  }

  OPJ_UINT32 numcomps = image->numcomps;
  OPJ_BOOL convert_to_rgba = OPJ_FALSE;

  if (pdf_numcomps <= 0) {
    // The pdf doesn't specify the color space, so we use the one from the image
    // and convert it to RGBA.
    numcomps = image->numcomps;
    if (!(pdf_smaks_in_data && numcomps == 4)) {
      if (image->color_space != OPJ_CLRSPC_SYCC && numcomps == 3 &&
          image->comps[0].dx == image->comps[0].dy && image->comps[1].dx != 1) {
        image->color_space = OPJ_CLRSPC_SYCC;
      } else if (numcomps <= 2) {
        image->color_space = OPJ_CLRSPC_GRAY;
      }

      if (image->color_space == OPJ_CLRSPC_SYCC) {
        color_sycc_to_rgb(image);
      } else if (image->color_space == OPJ_CLRSPC_CMYK) {
        color_cmyk_to_rgb(image);
      } else if (image->color_space == OPJ_CLRSPC_EYCC) {
        color_esycc_to_rgb(image);
      }
      convert_to_rgba = OPJ_TRUE;
    }
  } else if (numcomps > pdf_numcomps) {
    numcomps = pdf_numcomps;
  }

  if (!pdf_is_indexed_colormap) {
    for (int i = 0; i < numcomps; i++) {
      scale_component(&image->comps[i], 8);
    }
  }

  OPJ_SIZE_T nb_pixels = image->comps[0].w * image->comps[0].h;

  if (convert_to_rgba) {
    if (image->color_space == OPJ_CLRSPC_GRAY) {
      if (image->numcomps == 1) {
        gray_to_rgba(image->comps[0].data, nb_pixels);
      } else if (pdf_smaks_in_data) {
        graya_to_rgba(image->comps[0].data, image->comps[1].data, nb_pixels);
      }
    } else {
      rgb_to_rgba(image->comps[0].data, image->comps[1].data,
                  image->comps[2].data, nb_pixels);
    }
  } else {
    switch (numcomps) {
    case 1:
      copy_pixels_1(image->comps[0].data, nb_pixels);
      break;
    case 3:
      copy_pixels_3(image->comps[0].data, image->comps[1].data,
                    image->comps[2].data, nb_pixels);
      break;
    case 4:
      copy_pixels_4(image->comps[0].data, image->comps[1].data,
                    image->comps[2].data, image->comps[3].data, nb_pixels);
      break;
    }
  }
  opj_image_destroy(image);

  return 0;
}