Page 1 of 1

Create Image instance from in-memory monochrome data

Posted: 2010-06-08T01:35:18-07:00
by komuta
Hi,

Is it possible to create an Image instance from in-memory data when it is stored as monochrome 1 pixel-per-bit array ?
I can't find any working configuration in the primitive Image(const size_t width_, const size_t height_, std::string map_, const StorageType type_, const void *pixels_). However, the library is capable of loading such image formats, therefore I suppose it should be possible from in-memory raw buffer.

Thanks in advance.

Re: Create Image instance from in-memory monochrome data

Posted: 2010-06-15T12:32:58-07:00
by anotherprogrammer123
Hi, I have this problem also. I found this thread through a search.

The only thing I can think of is converting to Windows DIB and using that but it seems like it won't work.

Re: Create Image instance from in-memory monochrome data

Posted: 2010-06-15T13:18:22-07:00
by anotherprogrammer123
I found an ...extremely inefficient... solution!
However, I am sure there is a better solution, so please let me know!!
EDIT: Thinking about it, maybe I could manually setPixel() for every pixel in ImageMagick? Does anyone know how to do this efficiently?

Code: Select all

void myImage::copyToMagick(Magick::Image &magickImage) const
{
	myImage temp = *this;

	//we need to resize to 1 byte per pixel..
	temp._pixelBuffer = (BYTE*)realloc((void*)temp._pixelBuffer, getLength()*getHeight());
	for (unsigned int y = 0; y < getHeight(); y++)
	{
		for (unsigned int x = 0; x < getLength(); x++)
		{
			//'curPix' is 0 if black. 1 if white. BYTE is actually like one bit. I used it instead of bool
			BYTE curPix = this->_getPixelDirect(x, y);
			curPix = (curPix == 0) ? 255 : 0;
			*(temp._pixelBuffer + y*getLength() + x) = curPix;
		}
	}
	//Write in black color space
	magickImage.read(temp.getLength(), temp.getHeight(), "K", MagickLib::CharPixel, temp._pixelBuffer);
}

Re: Create Image instance from in-memory monochrome data

Posted: 2010-06-15T17:27:01-07:00
by anotherprogrammer123
Okay, I updated the code to be more efficient (directly set each pixel) but am getting weird errors (I think it has to do with MagickLib::BilevelType because MagickLib::TrueColorType causes no error, but I assume BilevelType is more efficient):

Code: Select all

.
.
.
First-chance exception at 0x76ec75ff in Scrap 2.exe: 0xC0000005: Access violation reading location 0xdddddde1.
First-chance exception at 0x76e79f17 in Scrap 2.exe: 0xC0000005: Access violation reading location 0xdddddddd.
First-chance exception at 0x76ec75ff in Scrap 2.exe: 0xC0000005: Access violation reading location 0xdddddde1.
The program '[1116] Scrap 2.exe: Native' has exited with code 702 (0x2be).
Please explain why or correct my code: (why BilevelType does not work but TrueColorType does?)

Code: Select all

void myImage::copyToMagick(Magick::Image &magickImage) const
{
	//Create a blank image with the same dimensions as this image
	magickImage = Magick::Image(Magick::Geometry(getLength(), getHeight()), Magick::Color(255, 255, 200));

	//Prepare to modify the image
	magickImage.modifyImage();

	//Set the image type to bilevel (black-and-white, 1 bit per pixel). IF WE CHANGE TO 'TrueColorType' NO ERROR!
	magickImage.type(MagickLib::BilevelType);

	//Get the pixel cache
	MagickLib::PixelPacket* magickPixels = magickImage.getPixels(0, 0, getLength(), getHeight());

	//Copy each pixel individually to 'magickImage'
	for (unsigned int y = 0; y < getHeight(); y++)
	{
		for (unsigned int x = 0; x < getLength(); x++)
		{
			//The current pixel in the original image
			BYTE curPix = this->_getPixelDirect(x, y);
			//Convert it to magick++ representation (black is 0. white is 255)
			curPix = (curPix == BLACK_PIXEL) ? 0 : 255;

			//The current pixel in 'magickImage'
			MagickLib::PixelPacket* curMagickPix = magickPixels + (y*getLength() + x);

			//Set the color of this pixel to 'curPix'
			curMagickPix->blue = curMagickPix->green = curMagickPix->red = curPix;
			curMagickPix->opacity = 0;
		}
	}

	//Save the changes to the magick image
	magickImage.syncPixels();
}

Re: Create Image instance from in-memory monochrome data

Posted: 2010-06-16T00:56:52-07:00
by komuta
You say that BilevelType image is "black-and-white, 1 bit per pixel". But in when modifying, you're accessing pixels as byte, not as bit.

Re: Create Image instance from in-memory monochrome data

Posted: 2010-06-16T10:07:02-07:00
by anotherprogrammer123
komuta wrote:You say that BilevelType image is "black-and-white, 1 bit per pixel". But in when modifying, you're accessing pixels as byte, not as bit.
Yeah, but ImageMagick apparently stores every pixel in 4 bytes no matter the type (for portability between a trillion different image formats).

Re: Create Image instance from in-memory monochrome data

Posted: 2010-06-16T18:52:52-07:00
by anthony
anotherprogrammer123 wrote:
komuta wrote:You say that BilevelType image is "black-and-white, 1 bit per pixel". But in when modifying, you're accessing pixels as byte, not as bit.
Yeah, but ImageMagick apparently stores every pixel in 4 bytes no matter the type (for portability between a trillion different image formats).
That is true though it is 3 or 4 numbers not bytes. The 4th depends on if you have a transparency channel. The actual number of bytes depends on your IM quality setting. Q16 will use 2-byte integers per number. Q8 on byte per number, A HDRI version of IM uses floating point 'doubles' for the number.

The various MagickCore methods extract the image values into one of two pixel data types for processing. The best idea is to go though the image row by row.

This is all documented in the 'Architecture' page on the IM website.
http://www.imagemagick.org/script/architecture.php

Re: Create Image instance from in-memory monochrome data

Posted: 2010-06-17T20:25:29-07:00
by anotherprogrammer123
Thanks for the information about the storage and the link, but why does my code above not work with BilevelType?

Re: Create Image instance from in-memory monochrome data

Posted: 2010-06-17T21:04:45-07:00
by anthony
bilevel is just binary. Pure black and white, no colors saved in the file.

See Im Examples. Common File Formats, TIFF
http://www.imagemagick.org/Usage/formats/#tiff

Re: Create Image instance from in-memory monochrome data

Posted: 2010-06-18T15:15:48-07:00
by anotherprogrammer123
anthony wrote:bilevel is just binary. Pure black and white, no colors saved in the file.
I tried this, but all pixels become white!

Code: Select all

 
	//Set the image type to bilevel (black-and-white, 1 bit per pixel)
	magickImage.type(MagickLib::BilevelType);
	//The current pixel in 'magickImage'
         MagickLib::PixelPacket* curMagickPix = magickPixels + (y*getLength() + x);

         //Set the color of this pixel to 'curPix'
         curMagickPix->blue = curMagickPix->green = curMagickPix->red = curPix;
         memset(curMagickPix, curPix, sizeof(curMagickPix));