Bug 43158 - Does not hold to requested or stated pixel formats
Summary: Does not hold to requested or stated pixel formats
Status: RESOLVED NOTABUG
Alias: None
Product: cairo
Classification: Unclassified
Component: general (show other bugs)
Version: 1.10.2
Hardware: x86 (IA32) Linux (All)
: medium normal
Assignee: Carl Worth
QA Contact: cairo-bugs mailing list
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-11-22 02:04 UTC by mako
Modified: 2011-11-22 22:26 UTC (History)
0 users

See Also:
i915 platform:
i915 features:


Attachments

Description mako 2011-11-22 02:04:36 UTC
On my machine, the following code will illustrate cairo's failure to store its image surface in the requested format.
Results indicate that the used format comes out BGRA32 no matter what it says it has chosen.
I can't tell how I can figure out which backend I'm running under, so I've put this in "general".

#include <cairo/cairo.h>
#include <stdio.h>
#include <stdint.h>
int main(int argc, char** argv){
	const int w=10, h=10;
	cairo_surface_t* ul = cairo_image_surface_create(
		CAIRO_FORMAT_RGB24,w,h);
	printf("%d\n", cairo_image_surface_get_format(ul));
	cairo_t* draw = cairo_create(ul);
	cairo_set_source_rgba(draw,1,0.5,0.27,1);
	cairo_paint(draw);
	uint8_t* dat = (uint8_t*)(cairo_image_surface_get_data(ul));
	for(unsigned iy=0; iy<h; ++iy){
		for(unsigned ix=0; ix<w; ++ix){
			unsigned pixelP = cairo_image_surface_get_stride(ul)*iy + ix*4;
			printf(
				"%x, %x, %x, %x\n",
				dat[pixelP],
				dat[pixelP+1],
				dat[pixelP+2],
				dat[pixelP+3]);
		}
		printf("%c", '\n');
	}
}
Comment 1 Andrea Canciani 2011-11-22 02:58:14 UTC
(In reply to comment #0)
> On my machine, the following code will illustrate cairo's failure to store its
> image surface in the requested format.
> Results indicate that the used format comes out BGRA32 no matter what it says
> it has chosen.

You should never access RGBA32 or RGB24 as single bytes.
As explained in http://cairographics.org/manual/cairo-Image-Surfaces.html#cairo-format-t they should be used as 32-bits quantities.

> I can't tell how I can figure out which backend I'm running under, so I've put
> this in "general".

You're using the image backend, but the same issue should happen everywhere.

Please fix as suggested and check again.

> 
> #include <cairo/cairo.h>
> #include <stdio.h>
> #include <stdint.h>
> int main(int argc, char** argv){
>     const int w=10, h=10;
>     cairo_surface_t* ul = cairo_image_surface_create(
>         CAIRO_FORMAT_RGB24,w,h);
>     printf("%d\n", cairo_image_surface_get_format(ul));
>     cairo_t* draw = cairo_create(ul);
>     cairo_set_source_rgba(draw,1,0.5,0.27,1);
>     cairo_paint(draw);
>     uint8_t* dat = (uint8_t*)(cairo_image_surface_get_data(ul));
>     for(unsigned iy=0; iy<h; ++iy){
>         for(unsigned ix=0; ix<w; ++ix){
>             unsigned pixelP = cairo_image_surface_get_stride(ul)*iy + ix;

     uint32_t* dat32 = (uint32_t*)(dat + pixelP);

             printf(
                 "%x, %x, %x, %x\n",
                 (dat32[0] >> 24) & 0xff,
                 (dat32[0] >> 16) & 0xff,
                 (dat32[0] >> 8) & 0xff,
                 (dat32[0] >> 0) & 0xff);
>         }
>         printf("%c", '\n');
>     }
> }

Please try the modified code and reopen the bugreport if the problem persists.
Comment 2 mako 2011-11-22 16:55:42 UTC
Right, sure. My mistake. I didn't notice the note in the docs about endianness. I made the mistake of thinking that the pixel format description on its own was sufficient to describing the way pixels are formatted in memory. </passive aggression>

My problem originally arose when I was trying to transfer an imageSurface to an external library, cogl. Cogl's format description scheme for the most part took the seemingly[to me] more logical avenue of describing the pixel formats in terms of byte order. The fact that these format descriptions don't align very well with cairo seems to be indicative of a bastard of a situation to me.
Comment 3 Andrea Canciani 2011-11-22 18:22:45 UTC
(In reply to comment #2)
> Right, sure. My mistake. I didn't notice the note in the docs about endianness.
> I made the mistake of thinking that the pixel format description on its own was
> sufficient to describing the way pixels are formatted in memory. </passive
> aggression>

RGB24 is even less self-explaining in that respect (most people believes that it indicates that pixels only occupy 3 bytes).

FWIW even cairo devs sometimes have to deal with the endianness/word-based access issue (you can have a look at the endian-dependent code in cairo-gl, for example).
The choice of making the pixels accessible using "pixelsize-words" was probably made to keep the access to non-byte-aligned formats simpler (accessing R5G6B5 would get quite ugly).

> 
> My problem originally arose when I was trying to transfer an imageSurface to an
> external library, cogl. Cogl's format description scheme for the most part took
> the seemingly[to me] more logical avenue of describing the pixel formats in
> terms of byte order. The fact that these format descriptions don't align very
> well with cairo seems to be indicative of a bastard of a situation to me.

You might want to keep an eye on cairo-gl (which already accesses/maps many "byte-defined" formats as cairo formats and on the new cogl backend.

If you have any idea about improvements to the documentations that might help avoid (to other people) your same issue (being tricked by misleading/not self-explaining format names), they would be very appreciated.
Changing format names or meaning would be an API break, so it's not possible (although for cairo 2.x I would definitely vote for deprecating RGB24 in favor of something which explicitly states that the format has 32 bpp).
Comment 4 mako 2011-11-22 22:26:04 UTC
I thank you for your vote. Aside from that I'd suggest making little-endian's argb distinguished from big-endian's version of argb.

Oh! Yes I was using the Cairomm docs, where there are no notes about the true nature of these formats. I was forced to presume their names were sufficient for figuring that out. I should do something about that.


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.