in libheif/plugins/encoder_openjpeg.cc [452:551]
struct heif_error opj_encode_image(void* encoder_raw, const struct heif_image* image, enum heif_image_input_class image_class)
{
struct encoder_struct_opj* encoder = (struct encoder_struct_opj*) encoder_raw;
struct heif_error err;
heif_chroma chroma = heif_image_get_chroma_format(image);
heif_colorspace colorspace = heif_image_get_colorspace(image);
int width = heif_image_get_primary_width(image);
int height = heif_image_get_primary_height(image);
std::vector<heif_channel> channels;
OPJ_COLOR_SPACE opj_colorspace;
switch (colorspace) {
case heif_colorspace_YCbCr:
channels = {heif_channel_Y, heif_channel_Cb, heif_channel_Cr};
opj_colorspace = OPJ_CLRSPC_SYCC;
break;
case heif_colorspace_RGB:
channels = {heif_channel_R, heif_channel_G, heif_channel_B};
opj_colorspace = OPJ_CLRSPC_SRGB;
break;
case heif_colorspace_monochrome:
channels = {heif_channel_Y};
opj_colorspace = OPJ_CLRSPC_GRAY;
break;
default:
assert(false);
return heif_error{heif_error_Encoding_error, heif_suberror_Unspecified, "OpenJPEG encoder plugin received image with invalid colorspace."};
}
int band_count = (int) channels.size();
opj_image_cmptparm_t component_params[4];
memset(&component_params, 0, band_count * sizeof(opj_image_cmptparm_t));
for (int comp = 0; comp < band_count; comp++) {
int bpp = heif_image_get_bits_per_pixel_range(image, channels[comp]);
int sub_dx = 1, sub_dy = 1;
switch (chroma) {
case heif_chroma_420:
sub_dx = 2;
sub_dy = 2;
break;
case heif_chroma_422:
sub_dx = 2;
sub_dy = 1;
break;
default:
break;
}
component_params[comp].prec = bpp;
component_params[comp].sgnd = 0;
component_params[comp].dx = comp == 0 ? 1 : sub_dx;
component_params[comp].dy = comp == 0 ? 1 : sub_dy;
component_params[comp].w = comp == 0 ? width : (width + sub_dx / 2) / sub_dx;
component_params[comp].h = comp == 0 ? height : (height + sub_dy / 2) / sub_dy;
}
opj_image_t* opj_image = opj_image_create(band_count, &component_params[0], opj_colorspace);
if (image == nullptr) {
// Failed to create image
err = {heif_error_Encoding_error, heif_suberror_Unspecified, "Failed create OpenJPEG image"};
return err;
}
opj_image->x0 = 0;
opj_image->y0 = 0;
opj_image->x1 = width;
opj_image->y1 = height;
for (int comp = 0; comp < band_count; comp++) {
int stride;
const uint8_t* p = heif_image_get_plane_readonly(image, channels[comp], &stride);
int cwidth = component_params[comp].w;
int cheight = component_params[comp].h;
// Note: obj_image data is 32bit integer
for (int y = 0; y < cheight; y++) {
for (int x = 0; x < cwidth; x++) {
opj_image->comps[comp].data[y * cwidth + x] = p[y * stride + x];
}
}
}
encoder->data_read = false;
encoder->codestream.clear(); //Fixes issue when encoding multiple images and old data persists.
//Encodes the image into a 'codestream' which is stored in the 'encoder' variable
err = generate_codestream(opj_image, encoder);
opj_image_destroy(opj_image);
return err;
}