I'm working with some scanner api which returns a HANDLE to an image in BMP format(so it is said so in documentation). I'm trying to somehow get BITMAP from this handle, but for example this code doesn't work:
HANDLE handle = getHandleFromScanner();
BITMAP bitmap;
int u = GetObject(handle, sizeof(BITMAP), &bitmap);
u is 0 here and getLastError() returns 6 which means that handle is invalid. But I cannot get any other handle except through getHandleFromScanner() function.
May be some transformations should be done with this handle? any ideas? What is the proper way to work with bitmap handles? Or any simple api exists? Samples I found via google didn't help me.
Thanks a lot.
Have you tried GetDIBits()? This should work but you'll need the device context as well. You may always want to call GetObjectType() on the handle to see if it is really returning an HBITMAP.
Thanks guys.
The handle appeared to be the image itself, so the following code solved the problem:
char* pImage = NULL;
HANDLE hImage= getHandleFromScanner();
pImage = (char *)GlobalLock(hImage);
// pImage now contains the bytes of the image
If someone will ever need it, the Scanner is Olivetti PR2 plus scanner.
Related
I am trying to load an image resource using the LoadImageA() function, yet it doesn't work and I don't understand why.
Here's a bit of my code :
bool isRessource = IS_INTRESOURCE(107);
// Load the resource to the HGLOBAL.
HGLOBAL imageResDataHandle = LoadImageA(
NULL,
MAKEINTRESOURCEA(107),
IMAGE_BITMAP,
0,
0,
LR_SHARED
);
HRESULT hr = (imageResDataHandle ? S_OK : E_FAIL);
The image I want to load is a bitmap saved in the resources, and represented as such within resources.h:
#define IDB_BITMAP1 107
When I execute the code, isRessource is equal to true, yet hr is equal to E_FAIL.
Any idea as to why this is happening? I am using Visual Studio 2019, and I made the image using Gimp.
After making the same image with the same format on another application (I used "Krita") and importing it again, the image finally loads with the same code (I only changed the reference to the resource). I guess that all types of bitmaps made from Gimp won't work in Visual Studio (I tried most formats of bitmaps from Gimp).
The first link searched with LoadImage gimp as a keyword is enough to answer this question.
This is some useful information:
The bitmap exported by GIMP has a broken header. Specifically, the
code seems to not write the RGBA masks, which AFAIK are not optional
in a BITMAPV5HEADER. This misaligns and changes the size of the entire
extended header, incidentally making it look like a BITMAPV4HEADER,
which explains why most programs will still open it fine. Without
having done any testing, I'd guess LoadImage() is more picky about the
values in this extended header; returning NULL is how it indicates
failure.
By the way, when you import a bitmap, the system does not remind you that the format of the image is unknown?
Like:
After testing, use LoadImage to load such an image will return NULL, and GetLastError will also return 0.
Previously, I was looking to output frames rendered by UE4 to file.
I managed to do this and the details can be found in this StackOverflow post
The function to out put the frame to file is:
FScreenshotRequest::RequestScreenshot(filename, false, false);
Now, instead of writing to file, I would like to write to memory. I don't want to write to file and then read into memory.
I have been digging through the source code and found where screenshots are being made, but am having some trouble.
ViewportClient->ProcessScreenShots(this); is being called on line 1012 of UnrealClient.cpp
Following that, I found that the screenshot is actually being generated here:
bScreenshotSuccessful = GetViewportScreenShot(InViewport, Bitmap);
So, after finding all the bits that I think I need, I tried to recreate it in a custom Actor:
UGameViewportClient* gameViewport = GEngine->GameViewport;
FViewport* InViewport = gameViewport->Viewport;
TArray<FColor> Bitmap;
bool bScreenshotSuccessful = GetViewportScreenShot(InViewport, Bitmap);
if (bScreenshotSuccessful){
FIntVector Size(InViewport->GetSizeXY().X, InViewport->GetSizeXY().Y, 0);
TArray<uint8> CompressedBitmap;
FString ScreenShotName = TEXT("out.png");
FImageUtils::CompressImageArray(Size.X, Size.Y, Bitmap, CompressedBitmap);
FFileHelper::SaveArrayToFile(CompressedBitmap, *ScreenShotName);
}
For some reason, bool bScreenshotSuccessful = GetViewportScreenShot(InViewport, Bitmap); throws an Access violation reading location 0x0000000000000020. exception.
I think the error has something to do with this line:
Viewport->ReadPixels(Bitmap, FReadSurfaceDataFlags(), ViewRect)
I've treid 'googeling' for what an 'Access violation' is, and it seems it is something to do with a null pointer or something like that, but I am still not able to figure this out as I'm rather new to c++.
Question
How can I fix this so that bScreenshotSuccessful is true?
NOTE: I realise that FFileHelper::SaveArrayToFile(CompressedBitmap, *ScreenShotName); attempts to save to file, despite me saying that is not what I want to do, so please ignore that as if I have the bitmap, I can compress and stream it.
You have ViewRect just of three points instead of four and in wrong format. Try this snippet:
FIntRect Rect(0, 0, InViewport->GetSizeXY().X, InViewport->GetSizeXY().Y);
bScreenshotSuccessful = GetViewportScreenShot(InViewport, Bitmap, Rect);
How can I load a jpg into a CBitmap where I am using visual c++ 6.0 and don't have access to CImage?
thx
I would simply call OleLoadPicturePath api to load not just jpg but other common formats also.
After loading it into the IPicture object you can call get_Handle to get the handle to HBITMAP.
Thanks
There's no native way I know of. I've always used FreeImage for JPGs and PNGs - it's robust and there's example code in the FAQ on how to load a PNG into an HBITMAP (which works exactly the same for a JPG).
One word of warning from experience - if you're storing your JPG as a resource, make sure you create a "JPG" resource type and store it as that, don't try and add it as a BITMAP resource or you'll have all sorts of problems trying to load it. I know it sounds obvious but it took me a while to figure out.
You can't, or at least, there isn't a build-in way. Have a look at CxImage, you can probably get that to work, especially when you only need jpg support.
This kind of conversion is complex so i would reccoment using an external libary, take a look at this.
CBitmap bmp;
HANDLE h = ::LoadImage(NULL, _T("c:\\MyImage.jpg"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
bmp.Attach(h);
I can find a couple ways to create a cursor in win32 but I need the third, the one I can't find.
The first I can find is to use LoadXXX() to open a file or resource and load the cursor that way.
The second I can find is to use CreateCursor to take the hot-spot points, some data arrays, and make one out of bits.
I want the third way that's between the two: I have an array of bytes that contains a .cur file data. I want to use that data to make a cursor. Can this be done?
As I more briefly posted in a comment, I think the easiest and most sensible way is to just write the binary data stored in the array out to a temporary .CUR file on disk, and then use the LoadCursorFromFile function to read that .CUR file. You can then remove the temporary file. There's no reason to go hunting for complicated solutions when simpler ones will do.
That being said, if you really need a way to do this, you might consider doing something similar to what the .NET Framework team did to load a cursor object from a memory stream. This takes advantage of the similarity between cursors and icons.
Use the OleCreatePictureIndirect function to create a new uninitialized IPicture object, which you then initialize from your array of bytes in memory via the IPersistStream::Load method. Once you've done that, just use the CopyImage function to create a cursor from the loaded image.
Arguments to CreateCursor() are here: http://msdn.microsoft.com/en-us/library/ms648385(VS.85).aspx
HCURSOR WINAPI CreateCursor(
__in_opt HINSTANCE hInst,
__in int xHotSpot,
__in int yHotSpot,
__in int nWidth,
__in int nHeight,
__in const VOID *pvANDPlane,
__in const VOID *pvXORPlane
);
The .cur file format is documented on Wikipedia here: http://en.wikipedia.org/wiki/ICO_(file_format)#Legacy_format
You can get all the arguments to CreateCursor() out of that icon file header; I think the pointer to the image data probably has a bitmap for the and plane directly followed by a bitmap for the xor plane.
Whilst looking for the answer to this, I stumbled across CreateIconIndirect, which "Creates an icon or cursor from an ICONINFO structure" that specifies a bitmap handle (HBITMAP) for the cursor image (so you can use the Win32 API bitmap routines to prepare the cursor):
https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-createiconindirect
HICON CreateIconIndirect(
PICONINFO piconinfo
);
Though its return type is HICON, the documentation says it returns an icon or cursor.
The ICONINFO structure has a boolean fIcon member to determine whether it is an icon (TRUE) or a cursor (FALSE):
typedef struct _ICONINFO {
BOOL fIcon;
DWORD xHotspot;
DWORD yHotspot;
HBITMAP hbmMask;
HBITMAP hbmColor;
} ICONINFO;
I've not yet used this in my program and realise this is a really old question, but hopefully it will point anyone else that is trying to do this in the right direction.
Can't be done. Best not to waste time trying. I was only trying to avoid having to convert a bunch of .cur files to something that sensible libraries support. Thought I'd use the HCURSOR constructor for QCursor, and I could, but it's just not worth the f'n bother trying to work around the worse imaginable API when I can just use PNG files or something.
Bitmap bff(L"1.jpg");
bff.Save(L"2.jpg", &Gdiplus::ImageFormatJPEG, NULL);
This creates a new file 2.jpg with zero-bytes length.
Isn't it supposed to write an image file that is identical to 1.jpg?
Why I'm having zero-bytes length files?
I'm doing this test because writing other Bitmaps to files, result in the same output.
Here's a fast way to save it, since GetEncoderClsid is a custom function:
//Save to PNG
CLSID pngClsid;
CLSIDFromString(L"{557CF406-1A04-11D3-9A73-0000F81EF32E}", &pngClsid);
bmp.Save(L"file.png", &pngClsid, NULL);
and here's IDs for other formats:
bmp: {557cf400-1a04-11d3-9a73-0000f81ef32e}
jpg: {557cf401-1a04-11d3-9a73-0000f81ef32e}
gif: {557cf402-1a04-11d3-9a73-0000f81ef32e}
tif: {557cf405-1a04-11d3-9a73-0000f81ef32e}
png: {557cf406-1a04-11d3-9a73-0000f81ef32e}
&Gdiplus::ImageFormatJPEG is the wrong value to send as the second parameter (thus why the new file is zero bytes large). Take a look at the code example at the bottom of the Image::Save() reference page which demonstrates the proper usage of Save().
AFAIK, you can't just pass the image format GUID ('ImageFormatJPEG' in your case) to 'Image::Save' method. The second argument is supposed to hold the encoder GUID, not a format GUID. See an example here