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.
Related
I am new to DirectShow API.
I want to decode a media file and get uncompressed RGB video frames using DirectShow.
I noted that all such operations should be completed through a GraphBuilder. Also, every the processing block is called a filter and there are many different filters for different media files. For example, for decoding H264 we should use "Microsoft MPEG-2 Video Decoder", for AVI files "AVI Splitter Filter" etc.
I would like to know if there is a general way (decoder) that can handle all those file types?
I would really appreciate if someone can point out an example that goes from importing a local file to decoding it into uncompressed RGB frames. All the examples I found are dealing with window handles and they just configure it and call pGraph->run(). I have also surfed through Windows SDK samples, but couldn't find useful samples.
Thanks very much in advance.
Universal DirectShow decoder in general is against the concept of DirectShow API. The whole idea is that individual filters are responsible for individual task (esp. decoding certain encoding or demultiplexing certain container format). The registry of the filters and Intelligent Connect let one to have the filters built in chain to do certain requested processing, in particular decoding from compressed format to 24-bit RGB for video.
From this standpoint you don't need a universal decoder and it is not expected that such decoder exists. However, such decoder (or close) does exist and it's a ffdshow or one of its derivatives. Presently, you might want to look at LAVFilters, for example. They wrap FFmpeg, which itself can handle many formats, and connect it to DirectShow API so that, as as filter, ffdshow could handle many formats/encodings.
There is no general rule to use or not use such codec pack, in most cases you take into consideration various factors and decide what to do. If your application handles various scenarios, a good starting point into graph building would be Overview of Graph Building.
My goal is to accomplish the task using DirectShow in order to have no external dependencies. Do you know a particular example that does uncompressing frames for some file type?
Your request is too broad and in the same time typical and, to some extent, fairy simple. If you spend some time playing with GraphEdit SDK tool, or rather GraphStudioNext, which is a more powerful version of the former, you will be able to build filter graph interactively, also render media files of different types and see what filters participate in rendering. You can accomplish the very same programmatically too, since the interactive actions basically all have matching API calls individually.
You will be able to see that specific formats are handled by different filters and Intelligent Connect mentioned above is building chains of filters in combinations in order to satisfy the requests and get the pipeline together.
Default use case is playback, and if you want to get video rendered to 24/32-bit RGB, your course of actions is pretty much similar: you are to build a graph, which just needs to terminate with something else. More flexible, sophisticated and typical for advanced development approach is to supply a custom video renderer filter and accept decompressed RGB frames on it.
A simple and so much popular version of the solution is to use Sample Grabber filter, initialize it to accept RGB, setup a callback on it so that your SampleCB callback method is called every time RGB frame is decompressed, and use Sample Grabber in the graph. (You will find really a lot of attempts to accomplish that if you search open source code and/or web for keywords ISampleGrabber, ISampleGrabberCB, SampleCB or BufferCB, MEDIASUBTYPE_RGB24).
Using the Sample Grabber
DirectShow: Examples for Using SampleGrabber for Grabbing a Frame and Building a VU Meter
Another more or less popular approach is to setup a playback pipeline, play a file, and read back frames from video presenter. This is suggested in another answer to the question, is relatively easy to do, and does the job if you don't have performance requirement and requirements to extract every single frame. That is, it is a good way to get a random RGB frame from the feed but not every/all frames. See related on this:
Different approaches on getting captured video frames in DirectShow
You are looking for vmr9 example in DirectShow library.
In your Windows SDK's install, look for this example:
Microsoft SDKs\Windows\v7.0\Samples\multimedia\directshow\vmr9\windowless\windowless.sln
And search this function: CaptureImage, in this method, see IVMRWindowlessControl9::GetCurrentImage, is exactly what you want.
This method captures a video frame in bitmap format (RGB).
Next, this is a copy of CaptureImage code:
BOOL CaptureImage(LPCTSTR szFile)
{
HRESULT hr;
if(pWC && !g_bAudioOnly)
{
BYTE* lpCurrImage = NULL;
// Read the current video frame into a byte buffer. The information
// will be returned in a packed Windows DIB and will be allocated
// by the VMR.
if(SUCCEEDED(hr = pWC->GetCurrentImage(&lpCurrImage)))
{
BITMAPFILEHEADER hdr;
DWORD dwSize, dwWritten;
LPBITMAPINFOHEADER pdib = (LPBITMAPINFOHEADER) lpCurrImage;
// Create a new file to store the bitmap data
HANDLE hFile = CreateFile(szFile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE)
return FALSE;
// Initialize the bitmap header
dwSize = DibSize(pdib);
hdr.bfType = BFT_BITMAP;
hdr.bfSize = dwSize + sizeof(BITMAPFILEHEADER);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + pdib->biSize +
DibPaletteSize(pdib);
// Write the bitmap header and bitmap bits to the file
WriteFile(hFile, (LPCVOID) &hdr, sizeof(BITMAPFILEHEADER), &dwWritten, 0);
WriteFile(hFile, (LPCVOID) pdib, dwSize, &dwWritten, 0);
// Close the file
CloseHandle(hFile);
// The app must free the image data returned from GetCurrentImage()
CoTaskMemFree(lpCurrImage);
// Give user feedback that the write has completed
TCHAR szDir[MAX_PATH];
GetCurrentDirectory(MAX_PATH, szDir);
// Strip off the trailing slash, if it exists
int nLength = (int) _tcslen(szDir);
if (szDir[nLength-1] == TEXT('\\'))
szDir[nLength-1] = TEXT('\0');
Msg(TEXT("Captured current image to %s\\%s."), szDir, szFile);
return TRUE;
}
else
{
Msg(TEXT("Failed to capture image! hr=0x%x"), hr);
return FALSE;
}
}
return FALSE;
}
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.
I have some wxImages and I would like to store them into a BLOB (Binary Large OBject) field in a MySQL database.
There are no methods in wxImage nor wxBitmap for obtaining the binary data as an array of unsigned char so I can load into the database.
My current workaround is to write the image to a temporary file, then load the BLOB field directly from the file.
Is there a more efficient method to load and store a wxImage object into a MySQL BLOB field?
I am using MySql C++ connector 1.05, MS Visual Studio 2008, wxWidgets and C++.
wxWidgets doesn't provide any API to the data from wxBitmap (because it's platform-dependent) but wxImage uses a well-defined (and very simple) format which you can access using its GetData() method as mentioned above. Just notice that you may need to use GetAlpha() as well if your images have alpha channel.
However this is not how I'd do it because the data will be huge if you do it like this. While compressing it, as also suggested above, is possible, why bother doing it manually when wxImage already supports writing image in any of the standard image formats. Just create a wxMemoryOutputStream and pass it to SaveFile(). Then simply access the stream buffer directly using GetOutputStreamBuffer()->GetBufferStart() and related functions.
Unless I'm missing something, couldn't you use WxImage::GetData (http://docs.wxwidgets.org/2.8/wx_wximage.html#wximagegetdata) to get the data and then ::GetHeight and ::GetWidth to know the length of the data that pointer points to? The unsigned char * that is returned by WxImage::GetData looks like it should point to the RGB data that makes up the image.
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
I've been working on testing a few things out using SFML 1.4 (Simple and Fast Multimedia Library) with C++ and Visual C++ 2008 Express Edition. To avoid having external images with my graphical programs, I was testing out the sf::Image::LoadFromMemory(const char * Data, std::size_t SizeInBytes) function with Bitmap resources loaded using a simple resource script:
IDB_SPRITE BITMAP "sprite1.bmp"
In my code to load the image to create an sf::Image using this bitmap resource, I use the following procedure, consisting of Win32 API functions (I've excluded the code that checks to make sure the Win32 functions don't return NULL to shorten this a bit):
HRSRC hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDB_SPRITE), RT_BITMAP);
HGLOBAL hResData = LoadResource(NULL, hResInfo);
char * resourceData = reinterpret_cast<char *>(LockResource(hResData));
After that, I use the sf::Image::LoadFromMemory function:
MyImage.LoadFromMemory(resourceData, SizeofResource(NULL, hResInfo));
However, this doesn't work (I get an unknown file type error). After some testing, I discovered that the bitmap data I pass to the LoadFromMemory function does not include the BITMAPFILEHEADER (the first 14 bytes), and I believe this is the cause of the unknown file type error.
I can restore the BITMAPFILEHEADER manually and get the LoadFromMemory function to work fine. However, I'm wondering if there is some way to preserve the BITMAPFILEHEADER in the resource data to avoid doing this?
Using a custom resource type will preserve the entire file. Change the resource script to utilize the RCDATA type as opposed to the BITMAP type:
IDB_SPRITE RCDATA "sprite1.bmp"
In the FindResource function call, use RT_RCDATA instead of RT_BITMAP:
HRSRC hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDB_SPRITE), RT_RCDATA);
For more information:
RCDATA Resource
Resource Types
You can add file to resources as a custom resource instead of RT_BITMAP -- this will add file exactly as it is. Unless you also need to ::LoadImage() it.