[cairo] BUG: CAIRO_FORMAT_ARGB32, image_surface transparency = CAIRO_IMAGE_IS_OPAQUE after write_png()
lamer314 at mail.ru
lamer314 at mail.ru
Tue Jun 7 07:15:41 UTC 2016
Tuesday, June 7, 2016, 8:58:57 AM, you wrote:
lmr> Tuesday, June 7, 2016, 1:49:47 AM, you wrote:
AJ>> On 07/06/16 05:37, chnav wrote:
>>> Hi,
>>>
>>> have discovered sporatic bug working with transparent images,
>>> which I finally managed to reproduce.
>>>
>>> ------- code 1 begin --------------
>>> cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 256, 256);
>>> cairo_t *cr = cairo_create (surface);
>>> // Initialisation
>>> cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
>>> cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
>>> cairo_paint(cr);
>>> cairo_surface_write_to_png(surface, "cairo_test3a.png");
>>> // ...
>>> cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.5);
>>> cairo_paint(cr);
>>> cairo_surface_write_to_png(surface, "cairo_test3b.png");
>>> ------- code 1 end --------------
>>>
>>> Both files supposed to be 32 bit PNG with alpha but above will produce
>>> 24 bit png without alpha.
>>>
>>>
>>> ------- code 2 begin --------------
>>> cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 256, 256);
>>> cairo_t *cr = cairo_create (surface);
>>> // Initialisation
>>> cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
>>> cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.9);
>>> cairo_paint(cr);
>>> cairo_surface_write_to_png(surface, "cairo_test3a.png");
>>> // ...
>>> cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.5);
>>> cairo_paint(cr);
>>> cairo_surface_write_to_png(surface, "cairo_test3b.png");
>>> ------- code 2 end --------------
>>>
>>> Now both files are 32 bit PNG alpha.
>>>
>>>
>>> Short explanation, tracing "code 1" in debugger:
>>>
>>> 1. Before 1st call of write_png():
>>> image->transparency = CAIRO_IMAGE_UNKNOWN;
>>> 2. cairo_surface_write_to_png() calls _cairo_image_analyze_transparency();
>>> 3. _cairo_image_analyze_transparency() see CAIRO_IMAGE_UNKNOWN and
>>> scans every pixels' alpha. It founds all of them equal 255 and changes
>>> image->transparency = CAIRO_IMAGE_IS_OPAQUE (!!!)
AJ>> If all alpha is 255 the image is opaque.
>>> 4. From now on any subsequent call of _cairo_image_analyze_transparency()
>>> will return CAIRO_IMAGE_IS_OPAQUE;
>>> 5. cairo_surface_write_to_png() sets png_color_type = PNG_COLOR_TYPE_RGB;
>>>
>>>
>>> I assume if we create image surface CAIRO_FORMAT_ARGB32 then
>>> image->transparency must be CAIRO_IMAGE_HAS_ALPHA
AJ>> That assumption is incorrect. Cairo analyses image transparency to
AJ>> ensure it uses the most efficient format when writing out images to PNG,
AJ>> PDF, and PS.
lmr> Ok, but writing PNG shall not affect consequent writings. If we paint
lmr> later with transparent source it is not opaque anymore and then
lmr> _cairo_image_analyze_transparency() shall run again.
lmr> Either we have optimised PNG which requires time cost analyzing,
lmr> or we have intentionally set CAIRO_FORMAT_ARGB32 and write
lmr> non-optimized 32-bit PNG.
lmr> I think it would be good idea to add some function like
lmr> cairo_surface_write_to_png_flat() which will dump image data
lmr> to PNG in the same format as surface. It also can be usefull for
lmr> debugging then user can open file in image viwer and see what data
lmr> in what format hi is actually working on.
lmr> I am making slippy web map and generating overlay images. Tiles can be
lmr> opaque or transparent depends on data and I cannot know which will go
lmr> first.
I have added my usecase
------- code 3 begin --------------
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 256, 256);
cairo_t *cr = cairo_create(surface);
while(havedata) {
// clear canvas
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
cairo_paint(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
// do real data drawing
_PaintSomeData(cr);
cairo_surface_write_to_png_stream(surface, ..........);
}
------- code 3 end --------------
lmr> Right now the tile surface cannot be re-used.
lmr> Thanks and Regards
lmr> chnav
lmr> Tuesday, June 7, 2016, 8:01:52 AM LOCAL
lmr> --
>>>
>>>
>>> Thanks and Regards
>>> chnav
>>>
>>>
>>> Monday, June 6, 2016, 9:52:54 PM LOCAL
>>>
More information about the cairo
mailing list