After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 783591 - openjpegdec: support grayscale with alpha
openjpegdec: support grayscale with alpha
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-bad
unspecified
Other Linux
: Normal enhancement
: 1.13.1
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2017-06-09 10:46 UTC by Aaron Boxer
Modified: 2017-07-10 07:15 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
openjpegdec: support grayscale with alpha (3.58 KB, patch)
2017-06-13 03:36 UTC, Aaron Boxer
none Details | Review
Enforce single alpha channel. (6.20 KB, patch)
2017-06-14 03:52 UTC, Aaron Boxer
none Details | Review
Enforce single alpha channel for YUVA, RGBA and YA (7.28 KB, patch)
2017-06-14 04:03 UTC, Aaron Boxer
none Details | Review
update comments on previous patch (8.28 KB, patch)
2017-06-15 11:18 UTC, Aaron Boxer
none Details | Review
Support alpha channel (pre-multiplied is treated as non-premultiplied, and user is warned in this case) (8.81 KB, patch)
2017-06-20 11:17 UTC, Aaron Boxer
none Details | Review
Support alpha channel (pre-multiplied is treated as non-premultiplied, and user is warned in this case) (9.08 KB, patch)
2017-06-24 18:41 UTC, Aaron Boxer
none Details | Review
support grayscale with alpha (5.71 KB, patch)
2017-07-06 18:19 UTC, Aaron Boxer
committed Details | Review

Description Aaron Boxer 2017-06-09 10:46:47 UTC
Sample image:  https://github.com/GrokImageCompression/grok-test-data/blob/master/input/nonregression/Marrin.jp2

Pipeline 

gst-launch-1.0 -v filesrc location=Marrin.jp2 ! typefind ! openjpegdec ! imagefreeze ! autovideosink

Error:  Unsupported number of GRAY components: 2
Comment 1 Aaron Boxer 2017-06-09 11:32:49 UTC
Can we not just ignore the alpha channel ?
Comment 2 Sebastian Dröge (slomo) 2017-06-12 06:39:56 UTC
You could either add a gray video format that has an alpha channel, or could convert inside the decoder to ARGB.
Comment 3 Aaron Boxer 2017-06-12 13:36:39 UTC
Thanks. Simplest approach is the ARGB idea.
Comment 4 Aaron Boxer 2017-06-13 03:36:54 UTC
Created attachment 353648 [details] [review]
openjpegdec: support grayscale with alpha
Comment 5 Sebastian Dröge (slomo) 2017-06-13 06:31:54 UTC
Review of attachment 353648 [details] [review]:

::: ext/openjpeg/gstopenjpegdec.c
@@ +386,3 @@
+      tmp[1] = off[0] + *data_in[0];
+      tmp[2] = tmp[1];
+      tmp[3] = tmp[1];

Is alpha always component 0 (data_in[0]) in openjpeg? And why do you output it as component 1 (tmp[1]), wouldn't that be RAGB or similar then?
Comment 6 Aaron Boxer 2017-06-13 12:14:39 UTC
Thanks for the review. On disk, alpha is invariably the last channel.
But, J2K has a colour definition box that can remap the channels, have
multiple alphas, or no alpha......

This would add another layer of complexity, but I could parse the box,
map the colours correctly, and deal with images with multiple alphas,
or four channels and no alpha. But, I have never seen such.
Comment 7 Aaron Boxer 2017-06-13 12:15:16 UTC
Also, there are palette images, but these are also rare.
Comment 8 Aaron Boxer 2017-06-13 20:11:10 UTC
Another issue to consider: there are two types of alpha - pre-multiplied and non-premultiplied. With pre-multiplied, the alpha has already been applied to the channel, and stored in the alpha channel. With non-pre-multiplied, alpha represents a floating point number between 0 and 1, which must then be multiplied with the colour channel to give the alpha representation.
Comment 9 Sebastian Dröge (slomo) 2017-06-13 20:56:12 UTC
pre-multiplied or not can be signalled with GstVideoMeta. Not sure what to do about the other things. What do you suggest?
Comment 10 Aaron Boxer 2017-06-14 03:51:47 UTC
I think at the moment, we can just limit support to single alpha channel for gray or RGB, and alpha must be the final channel. Hopefully that is not too heavy-handed :)

In the wild, my feeling is that 99% of all disk files are stored in this format.

I have updated the patch to do this checking, (I also corrected video format in a few places so that is consistently AXXX format, since all of the fill_frame methods expect output alpha to be stored in first component).

I have added a comment about how to determine pre-multiplied alpha, but don't know how to store this in GstVideoMeta.
Comment 11 Aaron Boxer 2017-06-14 03:52:55 UTC
Created attachment 353728 [details] [review]
Enforce single alpha channel.
Comment 12 Aaron Boxer 2017-06-14 04:03:49 UTC
Created attachment 353729 [details] [review]
Enforce single alpha channel for YUVA, RGBA and YA
Comment 13 Sebastian Dröge (slomo) 2017-06-15 07:36:08 UTC
Review of attachment 353729 [details] [review]:

::: ext/openjpeg/gstopenjpegdec.c
@@ +425,3 @@
+      tmp[1] = off[0] + (*data_in[0] << shift[0]);
+      tmp[2] = tmp[1];
+      tmp[3] = tmp[1];

Why are you generating something like RAGB here, i.e. alpha on the second component and all other components the same value?

@@ +888,2 @@
       if (image->numcomps == 4) {
+        /* alpha:  0 == colour channel, 1 == non-pre-multiplied alpha, 2 == pre-multiplied alpha */

This comment seems wrong for numcomps==4, and also above

@@ +903,3 @@
+          return GST_FLOW_NOT_NEGOTIATED;
+        }
+        if (alpha_channel != 3) {

If it's elsewhere, that seems to require only a minimal change to the conversion function or using e.g. BGRA instead of ABGR.
Comment 14 Aaron Boxer 2017-06-15 10:55:09 UTC
(In reply to Sebastian Dröge (slomo) from comment #13)
> Review of attachment 353729 [details] [review] [review]:
Thanks for the review

> 
> ::: ext/openjpeg/gstopenjpegdec.c
> @@ +425,3 @@
> +      tmp[1] = off[0] + (*data_in[0] << shift[0]);
> +      tmp[2] = tmp[1];
> +      tmp[3] = tmp[1];
> 
> Why are you generating something like RAGB here, i.e. alpha on the second
> component and all other components the same value?

I assume that alpha is always in the last component : component == 1. Since format is ARGB, and tmp[0] stores alpha in output, we need tmp[0] =  off[1] + (*data_in[1] << shift[1]);


> 
> @@ +888,2 @@
>        if (image->numcomps == 4) {
> +        /* alpha:  0 == colour channel, 1 == non-pre-multiplied alpha, 2 ==
> pre-multiplied alpha */
> 
> This comment seems wrong for numcomps==4, and also above

In the comment, alpha is referring to image->comps[c].alpha. If the value of image->comps[c].alpha is zero, then c is a colour channel. Otherwise, it is an alpha channel. I will make this clearer.


> 
> @@ +903,3 @@
> +          return GST_FLOW_NOT_NEGOTIATED;
> +        }
> +        if (alpha_channel != 3) {
> 
> If it's elsewhere, that seems to require only a minimal change to the
> conversion function or using e.g. BGRA instead of ABGR.

The code previously was assuming that alpha is always the last channel in the input; just making this assumption explicit :)  I don't think input frames have alpha in the first channel ?
Comment 15 Aaron Boxer 2017-06-15 10:57:18 UTC
For simplicity, can we not just assume alpha as last channel in input ? That's what the code was doing previously for RGBA, I'm just adding YA support....
Comment 16 Sebastian Dröge (slomo) 2017-06-15 11:04:06 UTC
Sure, that's fine, it just seems like I'm misunderstanding something with the patch :)

(In reply to Aaron Boxer from comment #14)
> (In reply to Sebastian Dröge (slomo) from comment #13)
> > Review of attachment 353729 [details] [review] [review] [review]:
> Thanks for the review
> 
> > 
> > ::: ext/openjpeg/gstopenjpegdec.c
> > @@ +425,3 @@
> > +      tmp[1] = off[0] + (*data_in[0] << shift[0]);
> > +      tmp[2] = tmp[1];
> > +      tmp[3] = tmp[1];
> > 
> > Why are you generating something like RAGB here, i.e. alpha on the second
> > component and all other components the same value?
> 
> I assume that alpha is always in the last component : component == 1. Since
> format is ARGB, and tmp[0] stores alpha in output, we need tmp[0] =  off[1]
> + (*data_in[1] << shift[1]);

But shouldn't that then be
tmp[0] = off[1] ...
tmp[1] = off[0] ...
tmp[2] = off[0] ...
tmp[3] = off[0] ...

I.e. alpha goes to alpha, grey value goes to R,G,B?
Comment 17 Aaron Boxer 2017-06-15 11:06:36 UTC
(In reply to Sebastian Dröge (slomo) from comment #16)
> Sure, that's fine, it just seems like I'm misunderstanding something with
> the patch :)

no problem :)


> 
> (In reply to Aaron Boxer from comment #14)
> > (In reply to Sebastian Dröge (slomo) from comment #13)
> > > Review of attachment 353729 [details] [review] [review] [review] [review]:
> > Thanks for the review
> > 
> > > 
> > > ::: ext/openjpeg/gstopenjpegdec.c
> > > @@ +425,3 @@
> > > +      tmp[1] = off[0] + (*data_in[0] << shift[0]);
> > > +      tmp[2] = tmp[1];
> > > +      tmp[3] = tmp[1];
> > > 
> > > Why are you generating something like RAGB here, i.e. alpha on the second
> > > component and all other components the same value?
> > 
> > I assume that alpha is always in the last component : component == 1. Since
> > format is ARGB, and tmp[0] stores alpha in output, we need tmp[0] =  off[1]
> > + (*data_in[1] << shift[1]);
> 
> But shouldn't that then be
> tmp[0] = off[1] ...
> tmp[1] = off[0] ...
> tmp[2] = off[0] ...
> tmp[3] = off[0] ...
> 
> I.e. alpha goes to alpha, grey value goes to R,G,B?

I am just trying to re-use the R value in the G and B channels. R == tmp[1]
Just save a little calculation :)
Comment 18 Aaron Boxer 2017-06-15 11:18:16 UTC
Created attachment 353814 [details] [review]
update comments on previous patch
Comment 19 Aaron Boxer 2017-06-17 15:37:16 UTC
So, I think the only missing piece in this patch is
how to signal that the opacity channel is pre-multiplied or not.
Comment 20 Sebastian Dröge (slomo) 2017-06-20 06:15:33 UTC
See GST_VIDEO_FLAG_PREMULTIPLIED_ALPHA. While this can be put into a GstVideoInfo, there's nothing that does anything meaningful with it for your case. It would have to be added to the caps or to the GstVideoMeta somehow to be useful.

Without such changes, only non-premultiplied alpha is supported currently.
Comment 21 Aaron Boxer 2017-06-20 11:17:22 UTC
Created attachment 354092 [details] [review]
Support alpha channel (pre-multiplied is treated as non-premultiplied, and user is warned in this case)
Comment 22 Aaron Boxer 2017-06-20 11:19:39 UTC
I am happy with this patch - it adds support for mono with alpha, fixes a few bugs with RGBA, and handles pre-multiplied alpha be warning the user and treating as non-pre-multiplied. As far as I know, most images these days do not use pre-multiplied alpha.
Comment 23 Aaron Boxer 2017-06-20 11:21:25 UTC
The patch also makes explicit the assumption in the current code that alpha is expected as the last channel in the input image. I believe this is the case for almost all J2K images in the wild.
Comment 24 Aaron Boxer 2017-06-24 18:41:40 UTC
Created attachment 354405 [details] [review]
Support alpha channel (pre-multiplied is treated as non-premultiplied, and user is warned in this case)
Comment 25 Aaron Boxer 2017-07-05 11:43:54 UTC
This patch is ready to change the world :) just needs merging.
Comment 26 Sebastian Dröge (slomo) 2017-07-06 07:02:17 UTC
commit 1883ac26b7d02724c11d4f4bad8698c4873b443d (HEAD -> master)
Author: Aaron Boxer <boxerab@gmail.com>
Date:   Mon Jun 12 23:36:05 2017 -0400

    openjpegdec: support grayscale with alpha channel
    
    https://bugzilla.gnome.org/show_bug.cgi?id=783591
Comment 27 Sebastian Dröge (slomo) 2017-07-06 07:31:09 UTC
This breaks the build with older openjpeg it seems:

> gstopenjpegdec.c: In function ‘gst_openjpeg_dec_negotiate’:
> gstopenjpegdec.c:752:30: error: ‘opj_image_comp_t {aka struct opj_image_comp}’ has no member named ‘alpha’
>            if (image->comps[i].alpha) {
>                               ^
Comment 28 Aaron Boxer 2017-07-06 13:16:40 UTC
damn! Yes, openjpeg doesn't have the alpha member, I added it on my project.
So, will have to remove a lot of this code then. I will assume that 2 component
image is YA and 4 component image is RGBA.
Comment 29 Aaron Boxer 2017-07-06 18:19:16 UTC
Created attachment 355039 [details] [review]
support grayscale with alpha

Since we can't get alpha info from openjpeg, we assume that grayscale with alpha is in the format YA, where Y is the luminance channel, and A is the alpha channel.
Comment 30 Sebastian Dröge (slomo) 2017-07-10 07:15:38 UTC
commit 6d723303a28a6dbe7b40911885d50acea9099a67 (HEAD -> master)
Author: Aaron Boxer <boxerab@gmail.com>
Date:   Mon Jun 12 23:36:05 2017 -0400

    openjpegdec: support grayscale with alpha channel
    
    https://bugzilla.gnome.org/show_bug.cgi?id=783591