Switch from Magick 6 --> Magick 7 with problems

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
Mihail
Posts: 3
Joined: 2017-08-18T15:39:43-07:00
Authentication code: 1151

Switch from Magick 6 --> Magick 7 with problems

Post by Mihail » 2017-08-18T16:15:37-07:00

Hi All,

I would have a question on you.
I switched from Magick 6 to Magick 7 and I have a problem: when I try to display an image I see a broken image (random pixels) and I think that is something related to Quantum type - when I use PixelPacket everything is fine, but when I use Quantum I get that problem.


I use VC++ 2013, Win7, 32bit

This is the code:

Code: Select all

		
		BITMAPINFOHEADER bmi;

		bmi.biSize = sizeof(BITMAPINFOHEADER);    // Size of structure
		bmi.biWidth = pDoc->image.columns();          // Bitmaps width in pixels
		bmi.biHeight = (-1)*pDoc->image.rows();       // Bitmaps height n pixels
		bmi.biPlanes = 1;                         // Number of planes in the image
		bmi.biBitCount = 32;                      // The number of bits per pixel
		bmi.biCompression = BI_RGB;               // The type of compression used
		bmi.biSizeImage = 0;                      // The size of the image in bytes
		bmi.biXPelsPerMeter = 0;                  // Horizontal resolution
		bmi.biYPelsPerMeter = 0;                  // Veritical resolution
		bmi.biClrUsed = 0;                        // Number of colors actually used
		bmi.biClrImportant = 0;                   // Colors most important
		

		InitializeMagick(NULL);

	
               //PixelPacket *pPixels = pDoc->image.getPixels(0, 0, pDoc->image.columns(), pDoc->image.rows()); // From Magick 6
		MagickCore::Quantum *pPixels = pDoc->image.getPixels(0, 0, pDoc->image.columns(), pDoc->image.rows());
		

		StretchDIBits(pDC->m_hDC,
			m_ptImagePos.x,
			m_ptImagePos.y,
			pDoc->image.columns(),
			pDoc->image.rows(),
			0,
			0,
			pDoc->image.columns(),
			pDoc->image.rows(),
			pPixels,
			(BITMAPINFO *)&bmi,
			DIB_RGB_COLORS,
			SRCCOPY);
This code works perfect when I use PixelPacket (and Magick 6), but it doesn't when I use Quantum (and Magick 7).

Some more details:

When I created the VC++ project, I had to use a configuration tool where I had to state the quantum depth. When I create a Q8 quantum depth project, the image contained a lot of random red pixels, also, when I created a Q16 quantum depth project I get a lot of random green pixels, and when I created a Q32 or Q64 quantum depth project, I get again a lot of random red pixels.

Do you have any idea what could be wrong?

Many thanks,
Mihail.

snibgo
Posts: 9379
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Switch from Magick 6 --> Magick 7 with problems

Post by snibgo » 2017-08-18T17:03:10-07:00

Your v6 code assumes that IM's getPixels() returns data in the same format as Microsoft StretchDIBits wants the data.

That's a dangerous assumption, and is false in v7.

The safe way to do it is to create an array for lpBits and loop through y and x, using GetPixelRed and so on to get IM's values, to put into the array you have created.

To get greater performance, you can check whether the IM and Microsoft structures are identical. If they are, then you can use one directly in the place of the other.

But assuming they are the same would often fail under v6, as well as v7.

EDIT to add: You might find IM's ExportImagePixels() function useful to get pixel data into a known format.
snibgo's IM pages: im.snibgo.com

Mihail
Posts: 3
Joined: 2017-08-18T15:39:43-07:00
Authentication code: 1151

Re: Switch from Magick 6 --> Magick 7 with problems

Post by Mihail » 2017-08-19T10:52:53-07:00

Thank you for the answer!

I tried to use ExportImagePixels(), but, In my application I use Magick::Image and not MagickCore::Image - it seems that ExportImagePixels wants MagickCore::Image as first parameter, and I get an error. Also, GetPixelRed/Green/Blue works only with MagickCore::Image. I didn't manage to convert from one type to another.

Anyway, I would have another question:

In v6, when I want to add a value to the RGB pixels of an image I do like this:

Code: Select all

			
			Image image;
			image.read("PATH_TO_MY_IMAGE");
			
			Pixels view(image);
			PixelPacket *pixels = view.get(0, 0, width, height);
			
			int height = image.rows();
			int width = image.columns();

			const int size= width * height;

			for (int i = 0; i < size; i++)
			{
				int r = pixels->red;
				int g = pixels->green;
				int b = pixels->blue;

				r = r + myValue;
				g = g + myValue;
				b = b + myValue;

				pixels->red = r;
				pixels->green = g;
				pixels->blue = b;

				pixels++;
			}
Could you tell me how can I do the same thing in v7? (Also, I need to work with Magick::Image and not MagickCore::Image - because Magick::Image has some functions that I need, like brightness, contrast, blur, etc.)

Thank you again,
Mihail.

snibgo
Posts: 9379
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Switch from Magick 6 --> Magick 7 with problems

Post by snibgo » 2017-08-19T11:26:00-07:00

As you can tell, I mostly use MagickCore, not MagickWand.

Is there any difference between Magick::Image and MagickCore::Image?

MagickWand has equivalent functions for most MagickCore functions, often with the same name but with "Magick" in front. If you had grepped the source code for "ExportImagePixels", you would have found "MagickExportImagePixels".

On pixel access in v7, I suggest you read http://www.imagemagick.org/script/porting.php
snibgo's IM pages: im.snibgo.com

Mihail
Posts: 3
Joined: 2017-08-18T15:39:43-07:00
Authentication code: 1151

Re: Switch from Magick 6 --> Magick 7 with problems

Post by Mihail » 2017-08-20T05:43:50-07:00

Is there any difference between Magick::Image and MagickCore::Image?

Good question, anyway, it seems that exist since I wasn't able to convert from one type to another :D

Finally, I manage to transfer all pixels from Quantum to lpBits. In PixelPacket (v6), pixels are represented as RGB, since in Quantum (v7) are BGR. So, I had to change the order. This is the code:

Code: Select all

	Quantum *pPixels = pDoc->image.getPixels(0, 0, pDoc->image.columns(), pDoc->image.rows());

		int height = pDoc->image.rows();
		int width = pDoc->image.columns();

		const int lenght = width * height;

		unsigned char *lpBits = new unsigned char[lenght * 4]; 


		int index = 0, inx = 0;
		for (int y = 0; y < height; y++)
		{
			for (int x = 0; x < width; x++)
			{			
				lpBits[index+2] = pPixels[inx];  index++; inx++;
				lpBits[index]    = pPixels[inx];   index++; inx++;
				lpBits[index-2] = pPixels[inx];   index++; inx++;

				lpBits[index] = 255; /*Alpha*/  index++;
			}
		}
There is another way to copy pixels from image to lpBits:

Code: Select all

		
		int height = pDoc->image.rows();
		int width = pDoc->image.columns();

		const int lenght = width * height;

		unsigned char *lpBits = new unsigned char[lenght * 4];

		for (int y = 0; y < height; y++)
		{
			for (int x = 0; x < width; x++)
			{			
				Magick::Color color = pDoc->image.pixelColor(x, y);

				unsigned char r = color.quantumRed();
				unsigned char g = color.quantumGreen();
				unsigned char b = color.quantumBlue();
				unsigned char a = color.quantumAlpha();

				lpBits[index] = b; index++;
				lpBits[index] = g; index++;
				lpBits[index] = r; index++;
				lpBits[index] = a; index++;
			}
		}
An interesting fact:
I measured the speed of execution of both above methods: (Intel 3.1 Ghz, RAM = 3GB, using a JPG image of 1600x1200 pixels)
1. First method = 0.015 seconds
2. Second method = 10.5 seconds

Conclusion: first method is 700X faster than second one. We never ever should use pixelColor() and quantumRed/Green/Blue.

snibgo
Posts: 9379
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Switch from Magick 6 --> Magick 7 with problems

Post by snibgo » 2017-08-20T06:26:11-07:00

pixelColor() calls getConstPixels() which calls GetVirtualPixels() which goes away and fills a cache with the block of pixels you want, and this might need disk access. But the block is only 1x1, so it does this for every pixel, which is massively slow.

pixelColor() is a good function when you want a few random accesses to some pixels. If you are visiting every pixel in an image, I suggest you look at http://www.imagemagick.org/Magick++/Ima ... l%20Access
snibgo's IM pages: im.snibgo.com

johnvicky
Posts: 1
Joined: 2017-08-22T01:09:47-07:00
Authentication code: 1151

Re: Switch from Magick 6 --> Magick 7 with problems

Post by johnvicky » 2017-08-22T01:18:05-07:00

snibgo wrote:
2017-08-20T06:26:11-07:00
pixelColor() calls getConstPixels() which calls GetVirtualPixels() which goes away and fills a cache with the block of pixels you want, and this might need disk access. But the block is only 1x1, so it does this for every pixel, which is massively slow.

pixelColor() is a good function when you want a few random accesses to some pixels. If you are visiting every pixel in an image, I suggest you look at http://www.imagemagick.org/Magick++/Ima ... l%20Access
I solved this problem ! thank :)

Post Reply