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;
}