Merging images into one (pixel by pixel / interleaving)

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
ilsland
Posts: 3
Joined: 2016-09-06T04:57:11-07:00
Authentication code: 1151

Merging images into one (pixel by pixel / interleaving)

Post by ilsland »

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
snibgo
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)

Post by snibgo »

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):

Code: Select all

convert ^
  rose: ^
  -background None ^
  -crop 0x1 -splice 0x1 -append ^
  -crop 1x0 -splice 1x0 +append ^
  r.png
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?
snibgo's IM pages: im.snibgo.com
User avatar
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)

Post by fmw42 »

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.
ilsland
Posts: 3
Joined: 2016-09-06T04:57:11-07:00
Authentication code: 1151

Re: Merging images into one (pixel by pixel / interleaving)

Post by ilsland »

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!
User avatar
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)

Post by fmw42 »

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
snibgo
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)

Post by snibgo »

Create four test images (Windows BAT syntax, IM v6):

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
Use the "crop, splice, append" method:

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
This takes about 7 seconds.

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
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.
snibgo's IM pages: im.snibgo.com
ilsland
Posts: 3
Joined: 2016-09-06T04:57:11-07:00
Authentication code: 1151

Re: Merging images into one (pixel by pixel / interleaving)

Post by ilsland »

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.
Post Reply