Image constructor throws exception

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
mmuratet

Image constructor throws exception

Post by mmuratet »

Greetings

I am trying to create a new image following the example(s) on the web page documentation:
char* data;
size_t data = columns*rows;
data = (char*) new char[data_size];
Magick::Image image(columns, rows, "RGB", (MagickCore::StorageType)0, data);

I get the error: ImageMagick: unrecognized pixel map 'RGB'

This seems like it should at least create the object. The pixel buffer may not be correct.

Is there a better way to create new images? I want to create some synthetic images to test a signal processing algorithm.

Cheers

Mike
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Image constructor throws exception

Post by magick »

Here is an example program that converts CMYK image data instead of RGB but it does prove the constructor works properly. We're using ImageMagick 6.5.7-4:

Code: Select all

#include <iostream>
#include <Magick++.h>

unsigned char imageData[] = {
0xff, 0xff, 0xff, 0xff,      // super black
0x00, 0x00, 0x00, 0x00,      // white
0xff, 0x00, 0x00, 0x00,      // cyan
0x00, 0xff, 0x00, 0x00,      // magenta
0x00, 0x00, 0xff, 0x00,      // yellow
0x00, 0x00, 0x00, 0xff,      // black
0x00, 0xff, 0xff, 0x00,      // red
0xff, 0x00, 0xff, 0x00,      // green
0xff, 0xff, 0x00, 0x00,      // blue
0x00, 0x00, 0x00, 0x00,      // white
0xff, 0xff, 0xff, 0xff      // super black
};

#define IMAGE_WIDTH 11
#define IMAGE_HEIGHT 1

unsigned char outputImage[IMAGE_WIDTH * IMAGE_HEIGHT * 4];


int main (int argc, char * const argv[]) {
   std::cout << "Hello, World!\n";

   Magick::Image image( IMAGE_WIDTH, IMAGE_HEIGHT, "CMYK", Magick::CharPixel, imageData );    
   //image.type(Magick::TrueColorType);
   image.write("/tmp/test.tif");
   
   image.modifyImage();
   //image.blur(30, 10);
   image.syncPixels();
   
   Magick::Pixels view(image);
   
   FILE *f = fopen("/tmp/test.txt",  "w");
   
   for ( int row = 0; row < IMAGE_HEIGHT ; ++row )
   {
     Magick::PixelPacket *pixels = view.get(0,row,IMAGE_WIDTH,1);
     Magick::IndexPacket *indexes = view.indexes();
      for ( int column = 0; column < IMAGE_WIDTH ; ++column ) {
         fprintf(f, "%8d\t%8d\t%8d\t%8d\n",
               pixels->red, pixels->green, pixels->blue, *indexes);
         pixels++;
         indexes++;
      }
   }
   fprintf(f, "\n");
   fclose(f);
   return 0;
}
mmuratet

Re: Image constructor throws exception

Post by mmuratet »

Thanks. I tried it and it works.

let me ask another question along the same line, although it may be some key fact I've forgotten about c++.

I'd like big images, about 2000x2000 or so. I substituted unsigned char *imageData = new unsigned char[N]; for the data statement in the code just to see if it will run. When N gets bigger than 40000 and the image is bigger than 200x200, I start getting seg faults. Is there some limit somewhere I've ignored? It seems like I should be able to create images of more or less arbitrary size.

Thanks

Mike
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Image constructor throws exception

Post by magick »

There is no limit on image size other than if your system runs out of temporary space on disk to store the intermediate pixel data. Post a complete smallish program that illustrates the problem. Hopefully it will fail for us and we'll produce a stack trace to identify where the fault lies.
mmuratet

Re: Image constructor throws exception

Post by mmuratet »

Here's a small method that will seg fault:

Code: Select all

#include <iostream>
#include <Magick++.h>

unsigned char *imageData = new unsigned char[1000000];
#define IMAGE_WIDTH 1000
#define IMAGE_HEIGHT 1000

unsigned char outputImage[IMAGE_WIDTH * IMAGE_HEIGHT * 4];

int main (int argc, char * const argv[])
{
    std::cout << "Hello, World!\n";

    Magick::Image image( IMAGE_WIDTH, IMAGE_HEIGHT, "CMYK", Magick::CharPixel, imageData );   

    return 0;
}
I checked my /tmp space and realized it was mounted as tmpfs, i.e., in memory. I set the size to 4G and remounted it but get the same error.

Thanks for the help

Mike
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Image constructor throws exception

Post by magick »

The default ImageMagick distribution is Q16, 16-bits per pixel component. You may need a constructor that specifies a depth of 8 otherwise its looking for 2 bytes per pixel instead of 1. Another option is to use the Q8 version of ImageMagick at 8-bits per pixel component.
mmuratet

Re: Image constructor throws exception

Post by mmuratet »

Hello again
A short test code:

Code: Select all

#include <iostream>
#include <Magick++.h>

unsigned short *imageData = new unsigned short[1000000];
#define IMAGE_WIDTH 1000
#define IMAGE_HEIGHT 1000
unsigned char outputImage[IMAGE_WIDTH * IMAGE_HEIGHT * 4];
int main (int argc, char * const argv[])
{
    std::cout << "Hello, World!\n";
    Magick::Image image( IMAGE_WIDTH, IMAGE_HEIGHT, "CMYK", Magick::ShortPixel, imageData ); 
    return 0;
}
I've been running this the debugger trying to sort the problem out. Note that I changed the data type to short. In the debugger I see:

Program received signal SIGSEGV, Segmentation fault.
ImportImagePixels (image=0xbd45770, x_offset=0, y_offset=0, columns=1000, rows=1000, map=<value optimized out>,
type=ShortPixel, pixels=0x2b409dfe8000) at magick/pixel.c:3315
3315 q->red=ScaleShortToQuantum(*p);
Current language: auto; currently c
(gdb) where
#0 ImportImagePixels (image=0xbd45770, x_offset=0, y_offset=0, columns=1000, rows=1000,
map=<value optimized out>, type=ShortPixel, pixels=0x2b409dfe8000) at magick/pixel.c:3315
#1 0x00002b409d279c3c in ConstituteImage (columns=1000, rows=1000, map=0xbd451e8 "CMYK", storage=ShortPixel,
pixels=0x2b409ddfe010, exception=0x7fff0d8bdf80) at magick/constitute.c:152
#2 0x00002b409d69bd5b in Magick::Image::read (this=0x7fff0d8be090, width_=1000, height_=1000,
map_=@0x7fff0d8be010, type_=MagickCore::ShortPixel, pixels_=0x2b409ddfe010) at Magick++/lib/Image.cpp:1619
#3 0x00002b409d69e47a in Image (this=0x7fff0d8be090, width_=1000, height_=1000, map_=@0x7fff0d8be0a0,
type_=MagickCore::ShortPixel, pixels_=0x2b409ddfe010) at Magick++/lib/Image.cpp:263
#4 0x0000000000400c5a in main (argc=1, argv=0x7fff0d8be1a8) at small_test_image.cpp:14
(gdb) print p
$1 = (const short unsigned int *) 0x2b409dfe8000

I note that the value of the pointer pixels is changed in the ImportImagePixels method while it is unchanged up to that call. If I decrease the size of the buffer from 1000000 to 10000 (i.e., 100x100 pixels of short) then the address _does_not_ change and the method runs to completion. This behavior baffles me. In my naivete I might believe that somehow a copy constructor got fouled up. Pass-by-reference is the norm for c++, isn't it? Can anybody suggest what might be going on here?

thanks

Mike
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Image constructor throws exception

Post by magick »

CMYK is 4 pixel components, whereas your imageData array only provides for 1 pixel component. Try this instead:
  • unsigned short *imageData = new unsigned short[4*1000000];
mmuratet

Re: Image constructor throws exception

Post by mmuratet »

Thanks. That was the problem.

I owe you a beer.

Mike
Post Reply