Hello
I'm interested to know if there's a feature (or a set of combined features) that allows to merge four images into one, pixel by pixel, as shown in this simplified scheme:
Input images (A,B,C,D):
A(1,1) A(2,1)
A(1,2) A(2,2)
B(1,1) B(2,1)
B(1,2) B(2,2)
C(1,1) C(2,1)
C(1,2) C(2,2)
D(1,1) D(2,1)
D(1,2) D(2,2)
Output image:
A(1,1) B(1,1) A(2,1) B(2,1)
C(1,1) D(1,1) C(2,1) D(2,1)
A(1,2) B(1,2) A(2,2) B(2,2)
C(1,2) D(1,2) C(2,2) D(2,2)
The idea is graphically (and better) shown in the following page as well:
http://casu.ast.cam.ac.uk/surveys-proje ... terleaving
I've been an IM user for a few years, and I've read again through the features' lists, but I couldn't find anything like this. Perhaps there's a loose analogy with interpolation algorithms, but this would be done with real data. I know that Fred Weinhaus wrote a script called "interleave", but it doesn't seem to be what I'm looking for.
I'm using ImageMagick 6.9.4-9 on Slackware Linux.
Thank you.
Best regards
Andrew
Merging images into one (pixel by pixel / interleaving)
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: Merging images into one (pixel by pixel / interleaving)
Someone may leap in with an intelligent way to do this. Meanwhile, here is a dumb method.
I assume A,B,C,D are the same sizes.
We make the final image from 4 images, composited over each other. The bottom layer is image A scaled by 200%, so each pixel is spread over 2x2 pixels.
The other 3 layers have one pixel each in every group of 2x2 pixels. How do we make these? The magic words are: "crop, splice, append". Here's an example, Windows BAT syntax (adjust for bash):
r.png has transparent pixels, except for the bottom-right in each group. With suitable gravity settings, the used pixel is in the other positions.
Does that supply enough details?
I assume A,B,C,D are the same sizes.
We make the final image from 4 images, composited over each other. The bottom layer is image A scaled by 200%, so each pixel is spread over 2x2 pixels.
The other 3 layers have one pixel each in every group of 2x2 pixels. How do we make these? The magic words are: "crop, splice, append". Here's an example, Windows BAT syntax (adjust for bash):
Code: Select all
convert ^
rose: ^
-background None ^
-crop 0x1 -splice 0x1 -append ^
-crop 1x0 -splice 1x0 +append ^
r.png
Does that supply enough details?
snibgo's IM pages: im.snibgo.com
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: Merging images into one (pixel by pixel / interleaving)
I believe another approach might be to scale 2x2 each image. Then create a black/white mask of a grid every other pixel. This can be rolled for each image appropriately and put into the alpha channel of each image. Then flatten the resulting images. I do something like this in my script, interleave at the link below for different images or for the channels of one image, but currently only in one dimension, not both.
Re: Merging images into one (pixel by pixel / interleaving)
Thank you very much for your valuable inputs.
Yes, I forgot to specify that A,B,C,D have exactly the same size. You both helped me to figure out a solution: it works, now I'll have to refine it. Basically I did it in three steps, using crop, append, and "for" loops:
1) Merge A and C vertically: -crop and -append the whole lines to an intermediate output.
2) The same as in 1), but with B and D, to a second intermediate output.
3) Merge both outputs horizontally: -crop and +append the whole columns to the final image.
I think I'll explore Fred's idea further (scaling, masking and flattening), which sounds like it might be faster than processing the images line by line. My IM skills are still very basic, but I hope I'll find some time to further climb the learning curve.
Thanks again!
Yes, I forgot to specify that A,B,C,D have exactly the same size. You both helped me to figure out a solution: it works, now I'll have to refine it. Basically I did it in three steps, using crop, append, and "for" loops:
1) Merge A and C vertically: -crop and -append the whole lines to an intermediate output.
2) The same as in 1), but with B and D, to a second intermediate output.
3) Merge both outputs horizontally: -crop and +append the whole columns to the final image.
I think I'll explore Fred's idea further (scaling, masking and flattening), which sounds like it might be faster than processing the images line by line. My IM skills are still very basic, but I hope I'll find some time to further climb the learning curve.
Thanks again!
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: Merging images into one (pixel by pixel / interleaving)
I think snibgo's approach might be faster, since it is likely easier to do your 3 steps in one command line. You can use parentheses processing for each step so that you do not have to save to disk the intermediates.
See http://www.imagemagick.org/Usage/basics/#parenthesis
See http://www.imagemagick.org/Usage/basics/#parenthesis
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: Merging images into one (pixel by pixel / interleaving)
Create four test images (Windows BAT syntax, IM v6):
Use the "crop, splice, append" method:
This takes about 7 seconds.
Use the rolling mask method:
This takes about 2 seconds.
The results from the two methods are identical, of course. I expect other methods are possible.
Less memory would be used if we did a "-compose Over -composite" after each stage, instead of a single "-layers merge" at the end. This is important if the images are large, eg 7500x5000 pixels.
Code: Select all
%IM%convert ^
-size 1000x750 ^
gradient:red-black +write a.png +delete ^
gradient:yellow-black +write b.png +delete ^
gradient:lime-black +write c.png +delete ^
gradient:blue-black d.png
Code: Select all
%IM%convert ^
-background None ^
( a.png ^
-scale 200%% ^
)^
( b.png ^
-gravity SouthWest ^
-crop 0x1 -splice 0x1 -append ^
-crop 1x0 -splice 1x0 +append ^
) ^
( c.png ^
-gravity NorthEast ^
-crop 0x1 -splice 0x1 -append ^
-crop 1x0 -splice 1x0 +append ^
) ^
( d.png ^
-gravity NorthWest ^
-crop 0x1 -splice 0x1 -append ^
-crop 1x0 -splice 1x0 +append ^
) ^
-layers merge ^
interleave_csa.png
Use the rolling mask method:
Code: Select all
%IM%convert ^
-size 2x2 -fill White ^
xc:Black -draw "point 1,0" ^
+write mpr:MSK_2x2 +delete ^
a.png ^
-scale 200%% ^
( +clone ^
-tile mpr:MSK_2x2 -draw "color 0,0 reset" ^
+write mpr:MSK_BIG +delete ^
) ^
( b.png ^
-scale 200%% ^
mpr:MSK_BIG ^
-compose CopyOpacity -composite ^
) ^
( c.png ^
-scale 200%% ^
( mpr:MSK_BIG -roll +1+1 ) ^
-compose CopyOpacity -composite ^
) ^
( d.png ^
-scale 200%% ^
( mpr:MSK_BIG -roll +0+1 ) ^
-compose CopyOpacity -composite ^
) ^
-compose Over -layers merge ^
interleave_rm.png
The results from the two methods are identical, of course. I expect other methods are possible.
Less memory would be used if we did a "-compose Over -composite" after each stage, instead of a single "-layers merge" at the end. This is important if the images are large, eg 7500x5000 pixels.
snibgo's IM pages: im.snibgo.com
Re: Merging images into one (pixel by pixel / interleaving)
I tried both methods, and they both work very well. I wasn't aware of the possibility to use parenthesis in the IM syntax. I can also confirm the timings - 7.1s vs 2.6s on my machine - whereas my trivial line-by-line method took more than 15 minutes to complete.
Problem solved: your help was highly appreciated. Thanks again for your time.
Problem solved: your help was highly appreciated. Thanks again for your time.