Copy_Pixels(sx, sy, width, height, dx, dy)

PerlMagick is an object-oriented Perl interface to ImageMagick. Use this forum to discuss, make suggestions about, or report bugs concerning PerlMagick.
Post Reply
BrianP007
Posts: 49
Joined: 2013-12-13T09:54:14-07:00
Authentication code: 6789

Copy_Pixels(sx, sy, width, height, dx, dy)

Post by BrianP007 »

I have a ~256 lines of pixels with complicated colors ~800 pixels long. I need to copy each line up to a dozen times to make columns > 1 pixel wide. I will create the original lines one pixel at a time as I need to do extensive calculations on each.

Is there any way to copy a rectangular area of pixels to another area? I see:
GetAuthenticPixels geometry=>geometry, width=>integer, height=>integer, x=>integer, y=>integer return image pixels as a C pointer
This looks promising. And then:
SyncAuthenticPixels sync image pixels to pixel cache
Even in the C API, the documentation is thin and examples are scarce.

Checking the web, the same PerlMagick page is mirrored myriad times, but I find no PerlMagick user-generated pages, only a few C API references.

It seems likely that a well crafted non-overlapping memcpy would do the trick. But that would require the C API. Is there any way for PerlMagick to do the same thing?

Brian
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Copy_Pixels(sx, sy, width, height, dx, dy)

Post by magick »

There are two methods to copy pixels, use Composite() with the Copy composite operator or you can use GetAuthenticPixels() / SyncAuthenticPixels() for fast direct update access to the image pixels.
BrianP007
Posts: 49
Joined: 2013-12-13T09:54:14-07:00
Authentication code: 6789

Re: Copy_Pixels(sx, sy, width, height, dx, dy)

Post by BrianP007 »

magick wrote:PerlMagick needs a SetAuthenticPixels() for fast direct update access to the image pixels. We'll work on that. We'll also add a CopyPixels() method. However, in the mean-time you'll need to use GetPixels() / SetPixels() to copy pixels to and from an image.
For the ~18 copies, I use a short line and repeat one line per pixel up to ~900. I would like to draw 1 vertical line from pixels, then double the line for 2, then double that for 4, the double for 8 then double for 16 and slam 2 more on for 18. 5 calls after the first line instead of 17.

Leave the base row pointer on the original line and keep the right source pointer moving with the new front until > 1/2 way there. The last chunk can then be done by moving the base pointer right to the line where the source width equals the remaining destination lines! QED!

And the wider bit block transfers would give more concentrated, low level, C grind time with less Perl/interface/translation overhead time. Right now, I am looking at 6 second run time on medium output. The C program that supplies the base data from 16 bit pshop .RAW files runs in 33 milliseconds! 182:1 ratio.

Maybe I could develop in Perl and make the final version a C dragster?!

RGBA, 16 bit quanta?
BrianP007
Posts: 49
Joined: 2013-12-13T09:54:14-07:00
Authentication code: 6789

Re: Copy_Pixels(sx, sy, width, height, dx, dy)

Post by BrianP007 »

Magick,

The need was to take a line of individually colored pixels, 1 pixel wide by 900 pixels tall and copy it to the left to fill the next ~17 columns:

>> There are two methods to copy pixels, use Composite() with the Copy composite operator or you can use GetAuthenticPixels() / SyncAuthenticPixels() for fast direct update access to the image pixels. <<

The first, mandatory parameter to Composite() is a "image=>image-handle". So one would dump the current, partial picture to disk, create a png file of the one, colored line, dump it to disk and then call Composite() 17 times to overlay the line image on top of the working image; then repeat 255 times for each column. Is this how this suggested method would work?

The current point-by-point solution takes ~6 seconds all in memory. With a back of the envelope ballpark calc, performing (17*255=4335) image overlays from disk images would probably take at least 10 to 100 times longer that the pixel by pixel method. This does not sound like an improvement.

From: http://www.imagemagick.org/script/perl-magick.php ::

Use these methods to obtain direct access to the image pixels:
GetAuthenticPixels geometry=>geometry, width=>integer, height=>integer, x=>integer, y=>integer return authentic pixels as a C pointer...
SyncAuthenticPixels sync authentic pixels to pixel cache
This is 100% of the documentation on the Perl-Magick resource page at http://www.imagemagick.org/script/perl-magick.php

The C API goes into more detail about the pixel cache, but for Perl, there appears to be nothing whatever on the web. 3 Google hits for (''perlmagick perl "Create the Pixel Cache" perl perlmagick -"c api" -ruby -c++ -cpp'')

ftp://ftp.tuwien.ac.at/graphics/ImageMa ... cture.html
viewtopic.php?t=13574 -> [[ NOT PerlMagick but /usr/bin/convert called with exec() ]]
http://www.imagemagick.org/ImageMagick- ... cture.html

From 3):

Create an image from a memory based image:

image=BlobToImage(blob_info,blob,extent,exception);
if (image == (Image *) NULL)
{ /* an exception was thrown */ }

All C MagickCore api, not Perl.

Do you know of any examples on the WWW of Perl successfully using these Get/Sync pixel functions? Fred's Cool Perl Tricks?

There is only 1 hit here: >> Search found 1 match: perlmagick SyncAuthenticPixels << This thread...

Thank you,

Brian
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Copy_Pixels(sx, sy, width, height, dx, dy)

Post by magick »

Ok, we'll add a CopyPixels() method to PerlMagick in ImageMagick 6.9.1-7 likely within the next week. Call it like this:
  • $image->CopyPixels(geometry=>'100x100+10+10', dx=>110, dy=>110);
The source is the image itself or you can specific the source image like this:
  • $image->CopyPixels(source=>$mysource, geometry=>'100x100+10+10', dx=>110, dy=>110);
BrianP007
Posts: 49
Joined: 2013-12-13T09:54:14-07:00
Authentication code: 6789

Re: Copy_Pixels(sx, sy, width, height, dx, dy)

Post by BrianP007 »

magick wrote:Ok, we'll add a CopyPixels() method to PerlMagick in ImageMagick 6.9.1-7 likely within the next week. Call it like this:
  • $image->CopyPixels(geometry=>'100x100+10+10', dx=>110, dy=>110);
The source is the image itself or you can specific the source image like this:
  • $image->CopyPixels(source=>$mysource, geometry=>'100x100+10+10', dx=>110, dy=>110);
I was checking out C API reference material and a Perl ref to a C blob might work.

The Blob would be RGBA/16 serialization of C memory region XY -> ZT copied one row at a time and appended to the buffer (xy -> zy++ for rows y to t)

Unpack could make the necessary Perl data structure. The question would be does Unpack() copy the raw BLOB buffer to make the array or does it use pointers/refs? Mangling the data in Perl and seeing whether it stuck or not back in C would answer whether Perl gets a copy or the original.

If Unpack() makes a copy, could a PACK() be used to smash it back into the same memory region passed in by C? Or could the SyncAuthenticPixels() be given 2 pointers, 1 to the old data and another (optional) pointer to the new and do a memcpy to blast the new over the old?

It all depends on how the XS (eXcesS? aXcesS? ) code is written. The data structure is so trivial in C, how hard could it be to devise a simple and direct transfer of a chunk of memory back and forth to Perl?

Thx,

Brian
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Copy_Pixels(sx, sy, width, height, dx, dy)

Post by magick »

CopyPixels() is ready for testing in ImageMagick-6.9.1-7 Beta by sometime tomorrow. Let us know if you find any bugs.
BrianP007
Posts: 49
Joined: 2013-12-13T09:54:14-07:00
Authentication code: 6789

Re: Copy_Pixels(sx, sy, width, height, dx, dy)

Post by BrianP007 »

I tried to build the latest beta and I don't have the same vc++ build environment your testers use. I have the express 2010 version but use GCC for most everything. And, checking, the missing .h file is really missing. It is NOT in the zip. Turns out, it is NOT included in the free ms compiler. :( Checking, the "New Customer Price" is only $5,999 WITH MSDN! Ouch@!

From the Install-windows.txt file in the ImageMagick-6.9.1-7-windows.zip
To create a workspace for your requirements, simply go to the
VisualMagick\configure folder and open the configure.dsw workspace (for
Visual Studio 6) or configure.sln (for Visual Studio 7 or 8). Set the build
configuration to Release.

Build and execute
1>------ Build started: Project: configure, Configuration: Release Win32 ------
1> stdafx.cpp
1>d:\download\image.magick\imagemagick-6.9.1\visualmagick\configure\stdafx.h(15): fatal error C1083: Cannot open include file: 'afxwin.h': No such file or directory
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


D:\download\image.magick\ImageMagick-6.9.1\VisualMagick>find .. -name *in.h
..\glib\glib\deprecated\gmain.h
..\glib\glib\gmain.h
..\glib\gobject\gtypeplugin.h
..\lcms\include\lcms2_plugin.h
..\librsvg\tools\rsvg-tools-main.h
..\pixman\pixman\loongson-mmintrin.h
..\ttf\src\autofit\aflatin.h
..\zlib\zconf.in.h

http://stackoverflow.com/questions/5543 ... ss-edition
afxwin.h is MFC and MFC is not included in the free version of VC++ (Express Edition).
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Copy_Pixels(sx, sy, width, height, dx, dy)

Post by magick »

BrianP007
Posts: 49
Joined: 2013-12-13T09:54:14-07:00
Authentication code: 6789

Re: Copy_Pixels(sx, sy, width, height, dx, dy)

Post by BrianP007 »

I use Strawberry Perl to get the CPAN/GCC support and modules not available on Activestate. The windoz installer above is looking for Activestate which is not installed. I shutter to think of the resulting tumult from having 2 battling ports of Perl present. I will try a cmake on the source and see if I can shoehorn it in with GCC...
Post Reply