[cairo] broken pixman bilinear filtering?

Vladimir Vukicevic vladimirv at gmail.com
Mon Feb 13 01:51:40 PST 2006


The attached test produces a png like the attached output; the first
square is the 3x3 image scaled up 20x with bilinear filtering, and the
second is the image scaled up with nearest neighbour.  It looks like
for bilinear the center of the coverage region for the pixel at source
0,0 is placed at 0,0 in the destination, when instead it should be
offset by half the size of the destination area covered by a single
pixel.

Erm, not sure if i'm explaining that right, but looking at the images
should make it clear.  The bottom image is a 180x180 rectangle drawn
from -60 -60 (outlined in violet), with the original 0,0 rectangle
outlined in cyan.  Note that the pattern result after scaling extends
only to above and to the left -- I'd expect it to extend on all 4
sides, but half of the amount it currently extends.  The width of the
extending region is 20 pixels, which is exactly the size of 1 "pixel"
when scaled up.  For reference, the ps-scaled.png image is the result
of photoshop scaling up a 9x9 image with the 3x3 color region at the
center by 20x; the 60x60 region at the center is outlined in yellow. 
(The extending region is smaller because ps had white to blend with
there, whereas cairo/pixman should have been operating in "extend"
mode and just used the nearest real pixel color for areas outside the
specified image.)

I don't dare delve into pixman myself to look into this, I don't think :)

   - Vlad
-------------- next part --------------
/*
 * Copyright © 2005 Mozilla Corporation
 *
 * Permission to use, copy, modify, distribute, and sell this software
 * and its documentation for any purpose is hereby granted without
 * fee, provided that the above copyright notice appear in all copies
 * and that both that copyright notice and this permission notice
 * appear in supporting documentation, and that the name of
 * Mozilla Corporation not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior
 * permission. Mozilla Corporation makes no representations about the
 * suitability of this software for any purpose.  It is provided "as
 * is" without express or implied warranty.
 *
 * MOZILLA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS, IN NO EVENT SHALL MOZILLA CORPORATION BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Author: Vladimir Vukicevic <vladimir at pobox.com>
 */

#include "cairo-test.h"

#define WIDTH 200
#define HEIGHT 300

cairo_test_t test = {
    "image-filter",
    "Test image filtering.",
    WIDTH, HEIGHT
};

unsigned int image_bits[] = {
    0xff0000ff, 0xff00ff00, 0xffff0000,
    0xff00ff00, 0xffff0000, 0xff0000ff,
    0xffff0000, 0xff0000ff, 0xff00ff00
};

static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    cairo_surface_t *img;
    cairo_pattern_t *pat;
    cairo_matrix_t mat;

    img = cairo_image_surface_create_for_data ((unsigned char*) image_bits,
                                               CAIRO_FORMAT_ARGB32,
                                               3,
                                               3,
                                               3*4);

    pat = cairo_pattern_create_for_surface (img);
    cairo_matrix_init_scale (&mat, 0.05, 0.05);
    cairo_pattern_set_matrix (pat, &mat);

    cairo_translate (cr, 10, 10);

    cairo_set_source_rgb (cr, 0, 0, 1);
    cairo_rectangle (cr, 0, 0, 60, 60);
    cairo_stroke (cr);

    cairo_pattern_set_filter (pat, CAIRO_FILTER_BILINEAR);
    cairo_set_source (cr, pat);
    cairo_rectangle (cr, 0, 0, 60, 60);
    cairo_fill (cr);

    cairo_translate (cr, 70, 0);

    cairo_set_source_rgb (cr, 0, 0, 1);
    cairo_rectangle (cr, 0, 0, 60, 60);
    cairo_stroke (cr);

    cairo_pattern_set_filter (pat, CAIRO_FILTER_NEAREST);
    cairo_set_source (cr, pat);
    cairo_rectangle (cr, 0, 0, 60, 60);
    cairo_fill (cr);

    cairo_translate (cr, 0, 150);

    cairo_pattern_set_filter (pat, CAIRO_FILTER_BILINEAR);
    cairo_set_source (cr, pat);
    cairo_rectangle (cr, -60, -60, 180, 180);
    cairo_fill (cr);

    cairo_set_source_rgb (cr, 0, 1, 1);
    cairo_rectangle (cr, 0, 0, 60, 60);
    cairo_stroke (cr);

    cairo_set_source_rgb (cr, 1, 0, 1);
    cairo_rectangle (cr, -60, -60, 180, 180);
    cairo_stroke (cr);

    cairo_pattern_destroy (pat);
    cairo_surface_destroy (img);

    return CAIRO_TEST_SUCCESS;
}

int
main (void)
{
    return cairo_test (&test, draw);
}





-------------- next part --------------
A non-text attachment was scrubbed...
Name: filter-results.png
Type: image/png
Size: 11726 bytes
Desc: not available
Url : http://lists.freedesktop.org/archives/cairo/attachments/20060213/78e05ec9/filter-results-0001.png
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ps-scaled.png
Type: image/png
Size: 6951 bytes
Desc: not available
Url : http://lists.freedesktop.org/archives/cairo/attachments/20060213/78e05ec9/ps-scaled-0001.png


More information about the cairo mailing list