How to Use Stdin with Caption in Imagemagick

Proper syntax for STDIN/STDOUT in imagemagick

I would try doing the first trim of the edges using -fuzz (to allow for small differences in the border colour) and -trim. That gets you this:

convert grid.png -fuzz 30% -trim trimmed.png

Then, I would tile to 4x3 and repage the images so they forget their positions in the original image:

convert trimmed.png -crop 4x3@ +repage step2.png

Now crop off the tops, bottoms and sides and save the individual 12 frames:

convert step2.png -crop 130x100+20+20 f-%02d.png

Now you can trim the excess, using a slightly different fuzz as there seems to be less variation here than in the outer edge of the original image. And, I have also put all the commands together in one that does all the steps for all 12 images in one go:

convert grid.png -fuzz 30% -trim -crop 4x3@ +repage -crop 130x100+20+20 -fuzz 5% -trim f-%02d.png

You may have to play with the fuzz factor for other images, but you should see how it works now.

convert multiple pngs to bmps from stdin to stdout

As Fred (@fmw42) says, you cannot do this with ImageMagick alone, but it should be possible to do something with a small C/C++, Perl, PHP or Python script.

Basically, PNG files are nicely "chunked", see Wikipedia PNG Specification, and each chunk has a type - such as IHDR (header), PLTE (palette), IDAT (image data), IEND (end of file marker) and, crucially, a length in bytes.

So, you could write a script/program that reads data off your pipe, gets the chunks and appends them to an in-memory string and keeps doing so until it reaches an IEND chunk. At that point it would either use ImageMagick or GD or Pillow to convert the in-memory string into a BMP and write it to a further pipe, or write the string to a pipe that ImageMagick was reading from and let ImageMagick convert the file. You would then zero out the accumulated (PNG) string and start reading the next file.

I don't feel like writing and debugging all that for 15 points, but it would look something like this:

chrome-cast | demultiplex

where demultiplex would be like:

while not error
clear accumulated string of PNG data
done = false
while not done
read chunk type and length of chunk
read whole chunk and append to accumulated string of PNG data
if chunk = IEND
pass accumulated PNG string to ImageMagick to make BMP
done = true
endif
end
end

Note that your program would not have to "understand" all the chunk types or their contents - just recognise the chunk length and the IEND chunk when it arrives.


Note that you may like to run pngcheck or pngsplit to get started in understanding how PNG files are structured in chunks - they are here. In fact, pngsplit may do what you want anyway.

Here is an example of pngcheck in action:

pngcheck -v file.png

File: file.png (462308 bytes)
chunk IHDR at offset 0x0000c, length 13
800 x 468 image, 32-bit RGB+alpha, non-interlaced
chunk gAMA at offset 0x00025, length 4: 0.45455
chunk cHRM at offset 0x00035, length 32
White x = 0.3127 y = 0.329, Red x = 0.64 y = 0.33
Green x = 0.3 y = 0.6, Blue x = 0.15 y = 0.06
chunk bKGD at offset 0x00061, length 6
red = 0x00ff, green = 0x00ff, blue = 0x00ff
chunk pHYs at offset 0x00073, length 9: 3779x3779 pixels/meter (96 dpi)
chunk tIME at offset 0x00088, length 7: 2 Oct 2017 21:34:26 UTC
chunk IDAT at offset 0x0009b, length 32768
zlib: deflated, 32K window, maximum compression
chunk IDAT at offset 0x080a7, length 32768
chunk IDAT at offset 0x100b3, length 32768
chunk IDAT at offset 0x180bf, length 32768
chunk IDAT at offset 0x200cb, length 32768
chunk IDAT at offset 0x280d7, length 32768
chunk IDAT at offset 0x300e3, length 32768
chunk IDAT at offset 0x380ef, length 32768
chunk IDAT at offset 0x400fb, length 32768
chunk IDAT at offset 0x48107, length 32768
chunk IDAT at offset 0x50113, length 32768
chunk IDAT at offset 0x5811f, length 32768
chunk IDAT at offset 0x6012b, length 32768
chunk IDAT at offset 0x68137, length 32768
chunk IDAT at offset 0x70143, length 3115
chunk tEXt at offset 0x70d7a, length 37, keyword: date:create
chunk tEXt at offset 0x70dab, length 37, keyword: date:modify
chunk IEND at offset 0x70ddc, length 0
No errors detected in file.png (24 chunks, 69.1% compression).

I did a rudimentary version of the PNG chunking in Perl for another answer, so have a quick look here.

What is the correct way to handle apostrophes in text in ImageMagick

You can avoid all issues with escaping and quoting by feeding the annotation text into ImagMagick from a file or from stdin. So, if you create a file, called say "annotation.txt" that contains:

Weird stuff with ', @ and ".

You can tell ImageMagick to read the annotation from that file (using @filename) and place it on your image like this:

magick -size 640x240 xc:magenta -gravity center -pointsize 32 -annotate -40+90 @annotation.txt result.png

Sample Image


Likewise, if you want to pump the annotation into ImageMagick from some other command, you can tell ImageMagick to read its stdin like this:

echo "Whatever @ '" | magick -size 640x240 xc:magenta -gravity center -pointsize 32 -annotate -40+90 @- result.png

Sample Image


As Fred kindly reminded me in the comments, you would need to ensure your policy.xml file permits this. Its location can be found with:

identify -list configure | grep CONFIGURE_PATH

More discussion about how to edit and security implications here.

IMAGEMAGICK: Filling when label contains blanks

I don't know why it does that, but you can generate the text you want by replacing the space with a UTF non-breaking space and sending that to the stdin of convert and asking -label to read its text from the "file" called stdin:

printf "DYMO\xc2\xa0FONT" | 
convert -background white -fill DarkRed -font DYMO -pointsize 72 label:@- result.png

Sample Image

Add -trim just before the output filename if you want the extraneous white space trimmed off from around the edges.

If you had more complicated text and didn't want to do that for all spaces, you could replace spaces using a short piece of Perl or sed to do it for you...

echo -n "Text with lots of spaces." | sed 's/ /\xC2\xA0/g' | convert -background white -fill DarkRed -font dymo -pointsize 72 label:@- -trim label.png

Sample Image

Powershell with Image Magick Montage reading from text file

Thanks everyone for your ideas and help. While I wasn't able to use any of the provided ideas it allowed me to think up a simple solution.

I simply removed the need to read a text file by targeting the files directly:

montage -verbose -label %t -pointsize 25 -background '#FFFFFF' -tile 24x5 -fill 'black' -define jpeg:size=600x780 -geometry 600x780+40+150 -quality 90 -auto-orient E:\Output\*.jpg E:\Contact_Sheet.jpg

Although I would have liked to solve the problem instead of developing a work around, my script is now working.

Send args to subprocess while using stdin

In linux you can use /dev/stdin as file name but it does not work all the times. If it does not work with visgrep, you must use a temporary file (which is not a shame).

PS. shouldn't png: be png:-?

Use exiv2 or imagemagick to remove EXIF data from stdin and output to stdout

Using exiv2

I was not able to find a way to get exiv2 to output to stdout -- it only wants to overwrite the existing file. You could use a small bash script to make a temporary file and get the md5 hash of that.

image.sh:

#!/bin/bash
cat <&0 > tmp.jpg # Take input on stdin and dump it to temp file.
exiv2 rm tmp.jpg # Remove EXIF tags in place.
md5sum tmp.jpg # md5 hash of stripped file.
rm tmp.jpg # Remove temp file.

You would use it like this:

cat image.jpg | image.sh

Using ImageMagick

You can do this using ImageMagick instead by using the convert command:

cat image.jpg | convert -strip - - | md5sum

Caveat:

I found that stripping an image of EXIF tags using convert resulted in a smaller file-size than using exiv2. I don't know why this is and what exactly is done differently by these two commands.

From man exiv2:

rm        Delete image metadata from the files.

From man convert:

-strip        strip image of all profiles and comments

Using exiftool

ExifTool by Phil Harvey

You could use exiftool (I got the idea from https://stackoverflow.com/a/2654314/3565972):

cat image.jpg | exiftool -all= - -out - | md5sum

This too, for some reason, produces a slightly different image size from the other two.

Conclusion

Needless to say, all three methods (exiv2, convert, exiftool) produce outputs with different md5 hashes. Not sure why this is. But perhaps if you pick a method and stick to it, it will be consistent enough for your needs.

ImageMagick convert from GRAY to TIFF using stdin

You just have the STDIN and format flipped. "-:gray" should be "gray:-"

cat imageTemp.gray | 
convert -size 1024x1024 \
-depth 14 \
-endian MSB gray:- /tmp/bla.tiff

To answer why this is happening. We can run your previous command with a -verbose switch.

cat imgTemp.gray | \
convert -verbose \
-size 1024x1024 \
-depth 16 \
-endian MSB -:gray /tmp/bla.tiff

This will give use an additional line of information that explains what ImageMagick is trying to do

convert: unable to open image `gray':
No such file or directory @ error/blob.c/OpenBlob/2638.
convert: no decode delegate for this image format
`gray' @ error/constitute.c/ReadImage/550.
convert: no images defined `bla.tiff' @ error/convert.c/ConvertImageCommand/3078.

Convert command becomes confused with -:gray and tries to open a blob file entitled "gray", and eventually attempts to open "bla.tiff" as a source image. Both of them non-existing on the filesystem.



Related Topics



Leave a reply



Submit