Avoid a color in a jpg

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
Lukeid
Posts: 1
Joined: 2015-08-26T08:47:52-07:00
Authentication code: 1151

Avoid a color in a jpg

Post by Lukeid »

Hello,

I need to asure that a generated image does not contain a specific color (or very similar one).

For example, to test if an image have a color I use:

Code: Select all

 convert test.jpg -fuzz 1% -fill black -opaque '#d3fec3' test_2.jpg
And visually check if there is any difference.

But once I know there is that color I tried to replace it with a similar one, for ejample:

Code: Select all

 convert test.jpg -fuzz 1% -fill '#c6ffb3' -opaque '#d3fec3' test_new.jpg
But if I check the new file to see if there is the color, it still it present. I guess that because JPEG compresion.

Code: Select all

 convert test_new.jpg -fuzz 1% -fill black -opaque '#d3fec3' test_new_2.jpg
I need to remove that color from the image because I use it in my application as chroma for transparency.

Is there any way to force that generated jpeg image does not contain a specific color?

Thank you very much in advance.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Avoid a color in a jpg

Post by snibgo »

JPEG uses lossy compression. This means it changes values of pixels, so you can't rely in particular colours being used, or not used, and can't decide exactly what values should be.
snibgo's IM pages: im.snibgo.com
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Avoid a color in a jpg

Post by fmw42 »

Convert your image to PNG, then determine what color you want to process and save to PNG.
246246
Posts: 190
Joined: 2015-07-06T07:38:22-07:00
Authentication code: 1151

Re: Avoid a color in a jpg

Post by 246246 »

If I understand right, if you can use lossless compression, pixel does not change.
So it is worth to try mozjpeg for your 2nd time conversion.

As far as I read, mozjpeg support lossless compression, and it try to keep compaitbility with jpeg.
http://blarg.co.uk/blog/comparison-of-j ... sion-tools

Probably you have to compile by yourself. For quick trial, online encoder is here:
http://mozjpeg.codelove.de/


----
[Edit]
Your 2nd time conversion need to change color to proper one, however, to see the online converter UI, It looks jpeg input is required for lossless conversion. (Internally, jpegtran do that lossless conversion.)

So I understand this is impossible even using lossless one :?
Last edited by 246246 on 2015-08-27T06:55:23-07:00, edited 1 time in total.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Avoid a color in a jpg

Post by snibgo »

As far as I know, when IM writes JPEG, it always uses a lossy compression, even at "-quality 100". Of course this doesn't mean that there will certainly be data loss. But is does mean there will probably be data loss.

So IM can create an image in memory that does not contain a certain colour. But it cannot write that as JPEG and guarantee that it won't contain that colour.

IM can write to PNG instead, so the written image won't contain that colour. Then perhaps another program can convert that without loss to JPEG.
snibgo's IM pages: im.snibgo.com
246246
Posts: 190
Joined: 2015-07-06T07:38:22-07:00
Authentication code: 1151

Re: Avoid a color in a jpg

Post by 246246 »

snibgo wrote:Then perhaps another program can convert that without loss to JPEG.
I had thought so, and the other program would be mozjpeg. But it seems that's not true. What it guarantees is jpg to jpg conversion is lossless.
246246
Posts: 190
Joined: 2015-07-06T07:38:22-07:00
Authentication code: 1151

Re: Avoid a color in a jpg

Post by 246246 »

It still can not be your help, but it seems there is one way to exclude specific color, according to the document.

libjpeg9 has new -wipe option for jpegtran.

Code: Select all

       A complementary lossless-wipe option is provided to discard (gray  out)
       data  inside  a  given image region while losslessly preserving what is
       outside:

       -wipe WxH+X+Y
              Wipe (gray out) a rectangular  subarea  of  width  W,  height  H
              starting at point X,Y.
Yes, it does not change to the arbitrary color. It seems to replace it to #808080. (That's why I said it is no useful for you.)

Anyway I start from this image.

Code: Select all

$ convert logo: logo.jpg
In my enviromnemt

Code: Select all

$ convert logo.jpg -format "%c" histogram:info: | sort -nr | head
    226556: (255,255,255) #FFFFFF white
      4471: ( 34, 62,146) #223E92 srgb(34,62,146)
      2732: (255,254,255) #FFFEFF srgb(255,254,255)
      1593: (254,255,255) #FEFFFF srgb(254,255,255)
      1577: (255,255,253) #FFFFFD srgb(255,255,253)
      1456: (255,253,255) #FFFDFF srgb(255,253,255)
       893: (252,255,255) #FCFFFF srgb(252,255,255)
       822: (255,255,251) #FFFFFB srgb(255,255,251)
       754: (254,254,254) #FEFEFE srgb(254,254,254)
       712: (255,252,255) #FFFCFF srgb(255,252,255)
So try to exclude #223E92.

Code: Select all

$ cp logo.jpg tmp.jpg
$ for i in `convert logo.jpg -depth 8 txt: | awk -F: '/#223E92/ {print $1}'`
> do
> X=`echo $i | awk -F, '{print $1}'`
> Y=`echo $i | awk -F, '{print $2}'`
> G="1x1+$X+$Y"
> echo $G
> jpegtran -wipe "$G" -outfile tmp2.jpg tmp.jpg
> mv tmp2.jpg tmp.jpg
> done | wc -l
4471
$ mv tmp.jpg result.jpg
check the result.

Code: Select all

$ convert result.jpg -format "%c" histogram:info: | grep -i 223E92

$ convert result.jpg -format "%c" histogram:info: | sort -nr | head
    226543: (255,255,255) #FFFFFF white
     11521: (128,128,128) #808080 fractal
      2695: (255,254,255) #FFFEFF srgb(255,254,255)
      1574: (254,255,255) #FEFFFF srgb(254,255,255)
      1562: (255,255,253) #FFFFFD srgb(255,255,253)
      1426: (255,253,255) #FFFDFF srgb(255,253,255)
       881: (252,255,255) #FCFFFF srgb(252,255,255)
       810: (255,255,251) #FFFFFB srgb(255,255,251)
       754: (254,254,254) #FEFEFE srgb(254,254,254)
       701: (255,252,255) #FFFCFF srgb(255,252,255)
Originally logo.jpg has 1 #808080

Code: Select all

$ convert logo.jpg -format "%c" histogram:info: | grep 808080
         1: (128,128,128) #808080 fractal
So I expected to get 4472 #808080 pixels but it did not.

I don't understand what I missed, or the bug of jpegtran (comes from MacPort).

Code: Select all

$ jpegtran -v
Independent JPEG Group's JPEGTRAN, version 9a  19-Jan-2014
Copyright (C) 2014, Thomas G. Lane, Guido Vollbeding
As far as I tried, it wipes at least 16x16 area for one time for logo.jpg above.
And if I start with jpg created with

Code: Select all

convert logo: -quality 100 logo100.jpg
it wipes 8x8 area.

Probably it is related with this sampling factor.

Code: Select all

$ identify -format "%[jpeg:sampling-factor]\n" logo100.jpg
1x1,1x1,1x1
$ identify -format "%[jpeg:sampling-factor]\n" logo.jpg
2x2,1x1,1x1
but I don't know the detail of these values.
Last edited by 246246 on 2015-09-10T08:21:59-07:00, edited 1 time in total.
246246
Posts: 190
Joined: 2015-07-06T07:38:22-07:00
Authentication code: 1151

Re: Avoid a color in a jpg

Post by 246246 »

246246 wrote:
snibgo wrote:Then perhaps another program can convert that without loss to JPEG.
I had thought so, and the other program would be mozjpeg. But it seems that's not true. What it guarantees is jpg to jpg conversion is lossless.
As far as I tried (a little), cjpeg comes from jpeg9a can create lossless jpg from bmp.

Code: Select all

% convert rose: BMP2:rose.bmp
% cjpeg -rgb1 -block 1 -arithmetic -outfile rose.jpg rose.bmp
% compare -metric PSNR rose.bmp rose.jpg -format "\n" null:
inf
So you probably can convert your jpg file first to bmp and remove specific color and then back to jpg like above.
(Also you can use jpegtran to wipe 1x1 area for this jpeg, but it's too slow.)

from Changelog

Code: Select all

Version 9  13-Jan-2013
----------------------

Add cjpeg -rgb1 option to create an RGB JPEG file, and insert
a simple reversible color transform into the processing which
significantly improves the compression.
The recommended command for lossless coding of RGB images is now
cjpeg -rgb1 -block 1 -arithmetic.
But be careful, from cjpeg man page.

Code: Select all

      -rgb1  Create  RGB  JPEG  file  with reversible color transform.  Works
              like the -rgb switch (see above) and inserts a simple reversible
              color transform into the processing which significantly improves
              the compression.  Use this switch in combination with the -block
              N  switch  (see  above)  for  lossless  JPEG coding.  Caution: A
              decoder with inverse color transform  support  is  required  for
              this  feature.   Reversible  color  transform support is not yet
              widely implemented, so many decoders will be unable  to  view  a
              reversible color transformed JPEG file at all.

       -arithmetic
              Use  arithmetic  coding.   Caution: arithmetic coded JPEG is not
              yet widely implemented, so many decoders will be unable to  view
              an arithmetic coded JPEG file at all.
Post Reply