magick++: read mono8 image, save as PNG

Questions and postings pertaining to the development of ImageMagick, feature enhancements, and ImageMagick internals. ImageMagick source code and algorithms are discussed here. Usage questions which are too arcane for the normal user list should also be posted here.
Post Reply
antenne
Posts: 2
Joined: 2015-11-17T08:46:21-07:00
Authentication code: 1151

magick++: read mono8 image, save as PNG

Post by antenne »

Hi all.

I have a bunch of GigE network cameras that provide raw grayscale pixel data (aka mono8). I intend to use magick++ to convert this to PNG for human consumption. I'm almost sure that this should be near trivial, but I can't get it to work properly. My code so far:

Code: Select all

void png::convert(void *dest, size_t *destsize,
                  void *src, size_t /*srcsize*/, size_t srcwidth, size_t srcheight) {
  Magick::Blob blob;

  Magick::Image im(srcwidth, srcheight, "R", Magick::CharPixel, src);
  im.type(Magick::GrayscaleType);
  im.depth(8);
  im.magick("png");
  im.write(&blob);

  memcpy(dest, blob.data(), blob.length());
  *destsize = blob.length();
}
The final output is not what I would expect. It appears that my gray data is read into a red channel, blue and green are untouched. Then, on GrayScale, a gray value is computed (probably) from all three channels. The final result is, unsurprising, not what I want. Hence, I spent most of the day trying to figure out how to either (a) tell the Image that there is only one channel or (b) how to duplicate the red channel into blue and green, such that I end up with the expected result. Alternatively, (c) find a completely different approach.

Any suggestions on how to proceed before I go bald? Thanks!
User avatar
glennrp
Posts: 1147
Joined: 2006-04-01T08:16:32-07:00
Location: Maryland 39.26.30N 76.16.01W

Re: magick++: read mono8 image, save as PNG

Post by glennrp »

I believe the "R" means red channel. I'm not familiar with that programming interface but I guess "L" (Luma) might work.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: magick++: read mono8 image, save as PNG

Post by fmw42 »

I do not think IM recognizes "L" for luma. See http://www.imagemagick.org/script/comma ... hp#channel.

In IM 6 a grayscale image is 3 exactly the same channels for R,G,B and not a single channel image (as it will be in IM 7). So to create a grayscale image, you need to put the same image (channel) into each of the R,G,B channels.

I do not know this API, so cannot comment on the code.
User avatar
glennrp
Posts: 1147
Joined: 2006-04-01T08:16:32-07:00
Location: Maryland 39.26.30N 76.16.01W

Re: magick++: read mono8 image, save as PNG

Post by glennrp »

fmw42 wrote:I do not think IM recognizes "L" for luma. See http://www.imagemagick.org/script/comma ... hp#channel.
Fred's right, "L" won't work. But that document does mention "Gray", so try that in place of "R" and let us know what happens.
antenne
Posts: 2
Joined: 2015-11-17T08:46:21-07:00
Authentication code: 1151

Re: magick++: read mono8 image, save as PNG

Post by antenne »

Thanks for your replies! Unfortunately, I can not use the commandline, but have to use the API directly. I didn't drill through the code to see how "gray" is implemented, but I suspect it's something along the lines I finally ended up doing. In case anyone is interested:

Code: Select all

void rgb(void **dest, size_t *destsize,
                 void *src, size_t srcsize, const std::string& srcformat) {

  std::string format;

  format.resize(srcformat.size());
  std::transform(srcformat.begin(), srcformat.end(), format.begin(), ::tolower);

  if (format == "mono8") {
    *destsize = 3 * srcsize;
    *dest = malloc(*destsize);

    for (char *destbyte = (char*)*dest, *srcbyte = (char*)src; srcbyte < (char*)src + srcsize; ++srcbyte) {
      *destbyte++ = *srcbyte;             // Red
      *destbyte++ = *srcbyte;             // Green
      *destbyte++ = *srcbyte;             // Blue
    }
...
Replace "R" in the first snippet by "RGB" and chain together. Don't forget to free() the rgb destination. Advantage: eventually I'll have to support other data formats that might come off a(nother) camera.
Post Reply