How to get the result of an ImageMagick convert command as bitmap data - imagemagick

I am working on a project that will make a jigsaw puzzle from an image and present it to the user as separate pieces in a browser. I have done all the prototyping in Python. At the moment I can produce separate images for each puzzle piece.
As a last step I want to make a nice bevel on the pieces to make them look realistic. I found a ImageMagick convert command to do that just fine:
convert piece.png -alpha extract -blur 0x2 -shade 120x30 piece.png -compose Overlay -composite piece.png -alpha on -compose Dst_In -composite result.png
I execute the command by using os.system, but this is taking way too long to complete.
Can you give me an advice on a solution to execute the ImageMagick processing in the fastest way? I think that would involve executing the processing directly with the ImageMagick libraries, sending it the input bitmap data and receiving the result also as bitmap data. Then I can stream the result to user. The solution does not have to be Python.

Update
I have just been looking at your command again - I kind of assumed it was sensible as you implied you got it from Anthony Thyssen's excellent ImageMagick Usage pages - however I see you are reading the image piece.png three times which it must be possible to avoid by using -clone or -write MPR:save. Let me experiment some more. I haven't got your jigsaw piece to test with, so I am in the dark here, but you must be able to change your command to something like this:
convert piece.png -write mpr:piece \
\( +clone -alpha extract -blur 0x2 -shade 120x30 \) \
-compose Overlay -composite \
mpr:piece -alpha on -compose Dst_In -composite result.png
MPR is a Memory Program Register, or basically a named lump of RAM that ImageMagick can read and write to. There are details and examples here.
Original Answer
Three things spring to mind... which one, or which combination of things, will help depends on the specification of your CPU, memory and disks as well as the sizes of your pieces - none of which I know or can test,
Firstly, if you used the libraries, you would avoid the overhead of creating a new process to run the convert - so that should help, but if your pieces are large and the bottleneck is actually the processing, using the libraries will make little difference.
Secondly, if your images are large, the time to read them in off disk and write them back to disk may be what is killing your performance. To test this, I would create a small RAMdisk and store the images on there and see if that helps. It is a quick and relatively easy test.
Thirdly, I assume you are generating many pieces and you currently do them one after the other in a sequential fashion. If this is the case, I would definitely recommend going multi-threaded. Either do this in your code with your language's threading environment, or try out GNU Parallel which has always been brilliant for me. So, if you were going to do
convert piece1.png -alpha extract ... -composite result1.png
convert piece2.png -alpha extract ... -composite result2.png
convert piece3.png -alpha extract ... -composite result3.png
...
convert piece1000.png -alpha extract ... -composite result1000.png
just either send all those commands to GNU Parallel on its stdin and it will execute them all in parallel on as many cores as your CPU has like this
(
echo convert piece1.png ... -composite result1.png
echo convert piece2.png ... -composite result2.png
echo convert piece3.png ... -composite result3.png
) | parallel
or build the command like this
parallel convert {} -alpha ..... result-{} ::: piece*.png

Related

Imagemagick - Getting the usable dimension of an image

I've a process which is creating a file with convert (ImageMagick) based on some parameter, and after that it checks the file and gives back the biggest dimension of it which has real pixels.
The commands look like this:
convert -size 5000x5000 xc:white -font {font} -pointsize {size} -fill black -draw "{some_occassional_additional_parameter}text 200,2500 \"{text}\"" {some_other_occassional_additional_parameter}{temporary_file}
convert {temporary_file}.png -trim +repage -format "%[w]x%[h]\n" info:
. It'll result something like: 526x425
This process runs half a million time per day, and it seems to be a huge bottleneck. I'm looking for a solution which can done this in memory, so not always creating a file and check it, but do it in memory somehow.
If can speed it up just like 50%, that'd be a huge achievement.
Thank You
Not at a computer to test, but change your first command to:
convert -size ... xc:... occasionalstuff -format "%#" info:
Note that you can, and probably should double quote the "%#" especially if you use expressions containing characters of significance to the shell, though it is not strictly necessary in this specific case.

Apply imagemagick transformation on only part of an image, whilst keeping the rest "stock"?

I have many documents per day that are photographed and I need to organise by QR code. The problem is, zbarimg is struggling to pick up many of the QR codes in the photos, so I have been trialling processing them with imagemagick first, using morphology open, thesholding, etc, which has yielded much better results.
The only issue with this is these apply to the whole image, which makes the rest of the file unusable for me, as I deal with the rest of the image based on colours and information which all gets destroyed in the processing. Could anybody give me an example on how I could apply my imagemagick filters to only a part of an image (coordinate based is fine) and leave the rest of the image untouched, so I can continue my process? I will be applying this to all images in a folder, so it's a batch file running this for me in most instances.
I have tried using crops, however this obviously leaves me with only the cropped portion of the image, which doesn't actually help when trying to process the rest of the file.
I'm running my scripts on Windows 11, if that means anything in terms of the solution.
Many thanks!
Tom
EDIT:
Thank you all for the advice given!
I solved my problem using the following:
convert a.jpg ( -clone 0 -fill white -colorize 100 -fill black -draw "polygon 500,300 500,1500 1300,1500 1300,300" -alpha off -write mpr:mask +delete ) -mask mpr:mask +repage -threshold 50% -morphology open square:4 +mask c.jpg
I did post this as an answer, but (and I have no idea why, I'm brand new to stack exchange) my answer was deleted. I used the clone to make the mask with the coordinates needed, then added the threshold and morphology that would make my QR codes more legible!
Thanks again everyone, really helped me out on my journey to figure it out :D
You can use -region to specify a region to process. So starting with this:
You can then specify a region to colorise with blue and then change the region to blur part of the blue and part of the original:
magick swirl.jpg -region 100x100+50+50 -fill blue -colorize 100% -region 100x100+100+100 -blur x20 result.png
The solution using -region may be the most direct. In ImageMagick versions where -region is not supported the same result can usually be achieved by cropping and modifying a clone inside parentheses.
magick swirl.jpg ( +clone -crop 100x100+50+50 -fill blue -colorize 50 ) -flatten result.png
The cloned, cropped, and and modified piece maintains its original geometry, so the -flatten operation puts it back where it was on the input image after the parentheses.

Compose multiple regions of an image into a target

I'm trying to use ImageMagick to compose different pieces of a rendered PDF into a target. E.g., I want to have ImageMagick render the PDF at 300dpi, then create a 300x400 pixel output image, then take from the PDF the area 10x20+30+40 and place it in the target (300x400 pixel image) at 12,34. Then take another (and a third and fourth) chunk at different coordinates with different sizes and place them at different places.
I cannot seem to figure out how to do this in one go, and doing it in multiple runs always re-renders the PDF and takes awfully long. Is this even possible?
Here's an idea of how you can approach this. It uses the MPR or "Memory Program Register" that Fred suggested in the comments. It is basically a named chunk of memory that I write into at the start and which I recall later when I need it.
Here is a rather wonderful start image from the Prokudin-Gorskii collection:
The code resizes the image and saves a copy in the MPR. Then, takes a copy of the MPR, crops out a head, resizes it and composites the resized result onto the resized original at a different location and then repeats the process for another head.
magick Prokudin.png -resize 300x400\! -write MPR:orig \
\( MPR:orig -crop 50x50+180+84 -resize 140x140 \) -geometry +10+240 -compose src-over -composite \
\( MPR:orig -crop 40x40+154+184 \) -geometry +40+100 -compose src-over -composite \
result.png
If you have trouble understanding it, try running it with the second or third line omitted so it just does one head ;-)
Hopefully it covers all the aspects of your question and you can adapt it to your PDF.

imagemagick - Restrict elaboration to a region of the image

I need to process a large amount of scans of dot matrix printed documents in order to optimize them for reading with an ocr engine.
I used imagemagick to make sure that there are no white spaces between the points of the matrix, so the ocr engine works much better. The problem is performance, pdfs are scanned at 600dpi and processing takes too long. I would like to limit the processing only to the area affected by the zonal ocr, I tried with the "-region" operator but even if it works, the processing takes the same time.
This is the command used by the windows command line:
convert -density "601.6x600" -units pixelsperinch -monochrome files\1.pdf -region 2000x200+2500+2100 -negate -morphology Thinning "17x17+8+8: -,-,-,-,-,0,0,0,0,0,0,0,-,-,-,-,- -,-,-,-,0,0,0,0,0,0,0,0,0,-,-,-,- -,-,-,0,0,0,0,0,0,0,0,0,0,0,-,-,- -,-,0,0,0,0,-,-,-,-,-,0,0,0,0,-,- -,0,0,0,0,-,-,-,-,-,-,-,0,0,0,0,- 0,0,0,0,-,-,-,-,-,-,-,-,-,0,0,0,0 0,0,0,-,-,-,-,-,-,-,-,-,-,-,0,0,0 0,0,0,-,-,-,-,-,-,-,-,-,-,-,0,0,0 0,0,0,-,-,-,-,-,1,-,-,-,-,-,0,0,0 0,0,0,-,-,-,-,-,-,-,-,-,-,-,0,0,0 0,0,0,-,-,-,-,-,-,-,-,-,-,-,0,0,0 0,0,0,0,-,-,-,-,-,-,-,-,-,0,0,0,0 -,0,0,0,0,-,-,-,-,-,-,-,0,0,0,0,- -,-,0,0,0,0,-,-,-,-,-,0,0,0,0,-,- -,-,-,0,0,0,0,0,0,0,0,0,0,0,-,-,- -,-,-,-,0,0,0,0,0,0,0,0,0,-,-,-,- -,-,-,-,-,0,0,0,0,0,0,0,-,-,-,-,-" -morphology Thinning "13x13+6+6: -,-,0,0,0,0,0,0,0,0,0,-,- -,0,0,0,0,0,0,0,0,0,0,0,- 0,0,0,-,-,-,-,-,-,-,0,0,0 0,0,-,-,-,-,-,-,-,-,-,0,0 0,0,-,-,-,-,-,-,-,-,-,0,0 0,0,-,-,-,-,-,-,-,-,-,0,0 0,0,-,-,-,-,1,-,-,-,-,0,0 0,0,-,-,-,-,-,-,-,-,-,0,0 0,0,-,-,-,-,-,-,-,-,-,0,0 0,0,-,-,-,-,-,-,-,-,-,0,0 0,0,0,-,-,-,-,-,-,-,0,0,0 -,0,0,0,0,0,0,0,0,0,0,0,- -,-,0,0,0,0,0,0,0,0,0,-,-" -morphology Close Disk -negate -compress zip r.pdf
P.S. I wanted to post on the imagemagick forum, but I didn't find the link to subscribe ...
Issue is resolved here https://github.com/ImageMagick/ImageMagick/discussions/2841.
the -region param appears to act after the processing of entire file. Fixed using clone, crop, layer and flatten:
magick in.tiff ( +clone -crop 100x100+500+500 -morphology dilate disk ) -layers flatten x2.tiff

ImageMagick multiple operations in single invocation

I'm trying to get ImageMagick to perform multiple operations (in this case, crops) in a single invocation, but it doesn't seem to be possible. For example, I can do a crop, rotate, and then another crop as two separate commands:
$ convert test.jpg -crop 223x187+588+757 -rotate 330 crop2.jpg
$ convert crop2.jpg -crop 200x100+43+87 crop3.jpg
But if I try to combine them into a single command, I get an error:
$ convert test.jpg -crop 223x187+588+757 -rotate 330 -crop
200x100+43+87 crop3.jpg
convert: geometry does not contain image `test.jpg' # warning/transform.c/CropImage/666.
Obviously I could just create a pipe, but if possible I want to avoid the extra overhead of multiple processes. Is there a way to do this?
Update:
Also, a pipe seems problematic: I don't want an extra compress/decompress stage so I try piping it as RGB, but I can't seem to get the parameters right:
convert test.jpg -crop 223x187+588+757 -rotate 330 rgb:- | convert -size 287x273 -depth 8 rgb:- -crop 200x100+43+87 crop3.jpg
convert: unexpected end-of-file `-': No such file or directory # error/rgb.c/ReadRGBImage/231.
Ok, so it turns out the above error is because my calculated size for the image differs from ImageMagick's calculations by two pixels. So obviously having to try to get the image size calculation exactly the same as IM is an extra problem introduced by the need to pipeline the two commands.
Here is a more generic approach to the question.
ImageMagick provides a few clever tricks which can help to optimize processing speed when...
...you want to process large images and
...when you want to create different output from the same original.
There are different methods which can even be combined:
Take advantage of ImageMagick's special mpr:{label} format and syntax.
This tells ImageMagick to temporarily save the input image into a named magick program register label.
(I've also seen it explained as magick persistent (memory) register or memory program register.)
The command pipeline can then later (while processing) read the image data much faster from there than it could read from harddisk.
And the command can read it as often as you want, multiple times.
Take advantage of ImageMagick's special mpc:{name} format and syntax.
This works similar to mpr:.
Its long name is magick pixel cache.
I've also seen it as magick persistent (disk) cache.
MPC is the native in-memory uncompressed file format of ImageMagick, but dumped to disk.
Once written to disk, it can be re-read faster into memory again than a JPEG, TIFF or PNG could, because no conversion is needed.
Construct a clever command sequence.
Make use of "sideway" processing, using the \( ... \) syntax in escaped parentheses where appropriate.
MPC
When the convert command reads input image (JPEG, TIFF, GIF, PNG... whatever format it may currently be), it first processes this format into an MPC.
This processed result is kept in RAM as an uncompressed raster format.
From there the further conversions and image manipulations happen.
When you want write an MPC to disk as MPC you can use +write mpc:myfilename.
This basically is simply a direct memory dump to disk.
ImageMagick then writes two, not one, (and larger than usual) binary files: myfilename.mpc and myfilename.cache.
The .mpc file holds the metadata of the image, .cache holds the actual pixel cache data.
A read from this disk file(s) is a fast memory map from disk to memory as needed (similar to memory page swapping).
But since the initial +write operation did store the native uncompressed internal, IM-native raster format, now no image decoding is needed.
So this can be faster (especially for large images) to use, IF you cannot avoid writing temporary files out which you need to read in again.
However, be careful with your disk space.
Remember to clean up, once you no longer need the MPC file on disk.
IM will not automatically track your +write commands for you.
(More technical details: MPC as a disk file format is not portable.
It also isn't suitable as a long-term archive format.
Its only suitability is as an intermediate format for high-performance image processing.
It requires two files to support one image.
It is not guaranteed to be 'stable' in between ImageMagick releases.
It may not work on a different machine from the one where you created it.)
If you still want to save this format to disk, remember this:
Image attributes are written to a file with the extension .mpc.
Image pixels are written to a file with the extension .cache.
MPC's main advantages lay in...
...processing very large images, or when
...applying several operations on one and the same image in "operation pipelines".
MPC was designed especially for workflow patterns which match the criteria "read many times, write once".
MPR
The MPR format (memory persistent register) does something similar as MPC.
It makes the image available via a named memory register.
You can use whatever name you want (even numbers).
Your process pipeline can also read the image again from that register -- multiple times even, should it need to do so.
The image mpr:label persists in the register until the current command pipeline exits. (This is the difference to a to-disk-written mpc:filename. This persists the completion of the current pipeline; it even survives system reboots.)
Clever command pipeline
(My use of the word 'pipeline' here is not to be confused with the pipelines in a shell, where multiple commands and processes are started and chained.
Here I talk only about a single invocation of convert which chains multiple image manipulations and operations into one process.)
So it is possible to accomplish all resize, crop, append, thumbnailing, color-manipulating, blurring, ... what-have-you operations in one single process writing out the different intermediate outputs you require.
Practical example...
...hmm, I'm not so sure if it is soooo practical. I haven't tested it, I just used my phantasy to construct an example which shows the principles about the usage of the different concepts.
Note: +write someimage is the same as -write someimage +delete.
convert \
very-very-large.jpg \
-write mpr:XY \
+delete \
-respect-parentheses \
\( mpr:XY -crop '3000x2001+0+491' -resize '170x116!>' +write pic1.png \) \
\( mpr:XY -crop '2981x2883+8+0' -resize '75x75!>' +write pic2.png \) \
\( mpr:XY -crop '1100x1983+0+0' -resize '160x160!>' +write pic3.png \) \
\( mpr:XY -crop '2000x2883+0+0' -resize '1024x960!>' +write pic4.png \) \
\( mpr:XY -crop '1000x2883+0+0' -resize '190x188!>' +write mpr:pic5 \) \
\( mpr:pic5 +write pic5.png \) \
\( mpr:XY -crop '3000x2000+0+0' -resize '2048x2047!>' +write pic6.png \) \
\( mpr:XY -crop '3000x2883+0+0' -resize '595x421!>' +write pic7.png \) \
\( mpr:XY -crop '3000x2883+0+0' -resize '3000x2883!>' +write mpr:AB \) \
\( mpr:AB +write pic8.tiff \) \
\( mpr:AB -blur 0x8 +write blur1.gif \) \
\( mpr:pic5 mpr:AB +append mpr:pic5 -append +write append.jpg \) \
\( mpr:pic5 -rotate -130 mpr:AB -gravity center \
-compose difference -composite +write final.png \) \
null:
After the first operation, -write mpr:XY, there are two images in the stack:
the input file, very-very-large.png, and
a copy of it which can be read from memory using its label XY.
We do not need the first of these two any more.
Hence we use +delete to remove it from the stack.
So this command used one single command pipeline which carried out multiple commands and manipulations creating 11 different output images in one go:
pic{1,2,3,4,5,6,7}.png, blur1.gif, pic8.tiff, append.jpg and final.png.
Quick'n'dirty answer: Insert a +repage into your first single command:
convert test.jpg \
-crop 223x187+588+757 \
-rotate 330 \
+repage \
-crop 200x100+43+87 \
crop3.jpg
Long and comprehensive answer: Will follow later. I have to complete another task first. The long answer will give you a more generic approach, how you can crop multiple sections in one single command, while keeping up performance.

Resources