strukturag / libheif

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

Cannot get data from image, crash ( heif_image_get_plane return NULL) #336

Closed Arthur111 closed 3 years ago

Arthur111 commented 3 years ago

I don't know why you closed this issue. ( https://github.com/strukturag/libheif/issues/228 ) The problem is not solved i just tested now.

heif_decode_image(handle, &img, heif_colorspace_undefined, heif_chroma_undefined, NULL);

The data is NULL from heif_image_get_plane_readonly(img, heif_channel_Y, &stride)

And it worked with version 1.6.2 (the version i am obliged to use )

farindk commented 3 years ago

You did not define any colorspace and libheif now returns RGB by default. Hence, you get NULL when you ask for a Y plane. Explicitly tell heif_decode_image that you want YCbCr, or handle RGB on your side (preferred).

farindk commented 3 years ago

YCbCr output might even be deprecated in the future. It does not work well together with color profiles and infers a lot of detail problems.

Arthur111 commented 3 years ago

Ok seems a summary of this problem is needed :

i open an issue last year about loss of information between loading and writing an image ( https://github.com/strukturag/libheif/issues/122 )

You said : You're probably reading the image in RGB. Then colorspace transformations to/from YUV are used. These are not lossless. You have to process the data in the native YUV colorspace

So i used YCbCr and that solved the problem and i closed it.

Now since the release 1.6.2 its impossible to read the image in this way and now you say YCbCr :

"output might even be deprecated in the future"

For the work i have to do, it must be lossless (Watermarking, steganography) i have no choice but to use this old version.

farindk commented 3 years ago

Seems you have a very special use-case... Passing YUV around introduced a lot of problems (tiled images, odd sizes, rotation, details of the color conversion, see #263, #240). The most reasonable way to solve these was to do the YUV/RGB conversion internally and work on RGB primarily.

The new way to get lossless compression is to pass the image as RGB and use a nclx color profile with matrix_coefficients=0. This was not possible before, but now works with >=v1.7.0.

If you have to encode YUV data exactly as you pass it in, you probably have to stick with v1.6.2. I don't see an easy way to keep the support for this.

silverbacknet commented 3 years ago

YCbCr is very useful for specific purposes, mostly minimizing banding in low-bit-depth or for absolute lossless, but if you made it difficult to access in a "you're on your own" API that bypasses compositing, profiles, etc, I'd have no problem.

Like, drop YCbCr from heif_image_get_plane_readonly and make a heif_image_get_plane_raw that returns an array of decoded streams, with positions & maaaaybe other properties, and what someone does with that is up to them. I tried to work out how to make odd-positioned 4:2:0 work losslessly and realized it was impossible without some sort of blending, the tiny quality hit beats the huge time sink. I'd be up to making that if you're interested.

farindk commented 3 years ago

@silverbacknet I think the way to support this would be a lower level API with direct access to the file structure. This would also allow other things like accessing tiles in a grid image separately, or adding your own transformation properties. However, that is a big can of worms that I don't want to open yet.

Maybe it might be even better that those users who need this low level access, use an ISOMBFF library and do the decoding of the images themselves for exactly that subset of image they have to support. A general purpose library handling every special use case is difficult.

A single 'heif_image_get_plane_raw' won't work because it's not clear how it should handle tiled images, for example.

silverbacknet commented 3 years ago

Good point. There's so much involved in dealing with corner cases that the complexity just multiplies.

Arthur111 commented 3 years ago

I tested like this :

    err = heif_decode_image(handle, &img, heif_colorspace_RGB, heif_chroma_interleaved_RGB, NULL);

   struct heif_color_profile_nclx nclx;
    nclx.version                  = 1;
    nclx.matrix_coefficients      = heif_matrix_coefficients_RGB_GBR;
    nclx.transfer_characteristics = heif_transfer_characteristic_unspecified;
    nclx.color_primaries          = heif_color_primaries_unspecified;
    nclx.full_range_flag          = true;
    heif_image_set_nclx_color_profile(img, &nclx);

   unsigned char *data = heif_image_get_plane(img, heif_channel_interleaved, &planeNo);

i get the data, no crash, but the picture is completely different (i only change the 1st bit on few bytes) and bigger.

So as you said i have to stick with 1.6.2. It work well with jpeg, tiff, png but your api after 1.6.2 or openExr apis cause problem (loss of data).

Thank you , i close this one