GDI+ Bitmap Save problem - c++

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

Related

Cannot get an image handle from a bitmap within the resources when using "LoadImageA()" and cannot understand why

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.

C++ - Loading Base64 Encoded String of an image to Boost GIL image/view

I'm using Boosts Generic Image Library. I'm being given a string representation of an image. After decoding it, could I directly make an Image or View object with that data? Or would I need to write the data to the computer as example.png and use GIL's read_image functions? The documentation mentions dynamic images but still takes a filename as a parameter to the i/o functions.
I would ideally be looking for a function that takes a string or byte array as a parameter rather than the image name to be loaded from disk. Something like GDI+ FromStream. I see that the documentation says "All functions take the filename or a device as the first parameter. A device could be a FILE*, std::ifstream, and TIFF*." Maybe it is possible to edit the contents of an ifstream to have the image data, not sure if this is actually possible though.

Saving output frame as an image file CUDA decoder

I am trying to save the decoded image file back as a BMP image using the code in CUDA Decoder project.
if (g_bReadback && g_ReadbackSID)
{
CUresult result = cuMemcpyDtoHAsync(g_bFrameData[active_field], pDecodedFrame[active_field], (nDecodedPitch * nHeight * 3 / 2), g_ReadbackSID);
long padded_size = (nWidth * nHeight * 3 );
CString output_file;
output_file.Format(_T("image/sample_45.BMP"));
SaveBMP(g_bFrameData[active_field],nWidth,nHeight,padded_size,output_file );
if (result != CUDA_SUCCESS)
{
printf("cuMemAllocHost returned %d\n", (int)result);
}
}
But the saved image looks like this
Can anybody help me out here what am i doing wrong .. Thank you.
After investigating further, there were several modifications I made to your approach.
pDecodedFrame is actually in some non-RGB format, I think it is NV12 format which I believe is a particular YUV variant.
pDecodedFrame gets converted to an RGB format on the GPU using a particular CUDA kernel
the target buffer for this conversion will either be a surface provided by OpenGL if g_bUseInterop is specified, or else an ordinary region allocated by the driver API version of cudaMalloc if interop is not specified.
The target buffer mentioned above is pInteropFrame (even in the non-interop case). So to make an example for you, for simplicity I chose to only use the non-interop case, because it's much easier to grab the RGB buffer (pInteropFrame) in that case.
The method here copies pInteropFrame back to the host, after it has been populated with the appropriate RGB image by cudaPostProcessFrame. There is also a routine to save the image as a bitmap file. All of my modifications are delineated with comments that include RMC so search for that if you want to find all the changes/additions I made.
To use, drop this file in the cudaDecodeGL project as a replacement for the videoDecodeGL.cpp source file. Then rebuild the project. Then run the executable normally to display the video. To capture a specific frame, run the executable with the nointerop command-line switch, eg. cudaDecodGL nointerop and the video will not display, but the decode operation and frame capture will take place, and the frame will be saved in a framecap.bmp file. If you want to change the specific frame number that is captured, modify the g_FrameCapSelect = 37; variable to some other number besides 37, and recompile.
Here is the replacement for videoDecodeGL.cpp I used pastebin because SO has a limit on the number of characters that can be entered in a question body.
Note that my approach is independent of whether readback is specified. I would recommend not using readback for this sequence.

WIC WINCODEC_ERR_BADHEADER only for JPEG images

I have a simple encoding/ decoding application using Windows Imaging Component API. The issue I'm having is that when I use either the JPEGXR or BMP formats, everything works fine. However, when I use the JPEG codec - the encoder works fine and I can visually verify the generated JPEG image, but when I try to decode that stream, I get a WINCODEC_ERR_BADHEADER (0x88982f61)
Here's the line that fails:
hr = m_pFactory->CreateDecoderFromStream(
pInputStream,
NULL,
WICDecodeMetadataCacheOnDemand,
&pDecoder);
Here pInputStream is an IStream created from a byte array (output of the encoder - a black box which outputs a byte vector).
Please help! This is driving me nuts!
When passing stream as an argument, make sure to pre-seek it to proper initial position (esp. seek it back to the beginning if you just wrote data into it and expect further retrieval). APIs are typically not expected to seek, because this way they let you provide data in the middle of a bigger stream.

How do you copy/paste image data?

Using C++ and the WinAPI, how do I copy the image data from a pre-loaded image into the clipboard?
You need to create an object that implements IDataObject, and then place it on the clipboard using OleSetClipboard.
When you place data in the clipboard you have the ability to specify multiple formats. This is so that the application reading the clipboard can enumerate the formats and decide which one to use.
There are quite a few "standard" clipboard formats (with known constant values), e.g.:
CF_BITMAP: A handle to a bitmap (HBITMAP).
CF_DIB: A memory object containing a BITMAPINFO structure followed by the bitmap bits.
CF_DIBV5: A memory object containing a BITMAPV5HEADER structure followed by the bitmap color space information and the bitmap bits.
You can also register custom formats using RegisterClipboardFormat. Office exposes images as a number of different formats that they've registered, e.g.:
DWORD CF_PNG = RegisterClipboardFormat("PNG");
DWORD CF_JFIF = RegisterClipboardFormat("JFIF");
DWORD CF_GIF = RegisterClipboardFormat("GIF");
DWORD CF_ENHMETAFILE = RegisterClipboardFormat("CF_ENHMETAFILE");
DWORD CF_METAFILEPICT = RegisterClipboardFormat("CF_METAFILEPICT ");
The EditCopy function on this page of MSDN gives a good example of what you want to achieve:
http://msdn.microsoft.com/en-us/library/ms649016(v=vs.85).aspx
You will need to change the data type from CF_TEXT to CF_BITMAP in order to tell windows it is of an bitmap mime type.