To answer my own questions:<br><br>In order to use cairo_image_surface_create_for_data(), the caller can provide an ARGB buffer with a stride that is either 1) aligned perfectly on (width X 4), or 2) aligned with a stride computed using cairo_format_stride_for_width(). In the case of 2, it is the end of the row that should be padded with nothingness.<br>
<br>Also, special care must be taken if the code is expected to run on multiple platforms since the ARGB buffer is required to be in native endian format. (imho, this is something that should be shielded from the caller, but there you go.)<br>
<br>So, to fill an ARGB buffer suitable for use in cairo_image_surface_create_for_data(), the following snippet will do:<br><br><span style="font-family: courier new,monospace;">short int word = 0x0001;<br>char *byte = (char *) &word;<br>
width = 550;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">height = 425;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">stride = cairo_image_surface_create_for_data(CAIRO_FORMAT_ARGB24, width)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">rgbbuf = calloc(stride * h, sizeof(char));</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> pos = rgbbuf;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">for(i=0;i<height;i++)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">{<br> A = (some computed alpha_value);<br>
R = (</span><span style="font-family: courier new,monospace;">some computed </span><span style="font-family: courier new,monospace;">red_value);<br> B = </span><span style="font-family: courier new,monospace;">(some computed </span><span style="font-family: courier new,monospace;">blue_value);<br>
G = </span><span style="font-family: courier new,monospace;">(some computed </span><span style="font-family: courier new,monospace;">green_value);<br style="font-family: courier new,monospace;"></span><span style="font-family: courier new,monospace;"> colorProb = colorP((float) PIX2USERY(&grL, i));</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> for(j=0;j<width;j++)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> { // ENDIANTEST ? LITTLE : BIG</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> *pos++ = (byte[0]) ? B : A;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> *pos++ = (</span><span style="font-family: courier new,monospace;">byte[0])</span><span style="font-family: courier new,monospace;"> ? G : R;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> *pos++ = (</span><span style="font-family: courier new,monospace;">byte[0]</span><span style="font-family: courier new,monospace;">) ? R : G;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> *pos++ = (</span><span style="font-family: courier new,monospace;">byte[0]</span><span style="font-family: courier new,monospace;">) ? A : B;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> }<br></span><span style="font-family: courier new,monospace;"> // advance to beginning of next row</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> pos += (stride/4 - width)*4; </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">}</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">cBar = cairo_image_surface_create_for_data(rgbbuf, CAIRO_FORMAT_RGB24, COLORBW, h, stride);</span><br style="font-family: courier new,monospace;">
<br>What I also found, curiously, was that the following code sequence produced wrong results on LINUX and a crash on MAC:<br><br><span style="font-family: courier new,monospace;">colorBar = cairo_image_surface_create_for_data(rgbbuf,<br>
CAIRO_FORMAT_RGB24, width, h, stride);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">free(rgbbuf);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">cBar2 = cairo_image_surface_create(CAIRO_FORMAT_RGB24, w, h);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">cr = cairo_create(cBar2);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">cairo_paint(cr);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">cairo_set_source_surface (cr, colorBar, 0, 0);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">cairo_paint (cr);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">cairo_surface_destroy (colorBar);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"></span><br>Playing around, it seems that the rgbbuf used to create colorBar cannot be freed until you're done with the colorBar surface itself. This is not stated in the documentation, so can cause serious head-scratching. Anyone know why the rgbbuf is required to hang around?<br>
<br>Moving the free() to after cairo_surface_destroy() removed this problem:<br><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">colorBar = cairo_image_surface_create_for_data(rgbbuf,<br>
CAIRO_FORMAT_RGB24, width, h, stride);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"></span><span style="font-family: courier new,monospace;">cBar2 = cairo_image_surface_create(CAIRO_FORMAT_RGB24, w, h);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">cr = cairo_create(cBar2);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">cairo_paint(cr);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">cairo_set_source_surface (cr, colorBar, 0, 0);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">cairo_paint (cr);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">cairo_surface_destroy (colorBar);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"></span><span style="font-family: courier new,monospace;">free(rgbbuf);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"><br><span style="font-family: arial,sans-serif;">And one other thing I discovered was that the PangoCairo routines are not thread-safe. Any idea if these are intended to be or will be in a future version? If so, which?<br>
<br>I think the documentation re: providing your own ARGB buffer could be made a little more robust in describing how to properly create an ARGB buffer for Cairo usage.<br><br>Thanks to those who provided pointers, they helped.<br>
<br>cheers,<br><br>richard<br><br></span></span><div class="gmail_quote">On Wed, Apr 9, 2008 at 9:39 AM, richard boaz <<a href="mailto:ivor.boaz@gmail.com">ivor.boaz@gmail.com</a>> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Hi,<br><br>I have a problem and a couple of questions related thereto.<br><br>The problem: I am trying to convert a programmatically generated RGB Buffer to a Cairo surface. Up till now, I have used GDK to create all my graphics (since I started before Cairo came to be, and required display within a GUI), but now need to convert to Cairo since I need to generate these PDF plots in the background on a server machine without a display. All fine and good.<br>
<br>Until I try to understand how to convert my gdk_* routines to their cairo equivalents.<br><br>In GDK, once I have created and filled my RGB buffer (3-byte color, RGB), I call:<br><br><font face="arial,sans-serif"><span style="font-family: courier new,monospace;">rgbbuf = malloc(wL * hL * 3); // RGB Buffer - 3-byte color - RGB<br>
memset(rgbbuf, 240, wL * hL * 3); // make the grey background<br>
pdf(rgbbuf, wL, hL, pdfReq, &gr, perB); // make the PDF plot<br>
<br>
</span></font><span style="font-family: courier new,monospace;">gdk_draw_rgb_image (pmap, gc, sideM, topM, wL, hL, GDK_RGB_DITHER_NONE, rgbbuf, wL*3);</span><br><br><font face="arial,sans-serif">After investigating how to do this in Cairo, I came up with this replacement:<br>
<br><span style="font-family: courier new,monospace;">rgbbuf = malloc(wL * hL * 4); // RGB Buffer - 4-byte color - ARGB<br>memset(rgbbuf, 240, wL * hL * 4); // make the grey background<br>pdf(rgbbuf, wL, hL, pdfReq, &gr, perB);</span></font><font face="arial,sans-serif"><span style="font-family: courier new,monospace;"> // make the PDF plot</span></font><br>
<font face="arial,sans-serif"><span style="font-family: courier new,monospace;"><br>pdfOut = cairo_image_surface_create_for_data(rgbbuf, CAIRO_FORMAT_RGB24, wL, hL, wL*4);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">cairo_set_source_surface (cr, pdfOut, sideM, topM); </span></font><font face="arial,sans-serif"><span style="font-family: courier new,monospace;">// cr is previously created</span></font><font face="arial,sans-serif"><span style="font-family: courier new,monospace;"></span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">cairo_rectangle (cr, sideM, topM, wL, hL); </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">cairo_fill (cr);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">cairo_surface_destroy (pdfOut);</span><br style="font-family: courier new,monospace;"><br>I have modified the RGB buffer size to 4-byte colors (ARGB) and filled it according to the <span style="font-family: courier new,monospace;">cairo_format_t</span> definition for </font><font size="4"><span style="font-family: courier new,monospace;"><code>CAIRO_FORMAT_RGB24<font face="arial,sans-serif">. However, this does not result in a picture that is correct.<br>
<br>My suspicion is that since the row stride is being optimized by Cairo, it does not nicely align on a boundary of width*4. The documentation currently states that in order to obtain the proper stride, the routine<font size="2"> </font></font></code></span></font><font style="font-family: courier new,monospace;" size="2">cairo_format_stride_for_width() <font face="arial,sans-serif">should be used. And also says that this is available since 1.6.<br>
<br>My questions:<br></font></font><ol><li>I do not find a v1.6 of Cairo available from the download site. Is it really true? The documentation preceeds the release of the software itself? (wow...) Or am I missing something? <br>
</li><li>If v1.6 isn't yet available, how do I get the optimized stride defined internally by Cairo?<br></li><li>Anyway, assuming for the moment this routine existed, how would I use it properly? Meaning, how do I programmatically generate a RGB buffer for display?</li>
</ol>My guess at Q3 would be:<br><ol><li>obtain the row stride using the cairo routine.</li><li>fill my RGB buffer, row by row, keeping track when i've hit the stride (computed in 1) to advance to the next proper 4-byte RGB location.</li>
</ol>This is based, however, on too many assumptions:<br><ol><li>I'm assuming that to optimize, Cairo makes the stride bigger (smaller makes no sense to me) than simply width*4 bytes.</li><li>Every row is guaranteed to be the same? Including the last?<br>
</li><li>Where are the empty bytes placed? at the end of the row or at the beginning? <br></li><li>Is the stride always a multiple of 4?<br></li></ol>More generally, it seems that programmatically generating a RGB buffer for conversion to a Cairo surface is not obvious (to me, yet). Am I wrong about this? Is there a more straightforward way of doing this I haven't yet teased from the documentation? Is there a different way of accessing the individual pixels of an RGB buffer I am unaware of that would allow me to fill them up individually without having to make wrong assumptions and guesses?<br>
<br>Any information to help me out of my pickle would be greatly appreciated.<br><br>regards,<br><font color="#888888"><br>richard<br>
</font></blockquote></div><br>