How can I make ImageMagick respect colour profiles in a composite operation? - imagemagick

I have a script that uses ImageMagick to composite two images together. It worked fine with ImageMagick v6, but outputs broken images with v7 (ImageMagick 7.0.8-68 Q16 x86_64 2020-01-14 on macOS, to be precise).
The two input images both use a CMYK colour profile, which they both have embedded, but I also have as a seperate file. I want the output file to use the same colour profile. Compositing the images together using ImageMagick v7 results in a broken image where the colour space is changed to RGB, with the CMY channels mapped to RGB and the K channel discarded (so the colours look very obviously wrong!). Performing other operations on these files, such as cropping, outputs results that retain the colour profile and CMYK colour space as intended; as far as I can tell, it's just the behaviour of composite that has changed.
I was originally using the following command:
convert -profile USWebCoatedSWOP.icc under.jpg -profile USWebCoatedSWOP.icc over.jpg -gravity center -composite -profile USWebCoatedSWOP.icc comp.jpg
This works under v6, but is broken under v7. Since the images have the colour profile embedded, I wondered if some kind of colour space conversion was happening because I was also providing the profile file in the command, so I tried a few other variations:
# No external profiles specified:
convert under.jpg over.jpg -gravity center -composite comp.jpg
# Embedded input profiles implicit, output profile specified:
convert under.jpg over.jpg -gravity center -composite -profile USWebCoatedSWOP.icc comp.jpg
# Output profile specified twice, as a from–to conversion:
convert under.jpg over.jpg -gravity center -composite -profile USWebCoatedSWOP.icc -profile USWebCoatedSWOP.icc comp.jpg
All of these however result in the same output. (They also result in consistent output under v6, except in that case, the output is always correct!) Adding -colorspace CMYK has no effect except to make the broken image slightly washed out. Adding -set colorspace CMYK results in a corrupt image.
Something has apparently changed in how ImageMagick handles colour profiles in composite operations between v6 and v7 – but what? Nothing immediately stands out in the changelogs.
Relevant portions from identify -verbose. Input files have:
Image: under.jpg
Format: JPEG (Joint Photographic Experts Group JFIF format)
Mime type: image/jpeg
Class: DirectClass
Geometry: 1630x2220+0+0
Resolution: 600x600
Print size: 2.71667x3.7
Units: Undefined
Colorspace: CMYK
Type: ColorSeparation
…
Properties:
date:create: 2020-08-29T13:13:02+00:00
date:modify: 2020-08-29T12:39:46+00:00
icc:copyright: Copyright 2000 Adobe Systems, Inc.
icc:description: U.S. Web Coated (SWOP) v2
jpeg:colorspace: 4
jpeg:sampling-factor: 1x1,1x1,1x1,1x1
signature: d8e1a18efe471b7a131e661ea31e0b02aed6cb9e6555254781fc9df5352f2d6c
Profiles:
Profile-icc: 557168 bytes
…
Broken output file from v7 has:
Image: comp.jpg
Format: JPEG (Joint Photographic Experts Group JFIF format)
Mime type: image/jpeg
Class: DirectClass
Geometry: 1630x2220+0+0
Resolution: 600x600
Print size: 2.71667x3.7
Units: Undefined
Colorspace: sRGB
Type: TrueColor
…
Properties:
date:create: 2020-08-29T13:35:01+00:00
date:modify: 2020-08-29T13:35:01+00:00
icc:copyright: Copyright 2000 Adobe Systems, Inc.
icc:description: U.S. Web Coated (SWOP) v2
jpeg:colorspace: 2
jpeg:sampling-factor: 1x1,1x1,1x1
signature: f1ef274bc6f6f631a406ea3e5c25691faa50ea99ff14ab56ed7b80431f2e64a4
Profiles:
Profile-icc: 557168 bytes
…
Correct output file from v6 has:
Image: comp.jpg
Format: JPEG (Joint Photographic Experts Group JFIF format)
Mime type: image/jpeg
Class: DirectClass
Geometry: 1630x2220+0+0
Resolution: 600x600
Print size: 2.71667x3.7
Units: Undefined
Colorspace: CMYK
Type: ColorSeparation
… Properties:
date:create: 2020-08-29T13:25:44+00:00
date:modify: 2020-08-29T13:24:12+00:00
icc:copyright: Copyright 2000 Adobe Systems, Inc.
icc:description: U.S. Web Coated (SWOP) v2
jpeg:colorspace: 4
jpeg:sampling-factor: 1x1,1x1,1x1,1x1
signature: 457347556af05e75fd5cc65f8c1cd1c94dae1ac6fb574c103dc09d8744877928
Profiles:
Profile-icc: 557168 bytes
…
Channel statistics for the RGB channels in the broken output exactly match those for the CMY channels in the correct output.
Edit:
Per fmw42's comment, I've also tried the stricter syntax of v7:
magick under.jpg -profile USWebCoatedSWOP.icc over.jpg -profile USWebCoatedSWOP.icc -gravity center -composite -profile USWebCoatedSWOP.icc comp.jpg
However, this still produces a broken image. Here are test images with the profile embedded (smaller than the real images I'm using, but still exhibiting the same problem):
under.jpg - input file
over.jpg - input file
compv6.jpg - desired output as produced by v6
compv7.jpg - incorrect output as produced by v7

These two command work fine for me with ImageMagick using IM 6.9.11.28 and IM 7.0.10.28 Q16 Mac OSX Sierra. Both produce CMYK results and contain the cmyk profile. I suspect your IM 7 version is old and had a bug that since has been corrected. The profiles are carried from the input to the ouput.
IM 6
convert under.jpg over.jpg -gravity center -compose over -composite result6.jpg
IM 7
magick under.jpg over.jpg -gravity center -compose over -composite result7.jpg

Related

ImageMagick Convert BMP from 24 bit to 16 bit question?

Trying to convert bmp file from 24-bit to 16-bit bmp by ImageMagick and ViX 統合画像ビュアー. This is the same as the thumbnail in my images, but in hex content is not my expected. And the question I ask because I have to covert these 16-bit bmp files to a .spr (Sprite image file) for MMORPG Game(Lineage 1).
ImageMagickVersion: ImageMagick-7.1.0-portable-Q16-HDRI-x64
ViX 統合画像ビュアー Version: ViX 2.21
Plateform: Win11
Source fils here
Input_24bit.bmp
Output_16bit_ViX.bmp
Output_16bit_IM.bmp
ImageMagick Command
convert '24_bit.bmp' -alpha off -define bmp:subtype=RGB565 '16_bit.bmp'
ViX 統合画像ビュアー
Use GUI windows to decreasing color to Highcolor(16bit)
Result presenting (Red background will been transparent in Game)
BMP Hex Compare
(A) result from ViX 統合画像ビュアー that I expected
(B) result from Imagemagick convert
The difference is that ImageMagick, by default, writes a v5 BMP, whereas your program has written a v3 BMP.
To make ImageMagick write the older BMP3 format, prefix your output filename with BMP3: like this:
convert input.bmp -alpha off -define bmp:subtype=RGB565 BMP3:output.bmp

ImageMagick - Can %d be used together with image property percent escapes?

I'm encountering behavior using ImageMagick's image property percent escapes that I can't explain. Consider this minimal example that exhibits the problem:
convert rose: 'rose_%d.png'
# Resulting filename: rose_0.png (as expected)
convert rose: -set filename:mysize "%wx%h" 'rose_%[filename:mysize]_%d.png'
# Resulting filename: rose_70x46_%d0.png
# Why is '%d' in the output filename?
# Expected: rose_70x46_0.png
convert rose: -set filename:mysize "%wx%h" 'rose_%d_%[filename:mysize].png'
# Resulting filename: rose70x46.png
# Expected: rose_0_70x46.png
Relevant documentation:
https://www.imagemagick.org/Usage/files/#save_escapes
Can %d be used together with image property percent escapes?
Can %d be used together with image property percent escapes?
Only if it comes before %[filename:. Looking at the source code; it appears to be a case statement. The order of precedence allow for field width & %d, but once %[ is trapped, it stops checking on closing brace ] -- or error.
Might be worth jumping over to the developer forums to discuss this behavior.
You can work around it by moving the index order over to the filename:mysize placeholder.
$ convert rose: -set filename:mysize "%wx%h_%p" rose_%[filename:mysize].png
#=> rose_70x46_0.png
$ convert rose: wizard: -set filename:mysize "%wx%h_%p" rose_%[filename:mysize].png
#=> rose_70x46_0.png rose_480x640_1.png

How to strip EXIF except "date taken" using Imagemagick?

I want to reduce image size by stripping EXIF metadata (convert -strip ...), but the problem is I want to preserve the "date taken" entry. Is it possible? For example: convert -quality 80 -strip-except "date taken" source.jpg dest.jpg
It depends how important it is to save the "date taken" "in the correct place" where it can be parsed by normal image viewing programs. If you just want the original date/time in the file somewhere/anywhere, you can extract it and save it in the "Comment" field like this:
# Use ImageMagick to get the exif:DateTime, e.g. "exif:DateTime: 2014:12:23 13:51:00"
d=$(identify -verbose image.jpg | grep "exif:DateTime:")
# Strip EXIF but then put DateTime in the "Comment" field
convert image.jpg -strip -set comment "$d" result.jpg
Update
Actually, you can get the date/time more succinctly, and in a platform-independent way than above by using:
identify -format "%[EXIF:DateTime]" image.jpg
2014:12:23 13:51:00
The date and time are now in the "Comment" field, it's just that ImageViewers won't find it there - although you can with:
identify -verbose result.jpg
Image: result.jpg
Format: JPEG (Joint Photographic Experts Group JFIF format)
Mime type: image/jpeg
Class: DirectClass
Geometry: 3264x2448+0+0
Resolution: 72x72
Print size: 45.3333x34
Units: PixelsPerInch
Type: TrueColor
Endianess: Undefined
Colorspace: sRGB
Depth: 8-bit
Channel depth:
red: 8-bit
...
...
Interlace: None
Intensity: Undefined
Compose: Over
Page geometry: 3264x2448+0+0
Dispose: Undefined
Iterations: 0
Compression: JPEG
Quality: 96
Orientation: Undefined
Properties:
comment: exif:DateTime: 2014:12:23 13:51:00
A better way to do it though is using jhead. It has these options:
-ft Set filetime to EXIF time
-purejpg Strip EXIF, IPTC and other meta-data
-mkexif Create a minimal EXIF section
-dsft Set EXIF time to filetime
which you can string together as you wish, but probably in the order I have shown.

Problems converting PDF to BMP using ImageMagick?

I would like to convert a PDF to BMP. The PDF I am talking about is available here.
I use ImageMagick with the following command :
convert -verbose -resize 256x256 phantom-brain-ellipse.pdf phantom.bmp
But the result is a phantom.bmp file corrupted or empty file with pixel dimensions 0x0.
The error message is :
"/opt/local/bin/gsx" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=pngalpha" -dTextAlphaBits=4 -dGraphicsAlphaBits=4 "-r72x72" "-sOutputFile=/var/tmp/magick-1199-UNts2yPB9u2%d" "-f/var/tmp/magick-1199rG26g03biUuT" "-f/var/tmp/magick-1199-sNgqMmlD53M"
/var/tmp/magick-1199-UNts2yPB9u21 PNG 263x263 263x263+0+0 8-bit sRGB 54.6KB 0.010u 0:00.009
phantom-brain-ellipse.pdf PDF 263x263 263x263+0+0 16-bit sRGB 54.6KB 0.000u 0:00.000
phantom-brain-ellipse.pdf=>phantom.bmp PDF 263x263=>256x256 256x256+0+0 16-bit sRGB 262KB 0.020u 0:00.019
When I convert to PNG everything works fine with the same command :
convert -verbose -resize 256x256 phantom-brain-ellipse.pdf phantom.png
Any idea how to fix that ?
Partial Solution
This command allowed me to get the right BMP :
convert phantom.png BMP3:phantom.bmp
But I don't get why it works !
Try:
convert -verbose -resize 256x256 phantom-brain-ellipse.pdf[0] BMP3:phantom.bmp
Update/Explanation
PDF is a multipage format. Potentially, the input PDF has more than one page.
ImageMagick commands can select a specific page with the naming convention filename[i], where i is the index of the page. Indexing is zero-based, so some.pdf[0] means: "Use page 1 of this PDF."
The SOMEFORMAT:filename convention determines the file format for output files and overrides any file format which may be indicated by the filename suffix. So an output filename of GIF:some.png will create a GIF file with the (wrong) suffix .png.
The BMP3: is a specific version of the general BMP format. By default, BMP:filename or filename.bmp will produce version 4 of BMP. To get version 3 use BMP3:filename.bmp. To get version 2 use BMP2:filename.bmp.
I used BMP3: because you reported that it worked...

How do I find out which quantum depth image magick is using?

Is there a flag I can pass at the command line to view the quantum depth that image magick was compiled with.
You just need to pass -version to convert and it will show you the quantum depth behind the version number:
Version: ImageMagick 6.8.8-6 Q16 x86 2014-01-29 http://www.imagemagick.org
Just for reference as Dirk's answer is already correct and accepted, there are other ways of getting at the quantum depth and quantum range:
Get Quantum Depth, e.g. Q8, Q16
convert xc: -format "%q" info:
16
Get Quantum Depth in a variable called "Q"
Q=$(convert xc: -format "%q" info:)
Get Quantum Range, i.e. 255 for 8-bit IM builds, 65535 for 16-bit IM builds
convert xc: -format "%[fx:quantumrange]" info:
65535
Get Quantum Range in a variable called "qrange"
qrange=$(convert xc: -format "%[fx:quantumrange]" info:)
Get Quantum Depth and Quantum Range in variables both in one go (bash only)
read Q qrange < <(convert xc: -format "%q %[fx:quantumrange]" info:)

Resources