Page 1 of 2

Converting a bi-tonal to a color image..

Posted: 2016-08-09T17:31:30-07:00
by Minok
I've read in a TIFF that is a bitonal compressed image and want to change the colors associated with the white and black, say make it green and blue.
To accomplish this I assume I first need to convert the two color image into a full RGB image.. but my attempts at changing the colorspace, changing the imagetype have so far failed to produce a non black-and-white image. The attributes of the image object change, but they don't cause any change in the underlying data... so when I write the image out as a PNG, I'm still getting a black and white image.

TransformImageColorSpace... no effect
SetImageType ... no effect

Is there a way that actually works? I've been able to use the core api just fine so far.. but this has me stumped.

Re: Converting a bi-tonal to a color image..

Posted: 2016-08-09T17:36:30-07:00
by snibgo
What version of IM are you using? If v7, have you used "-colorspace sRGB"? Exactly what command are you using? Please link to your image.

Re: Converting a bi-tonal to a color image..

Posted: 2016-08-09T17:58:16-07:00
by fmw42
You do not need to make the images colorspace sRGB before converting black/white to blue/green. This works fine in IM 6.9.5.5 Q16 Mac OSX

Create test bilevel image:

Code: Select all

convert logo: -colorspace gray -type bilevel logo.tif
identify -verbose logo.tif
Image: logo.tif
  Format: TIFF (Tagged Image File Format)
  Mime type: image/tiff
  Class: DirectClass
  Geometry: 640x480+0+0
  Units: PixelsPerInch
  Type: Bilevel
  Base type: Grayscale
  Endianess: LSB
  Colorspace: Gray
  Depth: 8/1-bit
  Channel depth:
    gray: 1-bit
change to blue/green:

Code: Select all

convert logo.tif +level-colors blue,green logo_color.tif
identify -verbose logo_color.tif
Image: logo_color.tif
  Format: TIFF (Tagged Image File Format)
  Mime type: image/tiff
  Class: DirectClass
  Geometry: 640x480+0+0
  Units: PixelsPerInch
  Type: Palette
  Base type: TrueColor
  Endianess: LSB
  Colorspace: sRGB
  Depth: 8-bit
  Channel depth:
    red: 1-bit
    green: 8-bit
    blue: 1-bit
see http://www.imagemagick.org/Usage/color_ ... vel-colors

Re: Converting a bi-tonal to a color image..

Posted: 2016-08-10T11:23:50-07:00
by Minok
I'm interfacing with the library via c/c++ function calls, not using command line tools.

I"m creating the image from a TIFF blob:

Code: Select all

#include "magick/MagickCore.h"
#include "magick/image.h"

Image* imgMagickImage;			// an imagemagick image handle
ImageInfo* imgMagickInfo= AcquireImageInfo(); // the imagemagick image info object
ExceptionInfo* imgMagickException= AcquireExceptionInfo();	// where exception information is stored from calls

imgMagickImage = BlobToImage(imgMagickInfo, (void*) tiffBlob, (size_t)tiffSize, imgMagickException); 
free(tiffBlob);	// free up the memory created by malloc in ccittBlobToTiffBlob as it is now no longer needed

strcpy_s(imgMagickImage->magick,MaxTextExtent, "png" );	
		
TransformImageColorspace( imgMagickImage, RGBColorspace); // <- this doesn't seem to convert the image
SetImageType( imgMagickImage, TrueColorType); // <- neither does this
		
// Change the values of the color table from white/black to input values red/green
// background is index 0 (which is RED in the sample TIFF data I'm using as input)
imgMagickImage->colormap[0].red = (MagickRealType)(bitonalTileIn->background_color.red *(QuantumRange/65535.0)); 
imgMagickImage->colormap[0].green = (MagickRealType)(bitonalTileIn->background_color.green *(QuantumRange/65535.0));
imgMagickImage->colormap[0].blue = (MagickRealType)(bitonalTileIn->background_color.blue *(QuantumRange/65535.0));
// foreground is index 1 (which is GREEN in the sample TIFF data I'm using as input)
imgMagickImage->colormap[1].red = (MagickRealType)(bitonalTileIn->foreground_color.red *(QuantumRange/65535.0));  
imgMagickImage->colormap[1].green = (MagickRealType)(bitonalTileIn->foreground_color.green *(QuantumRange/65535.0));
imgMagickImage->colormap[1].blue = (MagickRealType)(bitonalTileIn->foreground_color.blue *(QuantumRange/65535.0));		
After this, the imageMagickImage attributes are:
Colorspace is RGBColorspace
Compression is still Group4 compression
Depth is 8
colors is 2
colormap[0] is blue=0, green=0, red=65535
colormap[1] is blue=0, green=65535, red=0
Taint is MagickTrue

I then convert the image into a blob again (a PNG blob in this case)

Code: Select all

unsigned char* pngBlob = NULL;  // for storing the PNG blob created later (note: we need to free the blob ourselves)
size_t tiffSize_sizet = tiffSize;	// needed to allow g++ on a linux to compile the ImageToBlob (unsigned int* doesn't convert to size_t* there)
pngBlob = ImageToBlob( imgMagickInfo, imgMagickImage, &tiffSize_sizet, imgMagickException);	// create the PNG blob, based on the magick member (png)
That PNG blob written to a file is still white/black, so despite the changes to the color table and all, I'm not getting the image to change.


I have also trid to use OpaquePaintImage:

Code: Select all

MagickPixelPacket origColor;
MagickPixelPacket newColor;

origColor.red = 0;  // black
origColor.green = 0;
origColor.blue = 0;

newColor.red = (MagickRealType)(bitonalTileIn->background_color.red *(QuantumRange/65535.0)); // is red in background color
newColor.green = (MagickRealType)(bitonalTileIn->background_color.green *(QuantumRange/65535.0));
newColor.blue = (MagickRealType)(bitonalTileIn->background_color.blue *(QuantumRange/65535.0));
// newColor red=65535, green & blue=0

OpaquePaintImage( imgMagickImage, &origColor, &newColor, MagickFalse);  // should replace all black with red color
Also to no avail, I"m still getting out a white/black PNG image.

Re: Converting a bi-tonal to a color image..

Posted: 2016-08-10T12:11:54-07:00
by fmw42
Until you convert black/white to other colors, IM will recognize that it is grayscale (or bilevel) and keep it that way. IM does not allow grayscale to be convert to color unless it has actual color in it. Only a few formats permit that with a -define. See http://www.imagemagick.org/script/comma ... php#define for -define colorspace:auto-grayscale=on|off.

I do not use any API and so do not know what features they support.

Re: Converting a bi-tonal to a color image..

Posted: 2016-08-10T12:17:16-07:00
by snibgo
I know nothing about colormaps, but I can't see anything in your code that tells the image to use colormaps, or how many entries there should be, and so on.

The function LevelColorsImage() is the obvious way of doing this.

Re: Converting a bi-tonal to a color image..

Posted: 2016-08-10T12:51:15-07:00
by Minok
When it reads the bitonal TIFF it already has a color map - one entry is black and one is white. Maybe my confusion is with misleading information in attributes of the imagemagick image structure that don't apply to the actual pixel payload.

So the question then is HOW does one convert the bilevel to color. Thats step one of the two step sequence:
1) Convert from Bilevel to Color
2) Change the colors from white->red and black->green (for this example).

Raster image has one of two encodings: either
1) The image pixel data contains a color table reference and the that entry in the color table is the (say) RGB value to use.
or
2) The image pixel data is itself an (say) RGB value.

If the bitonal image is has a color table based encoding, then all I'd have to do is change the definitions of the colors to recolor.
If the bitonal has the color stored as the pixel data, then I'd have to touch the pixels to change their color.

Everything I saw about the image structure indicated to me the image was stored as a compressed raster with a color table of 2 entries for bitonal.
My attempts to make it become an RGB image via the core documentation has not led to success.
Nor has my attempt to paint the pixels with new colors.

The documentation at http://www.imagemagick.org/script/magick-core.php doesn't give a lot of colormap functionality; a grey colormap is the starting point.

Re: Converting a bi-tonal to a color image..

Posted: 2016-08-10T13:10:59-07:00
by fmw42
So the question then is HOW does one convert the bilevel to color. Thats step one of the two step sequence:
1) Convert from Bilevel to Color
2) Change the colors from white->red and black->green (for this example).
You can skip step one, since IM won't generally allow that. All you need do is change the colors and IM will automatically promote the type to color and the colorspace to sRGB

Re: Converting a bi-tonal to a color image..

Posted: 2016-08-10T14:35:51-07:00
by snibgo
When it reads the bitonal TIFF it already has a color map - one entry is black and one is white.
Does it? Which part of your code finds that?

I expect you can do this with palettes, if you really want to. I would just SetNoPalette() to ensure it doesn't have a palete, then LevelColorsImage().

You still haven't told us the version of IM you are using.

Re: Converting a bi-tonal to a color image..

Posted: 2016-08-10T15:07:58-07:00
by fmw42
snibgo wrote:You still haven't told us the version of IM you are using.
Also what platform?

Re: Converting a bi-tonal to a color image..

Posted: 2016-08-12T15:15:37-07:00
by Minok
Thanks for the tips. At present I'm using ImageMagick 6.8.9-0 Q16 x86 compiled into static library files on a Windows 7 platform with Visual Studio 2010. I intend to upgrade to 6.9.5-5 or 7.0.2-7 at some point. I'd think these sort of basic image manipulation features would be working in 6.8.x however.

I'll try just changing the colors; my attempts to do so via via:

Code: Select all

		MagickPixelPacket origColor;
		MagickPixelPacket newColor;
		
		origColor.red = 0;
		origColor.green = 0;
		origColor.blue = 0;
		
		newColor.red = QuantumRange; 
		newColor.green = 0; 
		newColor.blue = 0; 
		
		if (OpaquePaintImage( imgMagickImage, &origColor, &newColor, MagickFalse) == MagickFalse) {
			std::cerr << "ERROR: BitonalTile: OpaquePaintImage() ImageMagick call returned false." << std::endl;
		}
has so far resulted in no change to the output PNG generated subsequently by: (its still a white/black image)

Code: Select all

			std::stringstream pngNameS;
			pngNameS << imageFilePrefix << imageCounter << "_magick.png";
			strcpy_s(imgMagickImage->filename, MaxTextExtent, pngNameS.str().c_str() );
			std::cout << "DEBUG: Writing ImageMagick image to PNG file [" << pngNameS.str() << "]" << std::endl;
			WriteImage(imgMagickInfo, imgMagickImage);

Re: Converting a bi-tonal to a color image..

Posted: 2016-08-12T15:19:41-07:00
by fmw42
As user snibgo said above

"The function LevelColorsImage() is the obvious way of doing this."

It assumes you are starting with black and white and replace black with one color and white with the other color that you specify.

See http://www.imagemagick.org/script/comma ... vel-colors

Re: Converting a bi-tonal to a color image..

Posted: 2016-08-12T15:29:13-07:00
by Minok
snibgo wrote:
When it reads the bitonal TIFF it already has a color map - one entry is black and one is white.
Does it? Which part of your code finds that?

I expect you can do this with palettes, if you really want to. I would just SetNoPalette() to ensure it doesn't have a palete, then LevelColorsImage().

You still haven't told us the version of IM you are using.
When I'm looking at the image structure in the debugger, I can see the various attributes of the structure, one of which is called colormap that has 2 entries in the array at index 0, and 1, with values for black(0,0,0) and white (65535,65535,65535).. but as I was trying a bunch of things, I backtracked to see what was actually causing the changes.

Attempting to affect the colormap with TransformImageColorspace( imgMagickImage, RGBColorspace); or SetImageType( imgMagickImage, TrueColorType); resulted in no changes to the underlying colormap attribute, it stayed null (ie undefined).

It was the writing out of the image as a PNG via

Code: Select all

  strcpy_s(imgMagickImage->filename, MaxTextExtent, "outputimage.png" );
  WriteImage(imgMagickInfo, imgMagickImage);
that caused imagemagick to reprocess and produce the 2 entry colormap.

I'd rather not go through the needless exercise of generating an png file, as I don't really need to produce a file, I need the png blob for further usage. So I am trying to find a way to take the existing image in memory, and recolor it. Easiest is if its indexed-color, because then I only need to change the color map, vs touching the individual pixels to recolor.

Re: Converting a bi-tonal to a color image..

Posted: 2016-08-12T16:05:45-07:00
by fmw42
You cannot access nor change the colormap directly in Imagemagick. Please try LevelColorsImage() whether you write out to a file or keep as a blob.

Re: Converting a bi-tonal to a color image..

Posted: 2016-08-12T16:37:12-07:00
by Minok
After some fiddling around with LevelColorsImage() as the documentation language was a big unclear to me, I found the combination:

Code: Select all

		foreColor.red = QuantumRange; 
		foreColor.green = 0; 
		foreColor.blue = 0; 

		backColor.red = 0; 
		backColor.green = QuantumRange; 
		backColor.blue = 0; 

		LevelColorsImage( imgMagickImage, &foreColor, &backColor, MagickTrue);
That indeed maps the image's black color to red, and its white color to green.
Specify what color you want black mapped to and white mapped to and set the flag to TRUE.

Thank you so much all for the assistance.


Final followup question - I was in this bind somewhat as I wasn't able to discover this solution directly be looking over the API as described in :
http://www.imagemagick.org/script/magick-core.php (cannot find LevelColorsImage, much less guess where that might be in the bullet list if it was in there)

Is there a source that documents the core API that gets maintained with the code?
Or does one just poke around the source .c files and read the function descriptors?