static emscripten::val heif_js_decode_image()

in libheif/api/libheif/heif_emscripten.h [122:217]


static emscripten::val heif_js_decode_image(struct heif_image_handle* handle,
                                            enum heif_colorspace colorspace, enum heif_chroma chroma)
{
  emscripten::val result = emscripten::val::object();
  if (!handle) {
    return result;
  }

  struct heif_image* image;
  struct heif_error err = heif_decode_image(handle, &image, colorspace, chroma, nullptr);
  if (err.code != heif_error_Ok) {
    return emscripten::val(err);
  }

  result.set("is_primary", heif_image_handle_is_primary_image(handle));
  result.set("thumbnails", heif_image_handle_get_number_of_thumbnails(handle));
  int width = heif_image_handle_get_width(handle);
  result.set("width", width);
  int height = heif_image_handle_get_height(handle);
  result.set("height", height);
  std::basic_string<unsigned char> data;
  result.set("chroma", heif_image_get_chroma_format(image));
  result.set("colorspace", heif_image_get_colorspace(image));
  switch (heif_image_get_colorspace(image)) {
    case heif_colorspace_YCbCr: {
      int stride_y;
      const uint8_t* plane_y = heif_image_get_plane_readonly(image,
                                                             heif_channel_Y, &stride_y);
      int stride_u;
      const uint8_t* plane_u = heif_image_get_plane_readonly(image,
                                                             heif_channel_Cb, &stride_u);
      int stride_v;
      const uint8_t* plane_v = heif_image_get_plane_readonly(image,
                                                             heif_channel_Cr, &stride_v);
      data.resize((width * height) + (2 * round_odd(width) * round_odd(height)));
      unsigned char* dest = const_cast<unsigned char*>(data.data());
      strided_copy(dest, plane_y, width, height, stride_y);
      strided_copy(dest + (width * height), plane_u,
                   round_odd(width), round_odd(height), stride_u);
      strided_copy(dest + (width * height) + (round_odd(width) * round_odd(height)),
                   plane_v, round_odd(width), round_odd(height), stride_v);
    }
      break;
    case heif_colorspace_RGB: {
      if(heif_image_get_chroma_format(image) == heif_chroma_interleaved_RGB) {
        int stride_rgb;
        const uint8_t* plane_rgb = heif_image_get_plane_readonly(image,
                                                                 heif_channel_interleaved, &stride_rgb);
        data.resize(width * height * 3);
        unsigned char* dest = const_cast<unsigned char*>(data.data());
        strided_copy(dest, plane_rgb, width * 3, height, stride_rgb);
      }
      else if (heif_image_get_chroma_format(image) == heif_chroma_interleaved_RGBA) {
        int stride_rgba;
        const uint8_t* plane_rgba = heif_image_get_plane_readonly(image,
                                                                 heif_channel_interleaved, &stride_rgba);
        data.resize(width * height * 4);
        unsigned char* dest = const_cast<unsigned char*>(data.data());
        strided_copy(dest, plane_rgba, width * 4, height, stride_rgba);
      }
      else {
        assert(false);
      }
    }
      break;
    case heif_colorspace_monochrome: {
      assert(heif_image_get_chroma_format(image) ==
             heif_chroma_monochrome);
      int stride_grey;
      const uint8_t* plane_grey = heif_image_get_plane_readonly(image,
                                                                heif_channel_Y, &stride_grey);
      data.resize(width * height);
      unsigned char* dest = const_cast<unsigned char*>(data.data());
      strided_copy(dest, plane_grey, width, height, stride_grey);
    }
      break;
    default:
      // Should never reach here.
      break;
  }
  result.set("data", std::move(data));

  if (heif_image_has_channel(image, heif_channel_Alpha)) {
    std::basic_string<unsigned char> alpha;
    int stride_alpha;
    const uint8_t* plane_alpha = heif_image_get_plane_readonly(image,
							       heif_channel_Alpha, &stride_alpha);
    alpha.resize(width * height);
    unsigned char* dest = const_cast<unsigned char*>(alpha.data());
    strided_copy(dest, plane_alpha, width, height, stride_alpha);
    result.set("alpha", std::move(alpha));
  }

  heif_image_release(image);
  return result;
}