Page 1 of 1

force greyscale image to sRGB

Posted: 2018-12-13T00:53:28-07:00
by sir8472
I am hoping someone can help, as I'm a little bit stuck with some code.

From the command line, I can take an input PNG file, convert it to TIF and force it to sRGB using the following:

Code: Select all

convert in.png -colorspace srgb -type truecolor out.tif
and it outputs a TIF file with:
colorspace:13 (Imagick::COLORSPACE_SRGB)
type:6 (Imagick::IMGTYPE_TRUECOLOR)

When I run the following code via PHP

Code: Select all

$img = new Imagick();
$img->readImage('in.png');
$img->transformImageColorspace(\Imagick::COLORSPACE_RGB);
$img->setImageType(\Imagick::IMGTYPE_TRUECOLOR);
$img->setImageFormat('tiff');
// there's a reason I am using file_put_contents, not writeImage(), but assume it has no impact with this issue.
file_put_contents('out.tif', $img);
I get an image that is greyscale:
colorspace:2 (Imagick::COLORSPACE_GRAY)
type:2 (Imagick::IMGTYPE_GRAYSCALE)

I'm running ImageMagick 6.9.7-4 Q16 x86_64 20170114.

The input file is an RGB PNG, but its contents is greyscale.

Have I done something wrong, or missed something obvious?

Re: force greyscale image to sRGB

Posted: 2018-12-13T01:56:48-07:00
by snibgo
From documentation eg https://secure.php.net/manual/en/functi ... ntents.php, it seems file_put_contents is a generic function that writes binary data to a file. I'm surprised it give you a valid TIFF file. But it won't do any processing of the binary data, eg to promote grayscale to 3-channel.

Note that "-type truecolor" is a setting for future operations, and doesn't itself do any work.

Re: force greyscale image to sRGB

Posted: 2018-12-13T02:12:55-07:00
by sir8472
From various searches on Stack Overflow and this forum, I had assumed "type" needed to be used with the "colorspace" option, though I admit my interpretation is coloured (pun) by lack of knowledge in this area.

Code: Select all

$img->setoption("colorspace:auto-grayscale", "off");
Is another option I've found through my searches, but it also doesn't have an impact.

Ignoring what I already have, if you had to take a greyscale PNG and output it as an sRGB TIF using PHP, how would you accomplish it/is it possible?

Re: force greyscale image to sRGB

Posted: 2018-12-13T02:36:56-07:00
by snibgo
I don't use PHP or IMagick, but I expect that no settings have any effect on file_put_contents. Why do you use this? Why not writeImage?

Re: force greyscale image to sRGB

Posted: 2018-12-13T02:56:15-07:00
by sir8472
The imagick object is actually handed off to a storage class to write to disk. Live code doesn't actually "file_put_contents", but I bet it doesn't use writeImage either, which is why I didn't include it here. If it makes you feel any better I can use writeImage in the example, file output is the same.

Also, for reference, in the command line example above, there's an error. It should actually be:

Code: Select all

convert in.png -colorspace srgb -type TrueColorAlpha out.tif
It needs the alpha or it loses any transparent layer.

Re: force greyscale image to sRGB

Posted: 2018-12-13T04:31:09-07:00
by sir8472
Well, in the absence of a PHP solution, and a need to get sRGB TIF files through I have created the following script which may be useful to someone else in the future as a starting point.

Code: Select all

#!/bin/bash
############################################
# convertGreyscaleTosRGB
# Transform images from "Gray" to "sRGB" colourspace
# Created by: sir8472
# Created on: 2018/12
#
# Take an image and check to see if it's "Grey" colourspace, if so convert it to "sRGB" overwriting the original file.
#
# Notes
# -> Imagick sRGB is used instead of RGB for preservation of transparency
# -> The script has been tested on ubuntu 16.04 and 18.04
# -> file names with special characters cause problems. I don't have any of these, but you may need to edit to fix for your use case
# -> use at your own risk!


# Running the script
# ./convertGreyscaleTosRGB.sh -f /path/to/my/file
#
# Alternative: use find to pass in lots of files.
# find /path/to/images -iname "*.tif" -exec /path/to/script/convertGreyscaleTosRGB.sh -f {} \;
############################################

# I want images to end up in this colourspace
TARGET_COLOURSPACE="sRGB"

# If we have no flags passed, exit
if [ $# -le 0 ]; then
    echo "No arguments found, can't continue!"
    exit
fi

# Match the flags to functions (I assume I am adding some more later)
while [ "$1" != "" ]; do
    case $1 in
        -f | --file )           shift
                                filename=$1
                                ;;
        * )                     echo "nope, no idea what you want. Quitting"
                                exit 1
    esac
    shift
done

# for the provided image, check to see what colourspace it is.
file_colourspace=$(identify -format '%[colorspace]' $filename)

# If the current colourspace doesn't match the desired colourspace, convert it
if [ "$TARGET_COLOURSPACE" != "$file_colourspace" ]; then

    convert $filename -colorspace srgb -type TrueColorAlpha $filename

    # get the new colourspace
    new_file_colourspace=$(identify -format '%[colorspace]' $filename)

    # Record it in a log
    echo "$filename was $file_colourspace and is now $new_file_colourspace" >> converter_changed_files.log

    # Output it to the screen too
    echo "$filename was $file_colourspace and is now $new_file_colourspace"
else
    # if it isn't a match, log it to ignored files log, incase I need to review unexpected failures later
    echo "$filename is $file_colourspace" >> converter_ignored_files.log
fi

I'd still appreciate any input on the PHP side of forcing sRGB colourspace for TIF files if anyone has any.

Re: force greyscale image to sRGB

Posted: 2018-12-17T15:50:19-07:00
by sir8472
For completeness and to any lost coder who needs to do something similar, this is what I've ended up with in PHP:

Code: Select all

$img = new Imagick();
$img->readImage('in.png');

// Convert the image to a TIF file
$img->setImageFormat('tiff');

// Set the image type to TrueColour Matte (transparency should be preserved)
// SEE: 
// https://github.com/mkoppanen/imagick/issues/109
// https://stackoverflow.com/questions/34220981/setting-color-depth-with-imagick
// http://php.net/manual/en/imagick.constants.php
$img->setType(\Imagick::IMGTYPE_TRUECOLORMATTE);

$img->transformImageColorspace(\Imagick::COLORSPACE_sRGB);

// This works fine...
// file_put_contents('out.tif', $img);
// but as per snibgo's comments you should use this:
$img->writeImage('out.tif');
It would seem the order matters, so setting the format to tiff first, then applying the type and transforming the colorspace. This should preserve transparency and force greyscale images to sRGB colourspace as TIF files.