Created attachment 44569 [details] result of test. I got a problem in cairo 1.10.2. The boundary of an image I try to draw has wrong color. It's 1 pixel outer box. you can see it with the attached file. '_cairo_image_surface_paint' function (It's not in 1.8.8 so '_cairo_surface_fallback_paint' function is used), and the decimal scaling, and the alpha property of the image surface, seem to make this issue. please take this issue and please let me know how to make it right. ================================================ my test code and conditions are below. ================================================ A. The conditions 1. set operator as CAIRO_OPERATOR_SOURCE 2. scale factor is decimal not integer. like cairo_scale(cr,4.1) in the test code 3. the image surface has no alpha format. B. The Test Code { char outfile[100]; uint32_t* dst_buffer = create_buffer32(480*800, 0xff00ff00); cairo_surface_t* cairo_surface = cairo_image_surface_create_for_data ( (unsigned char*)dst_buffer, CAIRO_FORMAT_RGB24, 480, 800, cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, 480)); cairo_t* cr = cairo_create(cairo_surface); cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT); cairo_scale(cr,4.1, 4.1); cairo_surface_t* src_surface = cairo_image_surface_create_from_png("/white.png"); // just white image file 25x16. cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_pattern_t* pattern = cairo_pattern_create_for_surface(src_surface); cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD); cairo_matrix_t matrix = { 1.0, 0, 0, 1.0, 0, 0 }; cairo_pattern_set_matrix(pattern, &matrix); cairo_translate(cr, 8, 8); cairo_set_source(cr, pattern); cairo_pattern_destroy(pattern); cairo_rectangle(cr, 0, 0, 25, 16); cairo_clip(cr); cairo_paint_with_alpha(cr, 1.0); sprintf(outfile,"test.png"); cairo_surface_write_to_png(cairo_surface,outfile); cairo_surface_destroy(src_surface); cairo_surface_destroy(cairo_surface); cairo_destroy(cr); destroy_buffer32(dst_buffer); }
That's double premultiplication of the image border. The immediate solution is to use CAIRO_EXTEND_REPEAT (or any setting other than none) and always use a rectangle to crop the result to the area you expect. I also still recommend that cairo be altered so that CAIRO_EXTEND_NONE does this automatically, as the current behavior is useless and not at all what a beginning user expects. Using "min" for the intersection with the current region+mask will avoid double premultiplication, which would be much better than what the cairo client can do (unless more complex methods of intersecting paths are added). bugzilla-daemon@freedesktop.org wrote: > https://bugs.freedesktop.org/show_bug.cgi?id=35407 > > Summary: boundary of image gets wrong color > Product: cairo > Version: 1.10.2 > Platform: ARM > OS/Version: Linux (All) > Status: NEW > Severity: major > Priority: medium > Component: general > AssignedTo: cworth@cworth.org > ReportedBy: clock9@naver.com > QAContact: cairo-bugs@cairographics.org > > > Created an attachment (id=44569) > --> (https://bugs.freedesktop.org/attachment.cgi?id=44569) > result of test. > > I got a problem in cairo 1.10.2. > > The boundary of an image I try to draw has wrong color. > > It's 1 pixel outer box. > > you can see it with the attached file. > > > '_cairo_image_surface_paint' function (It's not in 1.8.8 so > '_cairo_surface_fallback_paint' function is used), > and the decimal scaling, and the alpha property of the image surface, > seem to make this issue. > > please take this issue and please let me know how to make it right. > > > ================================================ > my test code and conditions are below. > ================================================ > A. The conditions > > 1. set operator as CAIRO_OPERATOR_SOURCE > 2. scale factor is decimal not integer. like cairo_scale(cr,4.1) in the test > code > 3. the image surface has no alpha format. > > B. The Test Code > > { > char outfile[100]; > > uint32_t* dst_buffer = create_buffer32(480*800, 0xff00ff00); > > cairo_surface_t* cairo_surface = cairo_image_surface_create_for_data ( > (unsigned > char*)dst_buffer, > CAIRO_FORMAT_RGB24, > 480, 800, > > cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, > 480)); > cairo_t* cr = cairo_create(cairo_surface); > > cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT); > > cairo_scale(cr,4.1, 4.1); > > cairo_surface_t* src_surface = > cairo_image_surface_create_from_png("/white.png"); // just white image file > 25x16. > > cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); > > cairo_pattern_t* pattern = cairo_pattern_create_for_surface(src_surface); > > cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD); > > cairo_matrix_t matrix = { 1.0, 0, 0, 1.0, 0, 0 }; > > cairo_pattern_set_matrix(pattern, &matrix); > > cairo_translate(cr, 8, 8); > > cairo_set_source(cr, pattern); > > cairo_pattern_destroy(pattern); > > cairo_rectangle(cr, 0, 0, 25, 16); > > cairo_clip(cr); > > cairo_paint_with_alpha(cr, 1.0); > > sprintf(outfile,"test.png"); > > cairo_surface_write_to_png(cairo_surface,outfile); > > cairo_surface_destroy(src_surface); > > cairo_surface_destroy(cairo_surface); > > cairo_destroy(cr); > > destroy_buffer32(dst_buffer); > } >
Using CAIRO_EXTEND_REPEAT for the pattern, is not working. the problem is still in there. How do I get the right rectangle without double premultiplication?
(In reply to comment #1) > That's double premultiplication of the image border. > > The immediate solution is to use CAIRO_EXTEND_REPEAT (or any setting > other than none) and always use a rectangle to crop the result to the > area you expect. > The example code is using CAIRO_EXTEND_PAD though?
(In reply to comment #3) > (In reply to comment #1) > > That's double premultiplication of the image border. > > > > The immediate solution is to use CAIRO_EXTEND_REPEAT (or any setting > > other than none) and always use a rectangle to crop the result to the > > area you expect. > > > The example code is using CAIRO_EXTEND_PAD though? Yes it was. and I'd changed 'CAIRO_EXTEND_PAD' to 'CAIRO_EXTEND_REPEAT'. but it didn't work. anything else I need to do?
please let me know what the difference of using pixman between fallback-paint function and image-paint function. 1. _cairo_surface_fallback_paint function, in this case, '_clip_and_composite_source' -> '_cairo_surface_composite' -> '_cairo_image_surface_composite' are called finally, 'pixman_image_composite32' is called twice with 'CAIRO_OPERATOR_DEST_OUT' and 'CAIRO_OPERATOR_ADD'. and it can get good result. 2. _cairo_image_surface_paint function, in this case, _clip_and_composite_boxes -> _composite_boxes -> _composite_unaligned_boxes are called. finally, 'pixman_image_composite32' is called once with 'CAIRO_OPERATOR_SOURCE'. and it gets bad result. actually, in this case, 'mask' in '_composite_unaligned_boxes' seems to be wrong. If I set it NULL, no problem. and If I use 'pixman_image_composite32' twice like fallback-paint function, no problem. Can you let me know what's wrong with it for me?
Created attachment 45011 [details] [review] Commit which seems to fix the problem for me Hi, this seems to be the same problem that was already mentioned on the mailing list here: http://lists.cairographics.org/archives/cairo/2011-March/021827.html Attached is my patch for that. Could you test if that also fixes the issue for you? I tried running your test case, but since I don't have white.png and I don't know which size it should have, I'm not sure this actually fixes the problem. It certainly does fix it for me.
Fixed by Uli Schlachter's patch. I hope this will be on next version. appreciated.
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.