[SOLVED] How to get pixels index/indices of a quantized image?
Posted: 2018-07-06T08:49:53-07:00
I'm writing a program to convert PNG color images to a unique YCrCbA bitmap format that ImageMagick cannot directly output.
So I need to manually construct the color index map table and then write each pixel in its color index number.
The index should be 1 byte thus it limits to 256 colors.
Here is what I came so far:
Since Magick++ has no support of reading YCrCbA color, I wrote a custom ColorYCrCbA class:
The problem is, when I inspect the output file, there are 178 colors, for example, in the color index map table. This means every pixel should take index value from 0x00 to 0xB1. But in the actual pixels data, I found many indices much larger than that range, like 0xE3, 0xF2 and so on.
I'm not sure what went wrong. I'm using ImageMagick 7.0.8-5 statically compiled on Windows x64 with MSVC 2017. Can someone tell me what's the right way of doing this?
So I need to manually construct the color index map table and then write each pixel in its color index number.
The index should be 1 byte thus it limits to 256 colors.
Here is what I came so far:
Code: Select all
#include <Magick++.h>
#include <MagickCore/MagickCore.h>
int main(void)
{
// ...
// Load the PNG image from a memory buffer
Magick::Blob pngBlob(pngBuffer.data(), pngBuffer.size());
Magick::Image image(pngBlob);
image.quantizeColorSpace(MagickCore::YCbCrColorspace);
image.quantizeColors(256);
image.quantizeDither(true);
image.quantizeDitherMethod(MagickCore::DitherMethod::FloydSteinbergDitherMethod);
image.quantize();
// Write the color index map table
for (unsigned char i = 0; i < image.colorMapSize(); i++) {
Magick::ColorYCrCbA color(image.colorMap(i));
out.writeColorIndexEntry(i, color.Y(), color.Cr(), color.Cb(), color.Alpha());
}
// Write every pixel in its color index number
for (int row = 0; row < image.rows(); row++) {
// Get one row of pixels at a time
const Magick::Quantum *pixels = image.getConstPixels(0, row, image.columns(), 1);
for (int col = 0; col < image.columns(); col++) {
// Get pixel index number (This is not working properly!)
unsigned char index = (unsigned char)MagickCore::GetPixelIndex(image.constImage(), pixels++);
out.writePixelColorIndex(index);
}
}
// ...
}
Code: Select all
namespace Magick {
//
// YCrCbA Colorspace color
//
// Argument ranges:
// Y : 0 through 255
// Cr: 0 through 255
// Cb: 0 through 255
// A : 0 through 255
class MagickPPExport ColorYCrCbA : public Color
{
public:
// Default constructor
ColorYCrCbA(void)
: Color()
{
};
// Copy constructor
ColorYCrCbA(const Color &color_)
: Color(color_)
{
};
// PixelInfo constructor
ColorYCrCbA(const MagickCore::PixelInfo pixel_info_)
: Color(pixel_info_)
{
}
// Destructor
~ColorYCrCbA(void)
{
};
// Assignment operator from base class
ColorYCrCbA& operator=(const Color& color_)
{
*static_cast<Color*>(this) = color_;
return(*this);
};
// Color Y (0 through 255)
const unsigned char Y(void) const
{
return MagickCore::ScaleQuantumToChar(quantumRed());
};
// Color Cr (0 through 255)
const unsigned char Cr(void) const
{
return MagickCore::ScaleQuantumToChar(quantumGreen());
};
// Color Cb (0 through 255)
const unsigned char Cb(void) const
{
return MagickCore::ScaleQuantumToChar(quantumBlue());
};
// Color Alpha (0 through 255)
const unsigned char Alpha(void) const
{
return MagickCore::ScaleQuantumToChar(quantumAlpha());
};
protected:
// Constructor to construct with PixelInfo*
ColorYCrCbA(PixelInfo *rep_, PixelType pixelType_)
: Color(rep_, pixelType_)
{
};
};
}
I'm not sure what went wrong. I'm using ImageMagick 7.0.8-5 statically compiled on Windows x64 with MSVC 2017. Can someone tell me what's the right way of doing this?