I have no practice with windows programming at all, but now I have a problem I want to fix in some program. I need to place an image to windows clipboard and I have raw pointer to valid DIB (device independent bitmap)(in my experiments the dib header version is 3). The program uses the model with delayed clipboard rendering, which means that at first we use SetClipboardData(CF_DIB, NULL) and then on WM_RENDERFORMAT message the program place the actual data to clipboard with SetClipboardData(format, dibDataPointer).
When I open clipbrd.exe (on windows xp) and I choose the DIB view, I can see an Image without any problem. But in msdn is written that the system can render automatically from CF_DIB to CF_BITMAP format. I think that's why when I look in clipbrd.exe I see 2 formats: DIB and BITMAP. When I select in clipbrd.exe the bitmap format I got an error. At first when I looked at the code I saw that there is no case for CF_BITMAP in system message handler function, so when system asks to render CF_BITMAP nothing valid is placed to clipboard, so I added something like this:
switch(format){
case CF_DIB:
case CF_BITMAP: //new code
if(format == CF_BITMAP)//new cOde
format = CF_DIB;// new code
....
SetClipboardData(format, dibDataPointer);
....
and hope (actually, I knew that won't gonna work, but gave this way a try) that the system will recognize that I'm going to give as a response for CF_BITMAP a DIB data and the system will convert in automatically.
So how can I place proper data for WM_RENDERFORMAT message with CF_BITMAP format from the system if I have a DIB data (generally it would be better if I could use the system ability to convert DIB to BITMAP rather then create BITMAP from DIB manually)?
Update:
So I found how to fix the issue. At first it's needed to register for delayed rendering only the CF_DIB with SetClipboardData(CF_DIB, NULL). The CF_BITMAP format will be added to the available clipboard types by Windows automatically. Then you need to pass the dib data with header of the first version which is described by BITMAPINFOHEADER (I have v3 version, I doubt that v4 and v5 headers are going to work) structure with positive biHeight (Y Coordinate) on WM_RENDERFORMAT with CF_DIB format required (the system won't ask you for CF_BITMAP because you didn't register it manually). And in this particular case the system will convert CF_DIB to CF_BITMAP automatically. I don't know will this work with any of the compression method for bitmap data, because I've tested only the BI_RGB uncompressed images.
Every other version of bitmapinfo dib header is reverse compatible with BITMAPINFOHEADER and can be successfully copied with memcpy. But don't forget to set biSize to sizeof(BITMAPINFOHEADER). The second part is to setup positive Y coordinate. (I really hope that DIB format with compressed data should always have positive height.) But for uncompressed bitmaps biHeight can be less then zero, and should be made to a positive value. This will cause the image to be upside down, so it's needed to reverse image rows. The mention should be made that the rows are aligned by 4 bytes.
And the worst thing is that all this standards for headers are described in microsoft documentation. But. for example, Paint can get the dib info v3 header with negative height value, the clipbrd.exe can get v3 header with positive height. The wordpad wants only v1 header with positive height. And the windows converts DIB ro BITMAP only with v1 header and positive height. This all are applications which are distributed with windows (no clipbrd.exe in Vista or later). This is a terrible hell. I hope there won't be any more programming for Windows in my entire life.
Related
The Problem
I am loading the classic serife.fon file from Microsoft Windows using FreeType.
Here is how I set the size:
FT_Set_Pixel_Sizes(face, 0, fontHeight);
I use 0 for the fontWidth so that it will be auto-calculated based on the height.
How do I find the correct value for fontHeight such that the resulting font will be exactly 9 pixels tall?
Notes
Using trial and error, I know that the correct value is 32 - but I don't understand why.
I am not sure how relevant this is for bitmap fonts, but according to the docs:
pixel_size = point_size * resolution / 72
Substituting in the values:
point_size = 32
resolution = 96 (from FT_Get_WinFNT_Header)
gives:
pixel_size = 42.6666666
This is a long way from our target height of 9!
The docs do go on to say:
pixel_size computed in the above formula does not directly relate to the size of characters on the screen. It simply is the size of the EM square if it was to be displayed. Each font designer is free to place its glyphs as it pleases him within the square.
But again, I am not sure if this is relevant for bitmap fonts.
fon files are exe files with a fnt payload, where the fnt payload can be a vector or raster font. If this is a raster font (which is most likely) then the dfPixHeight value in the fnt header will tell you what size it's meant to be, which is exposed by FreeType2 as the pixel_height field of the FT_WinFNT_Header.
(And of course, note that using any size other than "the actual raster-size of the FNT" is going to lead to hilarious headaches because bitmap scaling is the kind of madness that's so bad, OpenType instead went with "just embed as many bitmaps as you need, at however many sizes you need, because that's the only way your bitmaps are going to look good")
The FNT-specific FT2 documentation can be found over on https://www.freetype.org/freetype2/docs/reference/ft2-winfnt_fonts.html but you may need to read it in conjunction with https://jeffpar.github.io/kbarchive/kb/065/Q65123 (or https://web.archive.org/web/20120215123301/http://support.microsoft.com/kb/65123) to find any further mappings that you might need between names/fields as defined in the FNT spec and FT2's naming conventions.
I am using buildroot with rpi3-64 configuration; integrated is uboot 2019.07.
I did several configurations but I am unable to display a picture with bmp display
The screen resolution is set to 1080p with config.txt hdmi_mode=16
I loaded the image via tfp <addr> <host>:/test.bmp
Check it with bmp info <addr> shows the correct information about the bitmap.
When calling display it simple return the input command line and does nothing
What I tried so far:
Create a full screen 1080p bitmap with 32bit also 24bit, 8bit results in an error that bitdepth do not fit to the frame buffer environment - as expected (or something like this message)
I tried lower resolution i.e. 1024*768
but had also no success with it.
I wonder if there is still any video/Fb setting to be made. Do I need special bmp setting.
Any ideas?
I'm not using buildroot, so apologies if this differs slightly. To get this working on my pi3, I had to modify u-boot/include/rpi.h to include this snippet.
#ifdef CONFIG_DM_VIDEO
#define CONFIG_BMP_32BPP
#endif
This only adds support for 32 bits/pixel, so if you need 8/16/24, use those instead.
This was tested on commit ecd4d99f654f3f7bfb96001891d69c3125e70b69 of the master branch, but I suspect it'll work on most versions.
MSDN says that the bitmap used in GetDiBits should not be selected into a DC before calling this function. But from my experience(with BitBlt) I know that I cannot draw an a bitmap unless it is selected.
How does GetDiBits circumvents this? Can I just use an unselected, newly created bitmap as argument to this function?
GetDiBits as well CreateDibSection returns an array. But MSDN says about the first function:
"bits of the specified compatible bitmap"
I thought DI stands for DeviceIndependent. Why is there a contradiction? This means that, according to MSDN, GetDiBits can be used only with CreateCompatibleBitmap (which is DD)? Then I can't send this array to another machine to display it,right?
Both functions use a hDC. If CreateDibSection is truly DIndependent why does it need a hDC? All the needed info is provided through the bitmapinfoheader...
I cannot draw an a bitmap unless it is selected. How does GetDiBits circumvents this?
GetDIBits doesn't do any drawing. It reads pixel data from a bitmap and converts it into the desired color format. SetDIBits doesn't "draw" either, but it will set the pixel data in a bitmap.
Naming confusion.
The DI in GetDIBitmap refers to the fact that the pixel data is returned in a device-independent format (specifically, the one you ask for). The source bitmap can be a compatible bitmap or a device-independent bitmap.
Similarly SetDIBitmap takes device-independent pixel data and converts it to the type of the target bitmap.
These functions are confusingly named.
What's the DC for?
The DC is used to answer any questions about the pixel format on the device. For example, if the source format is a palette-based device-dependent bitmap, GetDIBits will assume the palette selected into the DC is the correct one. Note that the palette is not in the BITMAPINFOHEADER.
CreateDIBSection creates a hybrid bitmap that stashes data in a device-independent method, but may also keep a device-dependent copy in sync with it for performance. So it needs to know the DC of the intended device.
Summarization:
Calculations point out in a straight-forward way that: A .BMP picture of 3289 X 4570 X 32bpp takes about 53MB. The picture of same size but 24bpp takes about 43MB, that of 16bpp takes about 28MB. ChemDraw-processed picture file must then be converted from 24bpp to 16bpp in my situation.
Further comparison of the hex data of both files gives more detailed understanding of the difference between ChemDraw-processed picture and the original picture. Specifically, ChemDraw stores "EMF_STRETCHDIBITS" instead of "EMF_STRETCHBLT". It should be added that "EMF_STRETCHDIBITS" can be done by calling StretchDIBits when copying pixels into TMetaFile/TMetaFileCanvas. It should be also noted that pixels for "EMF_STRETCHDIBITS" should be the same as those for "EMF_STRETCHBLT".
Unfortunately, till now I didn't find out how ChemDraw exactly processes and stores pasted pictures. That is to say, I didn't find out why the pixels ChemDraw stored is different from what I can obtain programingly.
PS: I will vote up kind answers regarding this question later because I do not have enough reputation for the moment. Thanks for everybody who has been kind to comment!
===
Hi,
Thanks for your time very much!
Say that I have a picture named "sample_original.bmp". The file size is 3289 X 4570, 43MB. Then I do the following to convert it into a .EMF file (Enhanced Windows MetaFile):
Method 1, by making a small in-house Delphi program:
(1) Load the .BMP image file.
(2) Obtain the Canvas of TMetaFile(TMetaFileCanvas)
(3) Call Canvas.Draw to copy the image.
(4) Save to .EMF file, named "sample_original_bmp2emf_method1.emf"
Method 2:
(1) Open the .BMP image file in the mspaint program, choose "select all", and choose "copy".
(2) Open an external program called ChemDraw, create new document, and choose "paste".
(3) Then I choose to save that in the XML-compatible .cdxml format, named "sample_original_bmp2emf_method2.cdxml".
(4) The content of picture (maybe changed or degraded?) is now saved in the sample_original_bmp2emf_method2.cdxml file. The format is Base64-encoded zlib-compressed format.
(5) I can Base64-decode the XML string, zlib-decompress it, and save it into the picture file "sample_original_bmp2emf_method2.emf".
The file size of sample_original_bmp2emf_method2.emf is smaller by 15 MB than sample_original_bmp2emf_method1.emf, but the width & height has been maintained.
Furthermore, if I open "sample_original_bmp2emf_method2.emf" in the mspaint program and save it back into .bmp file format, a warning pops up that transparent information is losing.
Could you help to comment on how to tell the difference "sample_original_bmp2emf_method1.emf" & "sample_original_bmp2emf_method2.emf"? Is the picture smaller because its quality is decreased?
In other words, what changes to my original picture could possibly be made by this external program?
Best wishes,
The files mentioned above can be downloaded in the following url:
http://www.rapidspread.com/file.jsp?id=2ighvzoci8
PS: I believe that Andreas Rejbrand has be kind enough to made his answer and I then gave my comments. But I cannot see those now. Is it supposed to be normal behavior of the system? o_o
You wrote:
Base64-decode the XML string, zlib-decompress it, and save it into the picture file "sample_original_bmp2emf_method2.emf".
So it's definitively NOT an emf file, but some zipped format..
Or it was converted to another format (like vectorial) before converting to XML. In this case, you've less data in the resulting picture than a real bitmap.
Whereas the first method will give you an emf file with a size of only a few bytes bigger than a plain bmp file (i.e. the emf records used to encapsulate the bitmap data).
If you zip the emf file of the first method, I'm quite sure you'll get a file with a smaller size than the false emf obtained by method two.
Why don't you just compare the two images? Open them in a raster editing program and compare the pixels.
Why do you care how big the files are? Surely what's important is whether or not the image is the right one.
I have an OpenCV matrix of double (CV_32F) values. I'd like to save it to the disk. I know, I could convert it to an 1-Channel 8-bit IplImage and save it. But that way, I loose precision. Is there a way to save it directly in the 32-bit format, without having to convert it first? It also would be nice, if the resulting file would have an image format, so I can view the result as an image.
You can always save any "object" (CvMat, IplImage, anything..) from OpenCV "as is" by using cvSave() and loading it back with cvLoad(). As to my experience, most floating-point image stuff does not work correctly, I usually save my floating point data this way.
However, you cannot directly view the stored data.
Another possibility we have used frequently is including an own built of OpenEXR. You can easily store full precision floating point images using this library and many third party applications are able to open EXR files. Note that OpenCV includes OpenEXR, if i am not mistaken, but the last time i've tried, saving/loading floating point images did not work correctly. However, you should first try to save an fp image as *.exr, maybe that already does the magic with recent versions.
You could always iterate over the matrix and write it out yourself. If you want it to be viewable as an image, you can use a variant of PPM. I'm not sure what programs would be able to natively read your image format if you use values out of the 0-255 range though.
This is old, but thought I'd throw in my two cents.
If you just want to save float images to disk, and you don't need to view them, you may want to look at Portable Float Map (PFM) image format. Very simple format, just saves floats to disk, no compression, minimal header. You can write your own read/write code for this very quickly. That's what I'm using for HDR research.
As the others pointed out, to "view" float images you need to ask yourself some questions about their contents and how to sensibly scale them back into an 8-bit range you can display on your monitor. You might consider Matlab's image viewer (imshow function) which offers some double scaling functionality.
You might also consider saving to either EXR or HDR format and using Photomatix's built-in HDR image viewer which gives you a little separate window that shows you a real-time tonemapped window around your current cursor position. It's a good way to navigate an HDR or floating point image to get a sense of "what's really there" without tonemapping the whole thing.