(none) imager-devel
/ help / lists / applications / search /
 

Re: Using other applications affine transformation matrixes with Imager

From: Bernhard Wei▀huhn (
19288@xyz.molar.is)
Date: Mon 09 Nov 2009 - 20:25:49 GMT

  • Next message: Tony Cook: "Re: Using other applications affine transformation matrixes with Imager"

    On 07.11.2009, at 23:53, Tony Cook wrote:

    > Hi Bernhard,
    >
    > It seems the main difference is that Imager uses the matrix to convert
    > a location in the destination image to a location in the source image,
    > while ImageMagick uses it to convert a location in the source image to
    > a location in the destination image.
    >
    > I expect what you need is the inverse of the matrix you're using with
    > ImageMagick.

    Thanks Tony, you were spot on with this. I had to swap rx and ry, but
    otherwise everything worked as suggested, thanks.

    Ultimately, I switched back to letting Cairo perform the actual
    transformation. Cairo is so insanely fast, that it is actually
    worthwhile to read the file with Imager, swap colour channels
    according to endianness and dump the imager data as raw to a cario
    image surface, let cairo do the matrix translation, read the surface
    back as a raw file, swap colour channels back and let imager write the
    file.

    The solution lacks in terms of elegance, but the achieved performance
    is so superb, it leaves the competition (including graphics magic) in
    the dust: A moderately complex matrix conversion of the same 2M jpeg:

       ImageMagic: 20s
       Imager native: 9.5s
       GraphicsMagic: 5.4s
       Imager + Cairo: 2.4s

    Currently I use the following (quite hackish) approach:

    use Config;

    my $channelSwapMatrix;
    if ( $Config{byteorder} =~ /^1234/) {
       # little endian (intel): bgra -> rgba
       $channelSwapMatrix = [
         [ 0, 0, 1, 0 ], # red comes from channel 3
         [ 0, 1, 0, 0 ], # green comes from channel 2
         [ 1, 0, 0, 0 ], # blue comes from channel 1
         [ 0, 0, 0, 1 ] # alpha comes from channel 4
       ];
    }
    else {
       # bigendian: argb -> rgba. Untested.
       $channelSwapMatrix = [
         [ 0, 1, 0, 0 ], # red comes from chan 2
         [ 0, 0, 1, 0 ], # green from chan 3
         [ 0, 0, 0, 1 ], # blue from chan 4
         [ 1, 0, 0, 0 ] # alpha from chan 1
       ]
    }

    my $data;
    my $imager = new Imager( file => $infile ) or croak Imager->errstr();
    $imager->convert( matrix=> $channelSwapMatrix )
       ->write( data => \$data, type => 'raw', raw_interleave => 0 );

    my $surface = Cairo::ImageSurface->create_for_data(
       $data, 'argb32', $imager->getwidth, $imager->getheight,
       Cairo::Format::stride_for_width( 'argb32', $imager->getwidth)
    );

    This is for moving Imager data to Cairo. A similar conversion it used
    to write back the transformed Cairo surface to Imager for converting
    it to the target filetype.

    Could this be improved upon or would a more elegant handover between
    Imager-data and Cairo Image-Surfaces be a reasonable feature request
    for Imager? Since Cairo Image_Surfaces rarely exist as a written file
    format, I hesitate to implement a filetype handler for Imager.

    Any suggestions?

    Thanks again for your help and your amazing Imager Library!

    regards,
       bkw



  •