strukturag / libheif

libheif is an HEIF and AVIF file format decoder and encoder.
Other
1.75k stars 302 forks source link

heif_decode_image with heif_colorspace_YCbCr, but output image's colorspace is RGB #250

Open zljj0818 opened 4 years ago

zljj0818 commented 4 years ago

Hi, I want to decode and the colorspace of output image is YUV, but find in HeifContext::decode_image_planar: if (target_colorspace==heif_colorspace_YCbCr) { target_colorspace = heif_colorspace_RGB; } It seems that if target colorspace is YUV, libheif will set to RGB internally.

Arthur111 commented 4 years ago

Yes and that's the problem. see https://github.com/strukturag/libheif/issues/228 RGB is not lossless and since a recent commit where rgb is set to i cannot use this api so i use 1.6.2 release.

the answer from the developper is :

Using YCbCr with downsamples chroma resulted in a lot of problems (e.g. rotating images with odd sizes), so that the default output format is now RGB. This probably won't change.

In fact, you can no longer get the original color space, rgb is not a default, it is set to.

silverbacknet commented 4 years ago

decode_image_planar() is a lower level function than decode_image_user(), which should be the only one converting unless explicitly requested. I would rather a "not implemented" error (heif_error_Unsupported_feature?) be sent back instead of forcibly converting everything to squash it, particularly since YUV<->RGB conversion is fraught with problems if the wrong matrix is used, but I'd also rather just get back the rotated subsampled bytes, like libjpeg-turbo, if it's an unlayered image. Upgrading to YUV444 instead of RGB should also be the first fallback.

HEIF has a number of weird corner cases, and one of them is that layered sub-images can have completely different colorspaces, like a lossy YUV420 layer and a lossless RGB444 layer. (One of the original use-cases behind HEIF.) In this case I would rather that decode_image_planar() simply return a "multiple colorspaces, no default available" error if heif_colorspace_undefined is passed.

I've been experimenting with the codebase and thinking of putting a pull request together for this.