Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merge a sequence of JPEG images into a grid losslessly with FFmpeg

I have a sequence of images that are blocks of a larger image, which together make up the whole image. The blocks are the result of splitting the original image along evenly spaced horizontal and vertical lines, so they don't have weird dimensions.

Is there a way to combine them with FFmpeg (or something else like ImageMagick) without re-encoding the images?

This answer suggests the hstack or vstack FFmpeg filter, but my image blocks aren't necessarily the full width or the full height of the original image.


Like this:

Six blocks of differing sizes in a 3-row, 2-column grid

Perhaps this could be achieved with multiple FFmpeg commands using hstack or vstack (I'd prefer just one command though). Or with a complex filter?


e.g. Mona Lisa split into six distinct blocks, then arranged together


Edit: I tried using filter_complex with FFmpeg:

ffmpeg -i 0.jpg -i 1.jpg -i 2.jpg -i 3.jpg -i 4.jpg -i 5.jpg \
-filter_complex "[0][1]hstack=inputs=2[row 0]; \
                 [2][3]hstack=inputs=2[row 1]; 
                 [4][5]hstack=inputs=2[row 2]; 
                 [row 0][row 1][row 2]vstack=inputs=3[out]" \
-map "[out]" -c copy out.jpg

but it can't filter and copy streams at the same time.

like image 537
Mody Avatar asked Oct 26 '25 07:10

Mody


2 Answers

You can do that with ImageMagick. However, it will decompress and recompress your jpg files. You will lose some quality.

Unix Syntax for IM 6:

convert \
\( 0.jpg 1.jpg +append \) \
\( 2.jpg 3.jpg +append \) \
\( 4.jpg 5.jpg +append \) \
-append \
mona_lisa.jpg


If using Windows remove the \ from the parentheses and replace the end of line \ with ^.

If using IM 7, replace convert with magick.

like image 89
fmw42 Avatar answered Oct 29 '25 03:10

fmw42


I found an interesting patch from 2010 against libjpeg which adds this feature to jpegtran. It won't split blocks, so your images will need to be multiples of 8 or even 16 pixels in each axis.

Unfortunately it's against the libjpeg 6b as distributed for ubuntu10. This includes some patches from 8d and doesn't really correspond neatly to any official libjpeg version (as far as I can see).

You need to download the ubuntu10.04 sources, extract their libjpeg, and patch that. The steps are:

wget http://old-releases.ubuntu.com/releases/releases/10.04/release/source/ubuntu-10.04-src-1.iso

Now open that ISO and pull out the files from ubuntu/pool/main/libj/libjpeg6b. Archive Manager can do this, perhaps there's some scriptable tool as well.

Now run:

# original sources
tar xf libjpeg6b_6b.orig.tar.gz
cd jpeg-6b

# apply ubuntu patches
zcat ../libjpeg6b_6b-15ubuntu1.diff.gz | patch

# apply jpegtran patches
patch < ../append-jpeg6b.patch

./configure
make
sudo make install

That will install the modified jpegtran to /usr/local.

Given 0.jpg and 1.jpg:

enter image description here

You can run it like this:

jpegtran -appright 1.jpg 0.jpg > join.jpg

To make:

enter image description here

like image 34
jcupitt Avatar answered Oct 29 '25 03:10

jcupitt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!