Re: patch [1/1] invert image in _cairo_gl_surrface_map_to_image

Andrea Canciani <[email protected]>
Newsgroups gmane.comp.lib.cairo
Message-ID <CAN_5=BAywWj99-4uDaWvEQqtuO-4hXekT7RPPDLeRAUVth3Adg@mail.gmail.com>
On Fri, Jan 13, 2012 at 1:05 AM, Henry (Yu) Song - SISA
<[email protected]> wrote:
> Hey, Andrea
>
> I looked at your negative stride image code,
> The effect of calling cairo_image_surface_create_for_data (data + stride * (height - 1), format, width, height, -stride) is same as calling
> _cairo_image_surface_create_with_pixman_format (data, format, width, height, -1), the stride parameter is tested and ignored in cairo-image-surface.c

No, it's not ignored, it's respected.
This means that the "data" buffer will contain the image in bottom to
top order and that cairo-image will use it in the same order, too.

>
> I don't see invert image comes out.

If you want to see an inverted image coming out, you should
"misinterpret" the buffer, as in the attachment
(data is filled drawing to png_image, which is top to bottom, then
read through inv, which is bottom to top)

IIRC GL gives you a buffer in a bottom to top order, hence you simply
need to wrap it into a top to bottom (aka negative stride) image.
No additional cairo-image allocation nor temporary buffers ;)

Andrea

>
> Thanks
>
> Henry
>
>
> -----Original Message-----
> From: [email protected] [mailto:[email protected]] On Behalf Of Andrea Canciani
> Sent: Wednesday, January 04, 2012 11:08 AM
> To: Henry Song
> Cc: [email protected]
> Subject: Re: [cairo] patch [1/1] invert image in _cairo_gl_surrface_map_to_image
>
> On Wed, Jan 4, 2012 at 4:57 PM, Henry Song <[email protected]> wrote:
>> Hi, Andrea
>>
>> The patch creates a dst of inv_image and the source is image,  they are not
>> same, aren't they?
>
> Sorry, you're right, I misread the pattern creation.
> Andrea
>
>>
>> Thanks
>>
>> Henry
>>
>> -----Original Message-----
>> From: [email protected]
>> [mailto:[email protected]] On Behalf Of
>> Andrea Canciani
>> Sent: Wednesday, January 04, 2012 12:43 AM
>> To: Henry (Yu) Song - SISA
>> Cc: [email protected]
>> Subject: Re: [cairo] patch [1/1] invert image in
>> _cairo_gl_surrface_map_to_image
>>
>> On Wed, Jan 4, 2012 at 1:56 AM, Henry (Yu) Song - SISA
>> <[email protected]> wrote:
>>> Date:   Fri Dec 30 11:24:54 2011 -0800
>>>
>>>    gl: Add support to invert non texture gl surface image that does not
>> have
>>>    GL_MESA_pack_invert when map from gl surface to image surface
>>>
>>> diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
>>> index 8f69033..8b8f196 100644
>>>
>>> --- a/src/cairo-gl-surface.c
>>> +++ b/src/cairo-gl-surface.c
>>> @@ -1001,6 +1001,10 @@ _cairo_gl_surface_map_to_image (void
>>  *abstract_surface,
>>>     unsigned int cpp;
>>>     cairo_bool_t invert;
>>>     cairo_status_t status;
>>> +    cairo_t *inv_cr = NULL;
>>> +    cairo_image_surface_t *inv_image = NULL;
>>> +    cairo_pattern_t *inv_pattern = NULL;
>>> +    cairo_matrix_t inv_matrix;
>>>
>>>     /* Want to use a switch statement here but the compiler gets whiny. */
>>>     if (surface->base.content == CAIRO_CONTENT_COLOR_ALPHA) {
>>> @@ -1093,6 +1097,50 @@ _cairo_gl_surface_map_to_image (void
>>  *abstract_surface,
>>>        image = (cairo_image_surface_t *)
>>>            _cairo_surface_create_in_error (status);
>>>     }
>>> +
>>> +    /*
>>> +     * FIXME: we must invert the image if it is non texture surface,
>>> +     * and it does not have GL_MESA_pack_invert.
>>> +     * Is there more efficient way to invert image?
>>
>> Using negative stride might be more efficient, but some backends might
>> not (yet) support them correctly.
>>
>> Side note:
>> It is already possible to create negative stride images.
>> Should we add a test trying to use them and support them?
>> Unless I get feedback, I'll try to write the test this weekend.
>>
>>> +     */
>>> +
>>> +    if (! _cairo_gl_surface_is_texture (surface) && ! invert) {
>>> +        inv_image = (cairo_image_surface_t*)
>>> +       _cairo_image_surface_create_with_pixman_format (NULL,
>>> +                                                       pixman_format,
>>> +                                                       extents->width,
>>> +                                                       extents->height,
>>> +                                                       -1);
>>> +       if (unlikely (inv_image->base.status)) {
>>> +           goto CLEAR_IMAGE;
>>> +       }
>>> +
>>> +       image->base.is_clear = FALSE;
>>> +       inv_pattern = cairo_pattern_create_for_surface (&image->base);
>>> +       if (unlikely (inv_pattern->status)) {
>>> +           goto CLEAR_PATTERN;
>>> +       }
>>> +       cairo_matrix_init_scale (&inv_matrix, 1.0, -1.0);
>>> +       cairo_matrix_translate (&inv_matrix, 0, -(extents->height));
>>> +       cairo_pattern_set_matrix (inv_pattern, &inv_matrix);
>>> +
>>> +       inv_cr = cairo_create (&inv_image->base);
>>> +       if (unlikely (inv_cr->status)) {
>>> +           goto CLEAR_CAIRO;
>>> +       }
>>> +       cairo_set_source (inv_cr, inv_pattern);
>>> +       cairo_set_operator (inv_cr, CAIRO_OPERATOR_SOURCE);
>>> +       cairo_paint (inv_cr);
>>
>> You're using the same surface as source and as destination.
>> This results in undefined behavior.
>> If you want to flip the image like this, you should use two independent
>> surfaces
>>
>>
>>> +       cairo_surface_destroy (&image->base);
>>> +       image = (cairo_image_surface_t *)cairo_surface_reference
>> (&inv_image->base);
>>> +    }
>>> +
>>> +CLEAR_CAIRO:
>>> +    cairo_destroy (inv_cr);
>>> +CLEAR_PATTERN:
>>> +    cairo_pattern_destroy (inv_pattern);
>>> +CLEAR_IMAGE:
>>> +    cairo_surface_destroy (&inv_image->base);
>>>
>>>     return &image->base;
>>>  }
>>> --
>>> cairo mailing list
>>> [email protected]
>>> http://lists.cairographics.org/mailman/listinfo/cairo
>> --
>> cairo mailing list
>> [email protected]
>> http://lists.cairographics.org/mailman/listinfo/cairo
>>
> --
> cairo mailing list
> [email protected]
> http://lists.cairographics.org/mailman/listinfo/cairo
> --
> cairo mailing list
> [email protected]
> http://lists.cairographics.org/mailman/listinfo/cairo

--
cairo mailing list
[email protected]
http://lists.cairographics.org/mailman/listinfo/cairo
negative-stride-image.c (text/x-csrc, 2.5 KB)
/*
 * Copyright 2012 Andrea Canciani
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * Author: Andrea Canciani <[email protected]>
 */

#include "cairo-test.h"

static const char *png_filename = "romedalen.png";

static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
    cairo_format_t format = CAIRO_FORMAT_ARGB32;
    cairo_t *cr_pngimage;
    cairo_surface_t *png, *pngimage, *inv;
    uint8_t *data;
    int stride;

    png = cairo_test_create_surface_from_png (ctx, png_filename);

    stride = cairo_format_stride_for_width (format, width);
    data = calloc (stride, height);
    pngimage = cairo_image_surface_create_for_data (data, format,
						    width, height, stride);
    inv = cairo_image_surface_create_for_data (data + stride * (height - 1),
					       format, width, height, -stride);

    cr_pngimage = cairo_create (pngimage);
    cairo_set_source_surface (cr_pngimage, png, 0, 0);
    cairo_paint (cr_pngimage);
    cairo_destroy (cr_pngimage);

    cairo_set_source_surface (cr, inv, 0, 0);
    cairo_paint (cr);

    cairo_surface_destroy (png);

    cairo_surface_finish (inv);
    cairo_surface_destroy (inv);

    cairo_surface_finish (pngimage);
    cairo_surface_destroy (pngimage);

    free (data);

    return CAIRO_TEST_SUCCESS;
}

CAIRO_TEST (negative_stride_image,
	    "Test that images with a negative stride are handled correctly.",
	    "stride, image", /* keywords */
	    NULL, /* requirements */
	    256, 192,
	    NULL, draw)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.