[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 05:58:57 UTC 2016


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.

Ok, but writing PNG shall not affect consequent writings. If we paint
later with transparent source it is not opaque anymore and then 
_cairo_image_analyze_transparency() shall run again.

Either we have optimised PNG which requires time cost analyzing,
or we have intentionally set CAIRO_FORMAT_ARGB32 and write
non-optimized 32-bit PNG.

I think it would be good idea to add some function like
cairo_surface_write_to_png_flat() which will dump image data
to PNG in the same format as surface. It also can be usefull for
debugging then user can open file in image viwer and see what data
in what format hi is actually working on.


I am making slippy web map and generating overlay images. Tiles can be
opaque or transparent depends on data and I cannot know which will go
first.

Right now the tile surface cannot be re-used.

Thanks and Regards
chnav

Tuesday, June 7, 2016, 8:01:52 AM LOCAL
--


>> 
>> 
>> Thanks and Regards
>> chnav
>> 
>> 
>> Monday, June 6, 2016, 9:52:54 PM LOCAL
>> 





More information about the cairo mailing list