i'm trying to copy values from QImage to my own image structure (because of school work), and I'am not able to figure out, how are pixels stored
API says that when using Format_Mono, The image is stored using 1-bit per pixel.
I created the following code:
QImage image(10,10,QImage::Format_Mono); // create 10x10 image
image.fill(1); // whiten the image
QPainter p;
p.begin(&image);
p.setPen(QPen(QColor(Qt::black)));
p.drawPoint(10,1); // make ONE point black
p.end();
uchar* pixels = image.constBits();
int count = image.byteCount(); // returns 40 !!
First thing: I don't understand why 40 bytes is used (I expected 20 will be more than enough - as would BufferedImage in java do)
Second thing: When iterating throuh pixels, every fourth(starting on third - indexes 2,6,10...) byte is set to 173 and every fourth(starting on fourth - indexes 3,7,11...) byte is set to 186.
Other bytes are correctly(??) set to 255 (white).
I expected 20 bytes, so 19 would be set 255, and one (with colored pixel [10,1] set to other value)
What am I missig? Thank you
API: The scanline data is aligned on a 32-bit boundary.
That was the reason ... the Qt documentation of the method bits() forgot to mention it...
Related
I have this code that converts an opencv image to a bitmap:
void processimage(MAT imageData)
{
Gdiplus::Bitmap bitmap(imageData.cols,imageData.rows,stride, PixelFormat24bppRGB,imageData.data);
// do some work with bitmap
}
It is working well when the size of image is 2748 X 3664. But I am tring to process an image wth size 1374 X 1832, it doesn't work.
The error is invalid parameter(2).
I checked and can confirm that:
in 2748 *3664:
cols=2748
rows=3664
stride= 8244
image is continues.
in 1374 X 1832
cols=1374
rows=1832
stride= 4122
image is continues.
So everything seems correct to me, but it generate error.
What is the problem and how can I fix it?
Edit
Based on answer which explained why I can not create bitmap. I finally implemented it in this way:
Mat newImage;
cvtColor(imageData, newImage, CV_BGR2BGRA);
Gdiplus::Bitmap bitmap(newImage.cols,newImage.rows,newImage.step1(), PixelFormat32bppRGB,newImage.data);
So effectively, I convert input image to a 4 byte per pixel and then use the convert it to bitmap.
All credits to Roger Rowland for his answer.
I think the problem is that a BMP format must have a stride that is a multiple of 4.
Your larger image has a stride of 8244, which is valid (8244/4 = 2061) but your smaller image has a stride of 4122, which is not (4122/4 = 1030.5).
As it says on MSDN for the stride parameter (with my emphasis):
Integer that specifies the byte offset between the beginning of one
scan line and the next. This is usually (but not necessarily) the
number of bytes in the pixel format (for example, 2 for 16 bits per
pixel) multiplied by the width of the bitmap. The value passed to this
parameter must be a multiple of four.
Assuming your stride is correct, I think you're only option is to copy it row by row. So, something like:
Great a Gdiplus::Bitmap of the required size and format
Use LockBits to get the bitmap pixel data.
Copy the OpenCV image one row at a time.
Call UnlockBits to release the bitmap data.
You can use my class CGdiPlus that implements all you need to convert from cv::Mat to Gdiplus::Bitmap and vice versa:
OpenCV / Tesseract: How to replace libpng, libtiff etc with GDI+ Bitmap (Load into cv::Mat via GDI+)
I am using WIC to load in an image and then I want to be able to get the RGB values of each pixel. I have got as far as using getDataPointer() to create a byte buffer (which I cast to a COLORREF array) but after this things get strange.
I have a 10x10 24bit png that I'm testing with. If I look at the size value getDataPointer() gives me it says it's 300, which makes sense because 10 * 10 * 3 (for 3 bytes per pixel) = 300. If I do getStride() it gives me 30, which also makes sense.
So I create a loop to go through the COLORREF with an iterator and the condition is i < size/3 because I know there are only 100 pixels in the array. I then use the macros GetRValue(), GetGValue() and GetBValue() to get the rgb values out.
This is when things go weird - My small image is just a test image with solid red, green, blue and black pixels in, but my RGB values come out (255, 0, 0), (0, 255, 0), (27, 255, 36), (0, 0, 0) etc. it seems that some values don't come out properly and are corrupted somehow. Also, the last 20/30 pixels of the image are either loads of crazy colors or all black making me think there some sort of corruption.
I also tested it with a larger actual photograph and this comes out all grayscale and repeating the same pattern, making me think it's a stride issue but I don't understand how because when I call getPixelFormat() WIC says it's 24bppBGR or 24bppRGB depending on the images.
Does anyone have any idea what I am doing wrong? Shouldn't I be using COLORREF and the macros or something like that?
Thanks for your time.
EDIT
Hmm I've still got a problem here. I tried with another 24bit PNG that PixelFormat() was reporting as 24bppBGR but it seems like the stride is off or something because it is drawing as skewed (obligatory nyan cat test):
EDIT 2
Okay so now it seems I have some that work and some that don't. Some reporting themselves as 24bpp BGR work while others look like the image above and if I calculate the stride it gives me compared to what it should be they are different and also the size of the buffer is different too. I also have some 32bpp BGR images and some of those work and others don't. Am I missing something here? What could make up the extra bytes in the buffer?
Here is an example image:
24bppBGR JPEG:
width = 126
height = 79
buffer size = 30018
stride = 380
If I calculate this:
buffer size should be: width * height * 3 = 126 * 79 * 3 = 29862
difference between calculation and actual buffer size: 30018 - 29862 = 156 bytes
stride size should be: width * 3 = 378
difference between calculation and actual buffer size: 380 - 378 = 2 bytes
I was thinking that we had 2 extra bytes per line but 79 * 2 is 158 not 156 hmm.
If I do these calculations for the images that have worked so far I find no difference in the calculations and the values the code gives me...
Am I understanding what is happening here wrong? Should these calculations now work as I have thought?
Thanks again
You shouldn't be using COLORREF and related macros. COLORREF is a 4-byte type, and you have 3-byte pixels. Accessing the data as an array of COLORREF values won't work. Instead, you should access it as an array of bytes with each pixel located at ((x + y * width) * 3). The order of individual channels is indicated by the format name. So if it's 24bppBGR you'd do data[(x + y * width) * 3] to get the blue channel, data[(x + y * width) * 3 + 1] for green, and data[(x + y * width) * 3 + 2] for red.
If you really want an array of pixels, you can make a structure with 3 BYTE fields, but since the meaning of those fields depends on the pixel format, that may not be useful.
In fact, you can't assume an arbitrary image will load as a 24-bit format at all. The number of formats you could get is larger than you could reasonably be expected to support.
Instead, you should use WICConvertBitmapSource to convert the data to a format you can work with. If you prefer to work with a COLORREF array and related macros, use GUID_WICPixelFormat32bppBGR.
I'm trying to work with this camera SDK, and let's say the camera has this function called CameraGetImageData(BYTE* data), which I assume takes in a byte array, modifies it with the image data, and then returns a status code based on success/failure. The SDK provides no documentation whatsoever (not even code comments) so I'm just guestimating here. Here's a code snippet on what I think works
BYTE* data = new BYTE[10000000]; // an array of an arbitrary large size, I'm not
// sure what the exact size needs to be so I
// made it large
CameraGetImageData(data);
// Do stuff here to process/output image data
I've run the code w/ breakpoints in Visual Studio and can confirm that the CameraGetImageData function does indeed modify the array. Now my question is, is there a standard way for cameras to output data? How should I start using this data and what does each byte represent? The camera captures in 8-bit color.
Take pictures of pure red, pure green and pure blue. See what comes out.
Also, I'd make the array 100 million, not 10 million if you've got the memory, at least initially. A 10 megapixel camera using 24 bits per pixel is going to use 30 million bytes, bigger than your array. If it does something crazy like store 16 bits per colour it could take up to 60 million or 80 million bytes.
You could fill this big array with data before passing it. For example fill it with '01234567' repeated. Then it's really obvious what bytes have been written and what bytes haven't, so you can work out the real size of what's returned.
I don't think there is a standard but you can try to identify which values are what by putting some solid color images in front of the camera. So all pixels would be approximately the same color. Having an idea of what color should be stored in each pixel you may understand how the color is represented in your array. I would go with black, white, reg, green, blue images.
But also consider finding a better SDK which has the documentation, because making just a big array is really bad design
You should check the documentation on your camera SDK, since there's no "standard" or "common" way for data output. It can be raw data, it can be RGB data, it can even be already compressed. If the camera vendor doesn't provide any information, you could try to find some libraries that handle most common formats, and try to pass the data you have to see what happens.
Without even knowing the type of the camera, this question is nearly impossible to answer.
If it is a scientific camera, chances are good that it adhers to the IEEE 1394 (aka IIDC or DCAM) standard. I have personally worked with such a camera made by Hamamatsu using this library to interface with the camera.
In my case the camera output was just raw data. The camera itself was monochrome and each pixel had a depth-resolution of 12 bit. Therefore, each pixel intensity was stored as 16-bit unsigned value in the result array. The size of the array was simply width * height * 2 bytes, where width and height are the image dimensions in pixels the factor 2 is for 16-bit per pixel. The width and height were known a-priori from the chosen camera mode.
If you have the dimensions of the result image, try to dump your byte array into a file and load the result either in Python or Matlab and just try to visualize the content. Another possibility is to load this raw file with an image editor such as ImageJ and hope to get anything out from it.
Good luck!
I hope this question's solution will helps you: https://stackoverflow.com/a/3340944/291372
Actually you've got an array of pixels (assume 1 byte per pixel if you camera captires in 8-bit). What you need - is just determine width and height. after that you can try to restore bitmap image from you byte array.
I am fairly new to image processing using Visual C++, I am in search of a way that reads black and white TIFF files and writes the image as an array hex values representing 0 or 1, then get the location information of either 0 (black) or 1 (white).
After a bit of research on Google and an article here https://www.ibm.com/developerworks/linux/library/l-libtiff/#resources I have the following trivial questions, please do point me to relevant articles, there are so many that I couldn’t wrap my heads around them, meanwhile I will keep on searching and reading.
Is it possible to extract pixel location information from TIFF using LIBTIFF?
Again being new to all image formats, I couldn't help to think that an image is made up of a 2D array of hex values , is the bitmap format more appropriate? Thinking in that way makes me wonder if I can just write the location of “white” or “black” mapped from its height onto a 2D array. I want the location of either “black” or “white”, is that possible? I don’t really want an array of 0s and 1s that represents the image, not sure if I even need them.
TIFF Example of a 4 by 2 BW image:
black white
white black
black black
white white
Output to something like ptLocArray[imageHeight][imageWidth] under a function named mappingNonPrint()
2 1
4 4
or under a function named mappingPrint()
1 2
3 3
With LIBTIFF, in what direction/ways does it read TIFF files?
Ideally I would like TIFF file to be read vertically from top to bottom, then shifts to the next column, then start again from top to bottom. But my gut tells me that's a fairy tale, being very new to image processing, I like to know how TIFF is read for example a single strip ones.
Additional info
I think I should add why I want the pixel location. I am trying to make a cylindrical roll printer, using a optical rotary encoder providing a location feedback The height of the document represents the circumference of the roll surface, the width of the document represent the number of revolutions.
The following is a grossly untested logic of my ENC_reg(), pretty much unrelated to the image processing part, but this may help readers to see what I am trying to do with the processed array of a tiff image. i is indexed from 0 to imageHeight, however, each element may be an arbitrary number ranging from 0 to imageHeight, could be 112, 354 etc that corresponds to whatever the location that contains black in the tiff image. j is indexed from 0 to imageWidth, and each element there is also starting 0 to imageWidth. For example, ptLocArray[1][2] means the first location that has a black pixel in column 2, the value stored there could be 231. the 231st pixel counting from the top of column 2.
I realized that the array[imageHeight][] should be instead array[maxnum_blackPixelPerColumn], but I don't know how to count the number of 1s, or 0s per column....because I don't know how to convert the 1s and 0s in the right order as I mentioned earlier..
void ENC_reg()
{
if(inputPort_ENC_reg == true) // true if received an encoder signal
{
ENC_regTemp ++; // increment ENC register temp value by one each time the port registers a signal
if(ENC_regTemp == ptLocArray[i][j])
{
Rollprint(); // print it
i++; // increment by one to the next height location that indicates a "black", meaning print
if (ENC_regTemp == imageHeight)
{
// Check if end of column reached, end of a revolution
j++; // jump to next column of the image (starting next revolution)
i = 0; // reset i index to 0, to the top of the next column
ENC_regTemp = 0; // reset encoder register temp to 0 for the new revolution
};
};
ENC_reg(); // recall itself;
};
}
As I read your example, you want two arrays for each column of the image, one to contain the numbers of rows with a black pixel in that column, the other with indices of rows with a white pixel. Right so far?
This is certainly possible, but would require huge amounts of memory. Even uncompressed, a single pixel of a grayscale image will take one byte of memory. You can even use bit packing and cram 8 pixels into a byte. On the other hand, unless you restrict yourself to images with no more than 255 rows, you'll have multiple bytes to represent each column index. And you'd need extra logic to mark the end of the column.
My point is: try working with the “array of 0s and 1s” as this should be both easier to accomplish, less demanding in terms of memory, and more efficient to run.
So I have a x8r8g8b8 formatted IDirect3DSurface9 that contains the contents of the back buffer. When I call LockRect on it I get access to a struct containing pBits, a pointer to the pixels I assume, and and integer Pitch (which I am very unclear about its purpose).
How to read the individual pixels?
Visual Studio 2008 C++
The locked area is stored in a D3DLOCKED_RECT. I haven't ever used this but the documentation says it is the "Number of bytes in one row of the surface". Actually people would normally call this "stride" (some terms explained in the MSDN).
For example, if one pixel has 4 bytes (8 bits for each component of XRGB), and the texture width is 7, the image is usually stored as 8*4 bytes instead of 7*4 bytes because the memory can be accessed faster if the data is DWORD-aligned.
So, in order to read pixel [x, y] you would have to read
uint8_t *pixels = rect.pBits;
uint32_t *mypixel = (uint32_t*)&pixels[rect.Pitch*y + 4*x];
where 4 is the size of a pixel. *myPixel would be the content of the pixel in my example.
Yep, you would access the individual RGB components of the pixel like that.
The first byte of the pixel is not used, but it is more efficient to use 4 Bytes per pixel, so that each pixel is aligned on a 32Bit boundary (that's also, why there's the pitch).
In your example, the x is not used, but note that there are lso other pixel formats, for example ARGB, which stores the alpha value (transparency) in the first byte. Sometimes the colors are also reversed (BGR instead of RGB). If you're unsure what byte corresponds to what color, a good trick is to create a texture which is entirely red, green or blue and then check which of the 4 bytes has the value 255.