in libheif/pixelimage.cc [1156:1255]
Error HeifPixelImage::scale_nearest_neighbor(std::shared_ptr<HeifPixelImage>& out_img,
int width, int height) const
{
out_img = std::make_shared<HeifPixelImage>();
out_img->create(width, height, m_colorspace, m_chroma);
// --- create output image with scaled planes
if (has_channel(heif_channel_interleaved)) {
out_img->add_plane(heif_channel_interleaved, width, height, get_bits_per_pixel(heif_channel_interleaved));
}
else {
if (get_colorspace() == heif_colorspace_RGB) {
if (!has_channel(heif_channel_R) ||
!has_channel(heif_channel_G) ||
!has_channel(heif_channel_B)) {
return Error(heif_error_Invalid_input, heif_suberror_Unspecified, "RGB input without R,G,B, planes");
}
out_img->add_plane(heif_channel_R, width, height, get_bits_per_pixel(heif_channel_R));
out_img->add_plane(heif_channel_G, width, height, get_bits_per_pixel(heif_channel_G));
out_img->add_plane(heif_channel_B, width, height, get_bits_per_pixel(heif_channel_B));
}
else if (get_colorspace() == heif_colorspace_monochrome) {
if (!has_channel(heif_channel_Y)) {
return Error(heif_error_Invalid_input, heif_suberror_Unspecified, "monochrome input with no Y plane");
}
out_img->add_plane(heif_channel_Y, width, height, get_bits_per_pixel(heif_channel_Y));
}
else if (get_colorspace() == heif_colorspace_YCbCr) {
if (!has_channel(heif_channel_Y) ||
!has_channel(heif_channel_Cb) ||
!has_channel(heif_channel_Cr)) {
return Error(heif_error_Invalid_input, heif_suberror_Unspecified, "YCbCr image without Y,Cb,Cr planes");
}
int cw, ch;
get_subsampled_size(width, height, heif_channel_Cb, get_chroma_format(), &cw, &ch);
out_img->add_plane(heif_channel_Y, width, height, get_bits_per_pixel(heif_channel_Y));
out_img->add_plane(heif_channel_Cb, cw, ch, get_bits_per_pixel(heif_channel_Cb));
out_img->add_plane(heif_channel_Cr, cw, ch, get_bits_per_pixel(heif_channel_Cr));
}
else {
return Error(heif_error_Invalid_input, heif_suberror_Unspecified, "unknown color configuration");
}
if (has_channel(heif_channel_Alpha)) {
out_img->add_plane(heif_channel_Alpha, width, height, get_bits_per_pixel(heif_channel_Alpha));
}
}
// --- scale all channels
for (const auto& plane_pair : m_planes) {
heif_channel channel = plane_pair.first;
const ImagePlane& plane = plane_pair.second;
const int bpp = get_storage_bits_per_pixel(channel) / 8;
if (!out_img->has_channel(channel)) {
return Error(heif_error_Invalid_input, heif_suberror_Unspecified, "scaling input has extra color plane");
}
int out_w = out_img->get_width(channel);
int out_h = out_img->get_height(channel);
int in_stride = plane.stride;
const uint8_t* in_data = plane.mem;
int out_stride = 0;
uint8_t* out_data = out_img->get_plane(channel, &out_stride);
for (int y = 0; y < out_h; y++) {
int iy = y * m_height / height;
if (bpp == 1) {
for (int x = 0; x < out_w; x++) {
int ix = x * m_width / width;
out_data[y * out_stride + x] = in_data[iy * in_stride + ix];
}
}
else {
for (int x = 0; x < out_w; x++) {
int ix = x * m_width / width;
for (int b = 0; b < bpp; b++) {
out_data[y * out_stride + bpp * x + b] = in_data[iy * in_stride + bpp * ix + b];
}
}
}
}
}
return Error::Ok;
}