Why does convert change my RGB value?

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
ajkerr
Posts: 4
Joined: 2012-08-29T13:34:18-07:00
Authentication code: 67789

Why does convert change my RGB value?

Post by ajkerr »

I am trying to generate a simple blank canvas from an RGB value and save it as a JPEG.

The command I am using is quite simple:

Code: Select all

convert -size 460x460 xc:#F4F2EA -quality 100 image.jpg
Unfortunately, all of the pixels in the resulting image are slightly off: #F5F2EB

Here is the output of identify -verbose on the resulting image:

Code: Select all

Image: ligIM.jpg
  Format: JPEG (Joint Photographic Experts Group JFIF format)
  Class: DirectClass
  Geometry: 460x460+0+0
  Units: Undefined
  Type: Palette
  Endianess: Undefined
  Colorspace: sRGB
  Depth: 8-bit
  Channel depth:
    red: 8-bit
    green: 8-bit
    blue: 8-bit
  Channel statistics:
    Red:
      min: 245 (0.960784)
      max: 245 (0.960784)
      mean: 245 (0.960784)
      standard deviation: 0 (0)
      kurtosis: 0
      skewness: 0
    Green:
      min: 242 (0.94902)
      max: 242 (0.94902)
      mean: 242 (0.94902)
      standard deviation: 0 (0)
      kurtosis: 0
      skewness: 0
    Blue:
      min: 235 (0.921569)
      max: 235 (0.921569)
      mean: 235 (0.921569)
      standard deviation: 0 (0)
      kurtosis: 0
      skewness: 0
  Image statistics:
    Overall:
      min: 235 (0.921569)
      max: 245 (0.960784)
      mean: 240.667 (0.943791)
      standard deviation: 0 (0)
      kurtosis: 0
      skewness: 0
  Colors: 1
  Histogram:
    211600: (245,242,235) #F5F2EB srgb(245,242,235)
  Rendering intent: Perceptual
  Gamma: 0.454545
  Chromaticity:
    red primary: (0.64,0.33)
    green primary: (0.3,0.6)
    blue primary: (0.15,0.06)
    white point: (0.3127,0.329)
  Interlace: None
  Background color: white
  Border color: srgb(223,223,223)
  Matte color: grey74
  Transparent color: black
  Compose: Over
  Page geometry: 460x460+0+0
  Dispose: Undefined
  Iterations: 0
  Compression: JPEG
  Quality: 100
  Orientation: Undefined
  Properties:
    date:create: 2012-08-29T16:35:58-04:00
    date:modify: 2012-08-29T16:35:58-04:00
    jpeg:colorspace: 2
    jpeg:sampling-factor: 1x1,1x1,1x1
    signature: 8a0a2f88ce4527538ae2ff9195c5d3aaf0769fc7ac2eb17fc84b18875fa39043
  Artifacts:
    filename: ligIM.jpg
    verbose: true
  Tainted: False
  Filesize: 2.81KB
  Number pixels: 212K
  Pixels per second: 21.16MB
  User time: 0.010u
  Elapsed time: 0:01.009
  Version: ImageMagick 6.7.9-0 2012-08-29 Q16 http://www.imagemagick.org
Can anyone explain why the colour value is being changed? I've been scratching my head with this for days. Only certain colours seem to cause this. I've tried experimenting with colorspaces as well, to no avail.

Thanks,
Andrew
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Why does convert change my RGB value?

Post by fmw42 »

Probably because jpg is a lossy compression and does not work well on constant color values. try saving to png or gif and see if that works.
ajkerr
Posts: 4
Joined: 2012-08-29T13:34:18-07:00
Authentication code: 67789

Re: Why does convert change my RGB value?

Post by ajkerr »

I'm puzzled, though, why JPEG would need to alter the colour when the quality is set to 100 and there's only a single colour.

PNG isn't an option, unfortunately - we're converting PNGs with a transparent background to JPEGs for a customer because of their enormous size.

To do this we are creating a canvas to match the background colour of the customer's web site, and then overlaying the original PNG on, then saving as a JPEG.

No matter what we try, ImageMagick is altering the colour we specify for the background canvas.

Note: We tried PNG8, the the results are too pixelated, unfortunately.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Why does convert change my RGB value?

Post by fmw42 »

I am not an expert on JPG, but even at 100% it still is lossy.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Why does convert change my RGB value?

Post by magick »

Correct, JPEG is lossy unless the JPEG delegate includes a lossless patch. JPEG2000 (extension jp2) is a lossless JPEG format.
Jason S
Posts: 103
Joined: 2010-12-14T19:42:12-07:00
Authentication code: 8675308

Re: Why does convert change my RGB value?

Post by Jason S »

Most JPEG files do not have enough precision to store all possible 24-bit RGB colors in this way. The main issue here is that color JPEGs usually use the YCbCr colorspace, not RGB, and some information is lost in the translation.

One solution would be to use higher precision (12 bits per sample instead of 8 ), but practically nothing supports 12-bit JPEGs.

Another idea would be to avoid the YCbCr conversion, and store RGB data directly in the JPEG file. There is a de facto standard way to do that. I wouldn't recommend it -- RGB JPEGs don't compress very well, and aren't as portable -- but just as an experiment:

Code: Select all

$ convert -size 460x460 'xc:#F4F2EA' -depth 8 temp.ppm
$ cjpeg -rgb -quality 100 temp.ppm > image.jpg
$ identify -verbose image.jpg
  Histogram:
    211600: (244,242,234) #F4F2EA srgb(244,242,234)
ajkerr
Posts: 4
Joined: 2012-08-29T13:34:18-07:00
Authentication code: 67789

Re: Why does convert change my RGB value?

Post by ajkerr »

Hi Jason, thanks very much for the response.

I tried your suggestion and it worked.

I'm a bit confused though - where does the YCbCr conversion come into play? When I create an image with:

Code: Select all

convert -size 460x460 'xc:#F4F2EA' -quality 100 -depth 8 temp.jpg
the resulting image indicates the the Colorspace is sRBG. Similarly when I create the image using the method you outlined above, the colorspace is also listed as sRGB, but the histogram shows that the color has been changed.

Is there some sort of internal conversion to YCbCr and then back to sRGB?

Thanks,
Andrew
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Why does convert change my RGB value?

Post by fmw42 »

It is internal to the conversion to jpg only for the purpose of storing the DCT components, if I understand correctly. It has nothing to do with the input or output image colorspace.
User avatar
GreenKoopa
Posts: 457
Joined: 2010-11-04T17:24:08-07:00
Authentication code: 8675308

Re: Why does convert change my RGB value?

Post by GreenKoopa »

ajkerr wrote:I'm a bit confused though - where does the YCbCr conversion come into play? ... Is there some sort of internal conversion to YCbCr and then back to sRGB?
Yes, YCbCr colorspace conversion is internal to JPEG compression. As Jason showed, this conversion is technically optional (but nearly universal). But heed his warnings. Check that you are still getting the compression you want, and that your new image is compatible with browsers you support (especially older ones). I'll also add that the YCbCr conversion is not the only lossy step in JPEG compression, and YCbCr conversion loss is not altered by changing the quality setting. For the curious, Wikipedia has an introduction to JPEG encoding (the compression process): http://en.wikipedia.org/wiki/Jpeg#JPEG_codec_example
Jason S
Posts: 103
Joined: 2010-12-14T19:42:12-07:00
Authentication code: 8675308

Re: Why does convert change my RGB value?

Post by Jason S »

Right; the YCbCr conversion is sometimes considered to be a part of the data compression process, as opposed to being an actual colorspace.

A deficiency in the JPEG file format is that there is no standard way to indicate what color format an image uses. The JFIF subformat provides a standard way to store YCbCr and grayscale image data, but not RGB.

The popular libjpeg library uses heuristics to decide if an image is RGB. If the file does not contain a JFIF segment, and the image has three components, and either the file contains an APP14/"Adobe" segment whose "color transform" field is 0, or the component ID numbers are {0x52, 0x47, 0x42} (ASCII "RGB"), then it assumes it is RGB. These fields can be seen with ExifTool, for example.

Code: Select all

$ exiftool -v3 image.jpg

JPEG APP14 (12 bytes):
    0006: 41 64 6f 62 65 00 64 00 00 00 00 00             [Adobe.d.....]
...
  | ColorTransform = 0
...
JPEG SOF0 (15 bytes):
    005b: 08 01 cc 01 cc 03 52 11 00 47 11 00 42 11 00    [......R..G..B..]
User avatar
GreenKoopa
Posts: 457
Joined: 2010-11-04T17:24:08-07:00
Authentication code: 8675308

Re: Why does convert change my RGB value?

Post by GreenKoopa »

ajkerr wrote:we're converting PNGs with a transparent background to JPEGs for a customer because of their enormous size.
One easy option is to recompress the enormous PNGs into new PNGs. There are specialized tools that will make this lossless conversion. The size reduction can vary from none to substantial.
ajkerr wrote:ImageMagick is altering the colour we specify for the background canvas.
To summarize: It is not ImageMagick, but the JPEG format that alters colors. Great compression is achieved by causing loss. So, ...
ajkerr wrote:To do this we are creating a canvas to match the background colour of the customer's web site, and then overlaying the original PNG on, then saving as a JPEG.
can you slightly alter the web site background to match a color JPEG can store?
ajkerr
Posts: 4
Joined: 2012-08-29T13:34:18-07:00
Authentication code: 67789

Re: Why does convert change my RGB value?

Post by ajkerr »

Thank you all for the detailed responses - they were very helpful.
Post Reply