WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
83973
[GTK] Should pass canvas/philip/tests/toDataURL.jpeg.alpha.html
https://bugs.webkit.org/show_bug.cgi?id=83973
Summary
[GTK] Should pass canvas/philip/tests/toDataURL.jpeg.alpha.html
noel gordon
Reported
2012-04-14 00:55:24 PDT
To pass this test, pass premultiplied color to the JPEG encoder. Modify the cairoImageSurfaceToGdkPixbuf() function added in
https://bugs.webkit.org/attachment.cgi?id=62763&action=prettypatch
to have an default second argument (default false) that requests premultiplied color output when creating the GdkPixbuf.
Attachments
Patch
(7.55 KB, patch)
2012-04-16 08:35 PDT
,
noel gordon
no flags
Details
Formatted Diff
Diff
Patch
(7.51 KB, patch)
2012-04-17 02:13 PDT
,
noel gordon
no flags
Details
Formatted Diff
Diff
Patch
(3.81 KB, patch)
2012-04-23 02:27 PDT
,
Carlos Garcia Campos
no flags
Details
Formatted Diff
Diff
Show Obsolete
(1)
View All
Add attachment
proposed patch, testcase, etc.
noel gordon
Comment 1
2012-04-14 01:25:56 PDT
... or else create a specific function, cairoImageSurfaceToGdkPixbufPremultiplied() say, for the purpose. Martin, let me know which you'd prefer and I'll prepare a patch.
noel gordon
Comment 2
2012-04-16 08:32:03 PDT
Given
bug 49532
, seems cairoImageSurfaceToGdkPixbufPremultiplied() is the way to go.
noel gordon
Comment 3
2012-04-16 08:35:44 PDT
Created
attachment 137350
[details]
Patch
noel gordon
Comment 4
2012-04-17 02:12:43 PDT
Update.
noel gordon
Comment 5
2012-04-17 02:13:43 PDT
Created
attachment 137494
[details]
Patch
noel gordon
Comment 6
2012-04-17 02:17:54 PDT
I have no means to run GTK tests in my setup. So maybe we submit and check the webkit GTK bots, or you could patch it locally and see if the toDataURL.jpeg.alpha test passes.
noel gordon
Comment 7
2012-04-17 02:28:48 PDT
https://www.w3.org/Bugs/Public/show_bug.cgi?id=11431
Carlos Garcia Campos
Comment 8
2012-04-17 03:05:11 PDT
I guess this should be handled by GdkPixbuf jpeg encoder, no? gdk_pixbuf_get_from_surface() returns a valid GdkPixbuf (using an alpha channel or not depending on the cairo surface image format). So gdk_pixbuf_save should work with that pixbuf.
noel gordon
Comment 9
2012-04-18 18:28:59 PDT
(In reply to
comment #8
)
> I guess this should be handled by GdkPixbuf jpeg encoder, no?
Nope. JPEG encoders ignore alpha channel and encode the RGB channels only. The encoder used by GTK looks right to me; see real_save_jpeg() here:
http://gdk-pixbuf.sourcearchive.com/documentation/2.22.0-1/io-jpeg_8c-source.html
I believe the JPEG encoder should remain dumb and encode whatever RGB it's given. That RGB can be in one of two states: premultiplied or not.
noel gordon
Comment 10
2012-04-18 18:34:47 PDT
(In reply to
comment #8
)
> gdk_pixbuf_get_from_surface() returns a valid GdkPixbuf (using an alpha channel or not depending on the cairo surface image format). So gdk_pixbuf_save should work with that pixbuf.
The cairo surface of an ImageBuffer is CAIRO_FORMAT_ARGB32 premultiplied. gdk_pixbuf_get_from_surface() converts the cairo surface pixels to un-premultiplied color. Thus, gdk_pixbuf_save() would send un-premultiplied color to the JPEG encoder if gdk_pixbuf_get_from_surface() was used to create the GdkPixbuf. The <canvas> spec states that toDataURL() must encode a Porter-Duff composite source-over black for image types that do not support alpha, JPEG for example. The toDataURL.jpeg.alpha.html checks for that. The test has been vetted for accuracy (
bug 40147
) and approved by the W3C
http://w3c-test.org/html/tests/approved/canvas/toDataURL.jpeg.alpha.html
The pass this test, you must send premultiplied color to the JPEG encoder. The reasons are documented in ChangeLog
https://bugs.webkit.org/attachment.cgi?id=76964&action=prettypatch
Carlos Garcia Campos
Comment 11
2012-04-19 00:08:34 PDT
(In reply to
comment #10
)
> (In reply to
comment #8
) > > gdk_pixbuf_get_from_surface() returns a valid GdkPixbuf (using an alpha channel or not depending on the cairo surface image format). So gdk_pixbuf_save should work with that pixbuf. > > The cairo surface of an ImageBuffer is CAIRO_FORMAT_ARGB32 premultiplied. gdk_pixbuf_get_from_surface() converts the cairo surface pixels to un-premultiplied color. Thus, gdk_pixbuf_save() would send un-premultiplied color to the JPEG encoder if gdk_pixbuf_get_from_surface() was used to create the GdkPixbuf. > > The <canvas> spec states that toDataURL() must encode a Porter-Duff composite source-over black for image types that do not support alpha, JPEG for example. The toDataURL.jpeg.alpha.html checks for that. The test has been vetted for accuracy (
bug 40147
) and approved by the W3C > >
http://w3c-test.org/html/tests/approved/canvas/toDataURL.jpeg.alpha.html
> > The pass this test, you must send premultiplied color to the JPEG encoder. The reasons are documented in ChangeLog
https://bugs.webkit.org/attachment.cgi?id=76964&action=prettypatch
In that case I think we should do exactly that, something like this should work: GRefPtr<GdkPixbuf> pixbuf; if (type == "jpeg" && cairo_image_surface_get_format(surface) == CAIRO_FORMAT_ARGB32) { // JPEG doesn't support alpha channel. The <canvas> spec states that toDataURL() must encode a Porter-Duff // composite source-over black for image types that do not support alpha. RefPtr<cairo_surface_t> newSurface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_RGB24, cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface))); RefPtr<cairo_t> cr = adoptRef(cairo_create(newSurface.get())); cairo_set_source_surface(cr.get(), surface, 0, 0); cairo_set_operator(cr.get(), CAIRO_OPERATOR_SOURCE); cairo_paint(cr.get()); pixbuf = adoptGRef(cairoImageSurfaceToGdkPixbuf(newSurface.get())); } else pixbuf = adoptGRef(cairoImageSurfaceToGdkPixbuf(surface)); if (!pixbuf) return false;
noel gordon
Comment 12
2012-04-19 00:28:21 PDT
> RefPtr<cairo_t> cr = adoptRef(cairo_create(newSurface.get())); > cairo_set_source_surface(cr.get(), surface, 0, 0); > cairo_set_operator(cr.get(), CAIRO_OPERATOR_SOURCE); > cairo_paint(cr.get()); > pixbuf = adoptGRef(cairoImageSurfaceToGdkPixbuf(newSurface.get()));
Does cairoImageSurfaceToGdkPixbuf produce un-premultiplied colors here?
Carlos Garcia Campos
Comment 13
2012-04-19 00:47:50 PDT
(In reply to
comment #12
)
> > RefPtr<cairo_t> cr = adoptRef(cairo_create(newSurface.get())); > > cairo_set_source_surface(cr.get(), surface, 0, 0); > > cairo_set_operator(cr.get(), CAIRO_OPERATOR_SOURCE); > > cairo_paint(cr.get()); > > pixbuf = adoptGRef(cairoImageSurfaceToGdkPixbuf(newSurface.get())); > > Does cairoImageSurfaceToGdkPixbuf produce un-premultiplied colors here?
It doesn't un-premultiply because there's no alpha in the source image.
noel gordon
Comment 14
2012-04-19 00:57:49 PDT
Ok and when cairo paints a CAIRO_FORMAT_ARGB32 source into a CAIRO_FORMAT_RGB24 surface, the alpha channel is just ignored?
noel gordon
Comment 15
2012-04-20 22:27:09 PDT
Because maybe it's not ignored given that the another plausible answer to my question is that since CAIRO_FORMAT_ARGB32 is premultipled data, it gets un-premultipled on write to a CAIRO_FORMAT_RGB24 target. I done a bunch of web searching trying to work out the correct answer, but so far I've found no canonical reference to the fact, nor in the cairo docs, or by reading through the cairo code trying to understand what it does. I guess I'm stuck here. What's a reasonable way for us to proceed here?
Carlos Garcia Campos
Comment 16
2012-04-21 01:27:01 PDT
Data is not un-premultiplied, you can test the code I pasted and check that test toDataURL.jpeg.alpha.html passes.
noel gordon
Comment 17
2012-04-21 01:52:53 PDT
Was
comment #6
unclear?
Carlos Garcia Campos
Comment 18
2012-04-21 02:05:16 PDT
(In reply to
comment #17
)
> Was
comment #6
unclear?
You an test it with GtkLauncher and loading
http://w3c-test.org/html/tests/approved/canvas/toDataURL.jpeg.alpha.html
you don't need to run the tests
noel gordon
Comment 19
2012-04-21 02:05:42 PDT
Was is the GtkLauncher ?
noel gordon
Comment 20
2012-04-21 02:07:06 PDT
And whatever is is, I doubt I can build on on windows box.
noel gordon
Comment 21
2012-04-21 02:12:35 PDT
Sorry, whatever GtkLauncher is, I doubt I can build it on a windows box.
Carlos Garcia Campos
Comment 22
2012-04-21 02:20:13 PDT
(In reply to
comment #21
)
> Sorry, whatever GtkLauncher is, I doubt I can build it on a windows box.
Ok, I thought you could build webkit but not run the tests. GtkLauncher is a small web browser for testing that is built with the GTK+ port. I can simply submit a patch with the code I pasted if you want.
noel gordon
Comment 23
2012-04-21 02:27:24 PDT
(In reply to
comment #22
)
> (In reply to
comment #21
) > > Sorry, whatever GtkLauncher is, I doubt I can build it on a windows box. > > Ok, I thought you could build webkit but not run the tests. GtkLauncher is a small web browser for testing that is built with the GTK+ port.
Appreciate the explanation. And no I can't build webkit gtk and run tests with my current setup (win32).
> I can simply submit a patch with the code I pasted if you want.
Yes please, that sounds good to me, if you like to do it.
noel gordon
Comment 24
2012-04-22 21:03:05 PDT
One more thought was that Martin's original code, now modified, is much like a single memcpy. The code in
comment #11
seems to cost two memcpy operations (one for the paint and one for cairoImageSurfaceToGdkPixbuf step). Should I worry about performance?
Martin Robinson
Comment 25
2012-04-22 21:22:36 PDT
(In reply to
comment #24
)
> One more thought was that Martin's original code, now modified, is much like a single memcpy. The code in
comment #11
seems to cost two memcpy operations (one for the paint and one for cairoImageSurfaceToGdkPixbuf step). Should I worry about performance?
Indeed it might be nice to do this in a single pass instead of two. How can you be sure your original patch fixes the test without testing it though? If necessary, I can do that locally.
noel gordon
Comment 26
2012-04-22 23:52:27 PDT
Indeed. Testing that the test works means we either 1) submit and watch the GTK+ build bot, or
> If necessary, I can do that locally.
do as you suggest. If you have time, that'd sure help.
Carlos Garcia Campos
Comment 27
2012-04-23 02:27:52 PDT
Created
attachment 138311
[details]
Patch
Carlos Garcia Campos
Comment 28
2012-04-23 02:28:48 PDT
(In reply to
comment #24
)
> One more thought was that Martin's original code, now modified, is much like a single memcpy. The code in
comment #11
seems to cost two memcpy operations (one for the paint and one for cairoImageSurfaceToGdkPixbuf step). Should I worry about performance?
We can actually use the same data to avoid the memory allocation since cairo use the same 32 bits also for RGB24.
noel gordon
Comment 29
2012-04-23 19:37:51 PDT
Comment on
attachment 138311
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=138311&action=review
> Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp:45 > + // JPEG doesn't support alpha channel. The <canvas> spec states that toDataURL() must encode a Porter-Duff
Patch looks fine to me. nit: CAIRO_FORMAT_ARGB32 is a given, right? We could just assert if we're concerned about it. if (type == "jpeg") { ASSERT(cairo_image_surface_get_format(surface) == CAIRO_FORMAT_ARGB32); ...
Philippe Normand
Comment 30
2012-04-24 06:59:20 PDT
Comment on
attachment 138311
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=138311&action=review
r=me but please consider this question before landing:
>> Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp:45 >> + // JPEG doesn't support alpha channel. The <canvas> spec states that toDataURL() must encode a Porter-Duff > > Patch looks fine to me. > > nit: CAIRO_FORMAT_ARGB32 is a given, right? We could just assert if we're concerned about it. > > if (type == "jpeg") { > ASSERT(cairo_image_surface_get_format(surface) == CAIRO_FORMAT_ARGB32); > ...
Yes I think it'd be ok to proceed as Noel advises. Carlos?
Carlos Garcia Campos
Comment 31
2012-04-24 08:08:19 PDT
(In reply to
comment #30
)
> (From update of
attachment 138311
[details]
) > View in context:
https://bugs.webkit.org/attachment.cgi?id=138311&action=review
> > r=me but please consider this question before landing: > > >> Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp:45 > >> + // JPEG doesn't support alpha channel. The <canvas> spec states that toDataURL() must encode a Porter-Duff > > > > Patch looks fine to me. > > > > nit: CAIRO_FORMAT_ARGB32 is a given, right? We could just assert if we're concerned about it. > > > > if (type == "jpeg") { > > ASSERT(cairo_image_surface_get_format(surface) == CAIRO_FORMAT_ARGB32); > > ... > > Yes I think it'd be ok to proceed as Noel advises. Carlos?
es, or even remove the check since surface is created unconditionally as ARGB32 in ImageBuffer constructor
Carlos Garcia Campos
Comment 32
2012-04-24 08:25:34 PDT
Committed
r115058
: <
http://trac.webkit.org/changeset/115058
>
noel gordon
Comment 33
2012-04-24 13:56:42 PDT
(In reply to
comment #31
)
> or even remove the check since surface is created unconditionally as ARGB32 in ImageBuffer constructor
Exactly. Thanks for helping everybody, test passes.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug