Print the pixel array from a bmp image - c++

So, I have a 24 bmp image saved in the memory and I want to print the array of pixels, I am using BITMAPFILEHEADER and BITMAPINFOHEADER for figuring out the header and info header of the bitmap, however when looking up documentation I see that the file header has a member called bfOffBits that should show the starting location of the pixels and I can get the size of the pixel array through info_header->Height and Width.
My issues is that when looking at the wikipedia (https://en.wikipedia.org/wiki/BMP_file_format#Bitmap_file_header) page I need to figure out the padding bytes size and the actual pixel bytes. But my image has a Width of 1152, I get that by printing:
BITMAPINFOHEADER* bitmap_info_header = NULL;
bitmap_info_header = (BITMAPINFOHEADER*)(file_info->file_address + sizeof(BITMAPFILEHEADER));
printf("Width %ld \n", bitmap_info_header->biWidth);
and i'm not sure if that means there is no padding? Also when starting to read the pixels I start from :
typedef struct
{
HANDLE file_handle;
HANDLE mapping_handle;
BYTE* file_address;
DWORD file_size;
}FILE_INFO;
file_info->file_address[bitmap_file_header->bfOffBits]
And I am not sure that is correct because reading through https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfoheader I find a "Colour table " that I haven't identified.
I just want to find out if there is padding or not and if I read from the correct address, as I get them mixed up a lot. thank you !

Related

Gray scale images processing in C++

How to read an image in C++ as a 2D array? I need to create a C/C++ program that reads an image (all formats) as a 2D array to show pixel values (0-255), divide the image into blocks and apply different compression methods using pixels blocks (BTC, AMBTC, MMBTC) and saving the new image by hand without using already set libraries (must not use magic++)..
thanks in advance
Here's some 'outline' code using MFC's CImage class that may help you. I've shown how to use the basic Load and Save options, and how to get a 'raw' array of pixel data (note: it's best to convert to 32-bit format, so you can be sure the DWORD pointer you get will really be to a width X height array - other BPP formats can give strange results):
First, load from file (CImage will know or guess the format from the file extension):
CImage original;
original.Load("Yourfile.jpg"); // Use actual file path, obviously
int pw = original.GetWidth(), ph = original.GetHeight(); // Dimensions
CImage working; // Use this to hold our 32-bit image
working.Create(pw, ph, 32);
// Next, copy image from original to working...
HDC hDC = working.GetDC();
original.BitBlt(hDC, 0, 0, SRCCOPY);
working.ReleaseDC();
// Get a DWORD pointer to the pixel data...
BITMAP bmp;
GetObject(working.operator HBITMAP(), sizeof(BITMAP), &bmp);
DWORD* pixbuf = static_cast<DWORD*>(bmp.bmBits);
// We can now access any pixel(x,y) data using: pixbuf[x + y * pw]
You now do all sorts of work on your image buffer, using the pixbuf array, as stated in the comment. For clarity: each DWORD (32-bit unsigned) in the buffer will be the RGBA data (where A is the 'alpha` channel - set to zero) but in reversed order; so, for each DWORD, the bytes will be 0xBBBBGGGGRRRR0000.
When you're done, you can save your modified image as follows:
CImage savepic;
savepic.Create(pw, ph, 24); // Change 24 to whatever BPP you require
hDC = savepic.GetDC();
working.BitBlt(hDC, 0, 0, SRCCOPY); // Copies modified image to output
savepic.ReleaseDC();
savepic.Save("NewFile.jpg"); // CImage understand what format to use base on extension
Of course, in a real-world program, there are error checks that you will need to make (most CImage methods return a status indicator, and GetLastError() can be used), and you would probably be safer copying the 'pixbuf' data to a separate memory zone - but, hopefully, this brief outline will help you get started.
Feel free to ask for further clarification and/or explanation.

OpenCV Cant load Bitmap (with extra stride bytes) from byte array

I have problem. When I'm loading mat from byte array there is a big problem; extra bytes cause mat to load wrong. If I send byte array ( width: 4-8-12-16-20 etc) It's not a problem because width and stride is equal. But If I byte array with extra stride bytes Image is corrupted. Is there a way to make it right ?
Function that I'm using:
Mat bytesToMat(byte * bytes,int height,int width)
{
Mat image = Mat(height,width,CV_8UC3,bytes).clone(); // make a copy
return image;
}
Example)
23 width image loaded as:
24 width image loaded (Correctly):
The link format was messed up in the comment, so I'll write an answer.
See the constructor step and steps parameters in the documentation. It lets you tell OpenCV how many bytes are in each row (including padding).
You'll also have to check if the byte array you're using as input has any added padding.

C++ VIDEOHDR to Image File in capVideoStreamCallback

I've been working on a Webcam video recorder and I got interested in trying everything when it comes to this topic but there's this problem that I can't solve.
Everything that you might wonder about can be found here
https://msdn.microsoft.com/en-us/library/windows/desktop/dd757677%28v=vs.85%29.aspx and here
https://msdn.microsoft.com/en-us/library/windows/desktop/dd757694%28v=vs.85%29.aspx
Now, in this code
if (capSetCallbackOnVideoStream(hCapWnd, capVideoStreamCallback))
{
capCaptureSequenceNoFile(hCapWnd); //Capture
}
I make sure that every frame that gets captured is sent to capVideoStreamCallback.
Now what I'm trying to do is transform a frame to an image and save it somewhere, this might be useless but it's interesting and it is surely possible.
Here is my capVideoStreamCallback function (it's commented):
LRESULT CALLBACK capVideoStreamCallback(HWND hWnd, LPVIDEOHDR lpVHdr)
{
BYTE *Image;
BITMAPINFO * TempBitmapInfo = new BITMAPINFO;
ULONG Size;
// First we need to get the full size of the image
Size = capGetVideoFormat(hWnd, TempBitmapInfo, sizeof(BITMAPINFO)); //header size
Size += lpVHdr->dwBytesUsed; //bytes used
Image = new BYTE[Size];
memcpy(Image, TempBitmapInfo, sizeof(BITMAPINFO)); //copy the header to Image
// lpVHdr is LPVIDEOHER passed into callback function.
memcpy(Image + sizeof(BITMAPINFO), lpVHdr->lpData, lpVHdr->dwBytesUsed); //copy the data to Image
//write the image
ofstream output("image.dib", ios::binary);
for (int i = 0; i < Size; i++)
{
output << (BYTE)Image[i];
}
output.close();
return (LRESULT)TRUE;
}
So, the information about every frame that gets sent to capVideoStreamCallback can be found in lpVHdr which is a structure (https://msdn.microsoft.com/en-us/library/windows/desktop/dd757688%28v=vs.85%29.aspx) and what I'm trying to do here is to take that information and transform it to an image.
I first start by getting the full size of the image by retrieving the size of the header and the size of the data and then I dynamically declared a BYTE Array called Image and copied the header and the data to Image using memcpy. I finally used ofstream to write the bytes to a file and that's pretty much it.
The problem is that everything works just fine but the image is somehow corrupted because it cannot be opened.
What is wrong in what I'm doing? It seems so logical but it's not working.
Please share your ideas and thanks for reading.
Here's the answer thanks to Frankie-C from http://codeproject.com who reminded me that I needed a BITMAPFILEHEADER structure at the top of the BITMAP File.
There's also few extra stuff that you need to do to get the image to show up the way it should be such as flipping bytes to get BGR instead of RGB etc, here's a nice tut explaining that: http://tipsandtricks.runicsoft.com/Cpp/BitmapTutorial.htm

Going from PNG data to tesseract

I am trying to move image data from Magick++ to tesseract.
I have the PNG data and some info about it.
And the signature for the tesseract method is:
void SetImage(const unsigned char* imagedata, int width, int height, int bytes_per_pixel, int bytes_per_line);
The first three arguments I can supply just fine. But bytes_per_pixel and bytes_per_line I'm not so sure about. The image itself has 11564 pixels but the length of the data is only 356 bytes... It's mostly a white image with some text. 11564/356 = 32.48 which obviously is not the correct bytes per pixel. How can I get the right bytes / pixel information? It's ok to just get that for one image on my desktop or something and set it as a constant, all the images I'm processing will have the same format.
Then as far as bytes per line, would that just be image width in pixels * bytes per pixel?
bytes_per_pixel can be obtained from PNG data. They are usually 8, 24 or 32.
bytes_per_line too, but you can compute it doing: bytes_per_pixel * width / 8

Bmp to raw strange problem

I have a strange problem in transform a stack of bmp images to raw file (unsigned char array) .This is the code :
for(int i=365;i<=385;i++)
{
sprintf(secondname,"C:\\tr\\tr_");
sprintf(secondtemp,"_%04d.bmp",i);
strcat(secondname,secondtemp);
cvSaveImage( secondname,out);
cvReleaseImage( &out );
IplImage* img2 = cvLoadImage( secondname,0);
memcpy(&im[xsize*ysize*(i-365)],img2->imageData,xsize*ysize);
}
outfile=fopen("C:\\Histo_Registration\\a.raw","wb");
fwrite((unsigned char*)im,1,(xsize)*(ysize)*(zsize),outfile);
fclose(outfile);
The problem is that when the images that i load is for example 512x512 the result raw is ok .When the images is 426x425 the result raw is strange is not for sure the correct one.Any idea?
Your code doesn't work with bitmap line alignment. See IplImage::widthStep member. You cannot copy the whole image in one memcpy call, if widthStep is not equal to (pixel size in bytes * line width in pixels).
Windows bitmaps are 32-bit aligned, this is why 512x512 image is OK, and 426x425 is wrong. For example, if image width = 11, and every pixel is 1 byte length, actual line width (widthStep) will be 12 (4 bytes alignment).
The length of each row in a BMP is a multiple of 4, if necessary the remaining bytes will be filled with 0. You need to take that into account.
See the Wikipedia article about the BMP file format for details.