I have an .emf file that I want to convert to a bitmap in legacy VC++ 6.0 code.
I've been looking through the WIC documentation and I'm surprised I haven't seen a way to do this.
Am I missing something?
If WIC ends up not supporting this, is there a method programattically load an .emf file into a CBitmap object?
There's no need for WIC. It's built into the core of Windows itself in the form of PlayEnhMetafile.
So, to get the picture into a BMP, you select your BMP into a DC, then do PlayEnhMetafile on that DC, and the result will go into the BMP.
Note that this isn't really converting a metafile into a BMP--it's rendering the metafile into the BMP. That is to say, a metafile is (usually) resolution independent. For example, it may specify a line from logical coordinate (0,0) to (100, 100). When you render that into a BMP, you get the line rasterized at a specific resolution. If you later wanted the same picture at higher resolution, the metafile could provide it, but the rendering in the BMP couldn't/can't.
Related
I'm currently writing a 3D renderer (for fun and research), so I need a way to draw my framebuffer to a window. Since I'm doing all of my calculations on CPU, the drawing needs to be as fast as possible.
One of my goals is to use no existing graphics library (OpenGL/DirectX) so the drawing to the screen is pure Win32. In my research I've found a couple of ways to create and draw bitmaps and now I'm looking for the best one.
My current implementation uses a bitmap created with CreateDIBSection(), which is drawn to my window DC using BitBlt().
CreateDIBSection() give me a pointer to my bitmap bytes so I can manipulate it without copying. Using this method I achieve an update rate of about 260 FPS (without any rendering done).
This seems a bit slow, so I'm looking for optimizations.
I've read something about that if you don't create a bitmap with the same palette as the system palette, some slow color conversions are done.
How can I make sure my DIB bitmap and window are compatible?
Are there methods of drawing an bitmap which are faster than my current implementation?
I've also read something about DrawDibDraw(), can anyone confirm that this is faster?
I've read something about that if you don't create a bitmap with the same palette as the system palette, some slow color conversions are done.
Very few systems run in a palette mode any more, so it seems unlikely this is an issue for you.
Aside from palettes, some GDI functions also cause a color matching conversion to be applied if the source bitmap and the destination have different gamuts. BitBlt, however, does not do this type of color matching, so you're not paying a price for that.
How can I make sure my DIB bitmap and window are compatible?
You don't. You can use DIBs (which are Device-Independent Bitmaps) or compatible (device-dependent) bitmaps. It's possible that your DIB bitmap matches the current mode of your device. For example, if you're using a 32 bpp DIB, and your display is in that same mode, then no conversion is necessary. If you want a bitmap that's guaranteed to be in the same mode as your device, then you can't use a DIB and all the nice properties it provides for predictable pixel layout and format.
Are there methods of drawing an bitmap which are faster than my current implementation?
The limitation is most likely in getting the data from system memory to graphics adapter memory. To get around that limitation, you need a faster graphics bus, or you need to render directly into graphic memory, which means you'd need to do your computation on the GPU rather than the CPU.
If you're rendering a 1920 x 1080 pixel image at 24 bits per pixel, that's close to 6 MB for your frame buffer. That's an awful lot of data. If you're doing that 260 times per second, that's actually pretty impressive.
I've also read something about DrawDibDraw(), can anyone confirm that this is faster?
It's conceivable, but the only way to know would be to measure it. And the results might vary from machine to machine because of differences in the graphics adapter (and which bus they use).
I've recently started learning how to use MFC in Visual Studio. My program uses many small 32x32 pixel images that for convenience are put together in one large .png. I've figured out how to load the big image into a CImage and display it on a CClientDC, but I can't find anything that helps me split the image into those smaller 32x32 images.
Alternatively, I can get the pixel data for the big image using DevIL, but I can't find anything that constructs a CImage from pixel data.
As I've only started learning MFC a few days ago, I don't know the API too well and I'm probably missing something obvious. Can anyone point me in the right direction?
You'll need to use the CImage::Draw() overload that lets you specify the source rectangle. So that you can clip the image that you want to paint from the original. There are two candidates, the Draw(HDC hDestDC, const RECT& rectDest, const RECT& rectSrc) for example. The other one is the first one listed on this doc page.
Usually you don't want to create a small image if you're just using the multi-icon image in a GUI.
When you come to draw the icon, pass its offset and size to the bitblt function rather than the dimensions of the whole image.
If you do want to store the sub-image in a bitmap, create a memory DC for the target bitmap and draw into that.
We have a encoder library which takes 32 bpp data. We have a screen capture library which needs to support 16 bpp as well. I would like to convert a 16bpp raw data into 32bpp whenever I need to pass the new screen captures to encoder. How can it be done efficiently and are there any other alternatives ?
I dont want to change the encoder library because that will require changes upstream of encoder as well.
Thanks!
You could load the source bitmap into an HBITMAP, create a destination bitmap with the desired pixel format and then draw the source onto the destination. That would be the easiest way to do it.
If you wanted to work directly with the bits then that would be possible but it's easier to let the system worry about it for you. It's probably quicker when the system does it because it will be well optimised.
To clarify the other answers: you need to use CreateDIBSection to create bitmaps in the formats you are interested in: 16bpp and 32bpp.
The handy thing with this function is it returns a pointer to the memory buffer with the pixel data, allowing you to easily initialize the bitmap from the one source, and extract the pixel data to give to the encoder library.
The source bitmap doesn't need to be a DIBSection, it can be any kind of HBITMAP at all (as long as its compatible with the HDC you try to select it into - but the screen capture library will be giving you a screen DC compatible HBITMAP if it gives you an HBITMAP at all)
BitBlt can then be used to get the device driver to perform the format conversion.
Use BitBlt:
"If the color formats of the source and destination device contexts do not match, the BitBlt function converts the source color format to match the destination format."
http://msdn.microsoft.com/en-us/library/dd183370%28v=VS.85%29.aspx
Summary
Using Windows GDI to convert 24-bit color to indexed color, it seems GDI chooses colors which are "close enough" even though there are exact matches in the supplied palette.
Can anyone confirm this as a GDI issue or am I making a mistake somewhere?
Maybe there's a "please check the whole palette for color matches" flag which I've failed to find?
Note: This is not about quantizing. The source is 24-bit but contains 256 or fewer colors so an exact palette is trivial to calculate. The problem is GDI doesn't use the full palette.
Workaround
I've worked around the problem by mapping the colors myself but I'd prefer to use GDI as it should be better optimized. Problem is, it seems to be "fast but wrong."
Detailed description
My source image is 24-bit but uses 256 (or fewer) colors. I generate an exact palette for it and ask GDI to transfer the image into an indexed bitmap using that palette. For some pixels GDI chooses similar, but not exact, colors even though there are exact colors elsewhere in the palette. This ruins smooth gradients.
This problem happens with:
SetDIBitsToDevice
StretchDIBits
BitBlt
StretchBlt
The problem does not happen with:
SetPixel or SetPixelV in a loop (incredibly slow!)
Using my own code to do the mapping
I've tested this on:
Windows 7 (NVidia hardware/drivers)
Windows Vista (ATI hardware/drivers)
Windows 2000 (VMware hardware/drivers)
In every test I get the same results. (Not just the wrong colours but always the same wrong colors.)
I don't think the issue is color management (ICM/ICC profiles/etc.) as most of the APIs say they don't use it, I've tried explicitly turning it off on the GDI DC as well as via the V5 bitmap header, and I don't think it would apply within my vanlilla-Win2k VM.
Test Project
Code for a simple Win32/GDI/VS2008 test project can be found here:
http://www.pretentiousname.com/data/GdiIndexColor.zip
The Test1 function within Win32UI.cpp is the actual test. It has two arrays of RGBQUADs, one the source image and the other the exact palette for it. It verifies that the palette really is exact and then asks GDI to convert the image using the APIs mentioned above, testing the result each time. For each test it'll tell you the first incorrect pixel's before & after colors, or tell you that all pixels are correct if it worked.
Thanks!
Thanks for reading my question! Sorry if it's the result of me doing something really dumb! :-)
I ran into this exact same problem, eventually contacted Microsoft and provided them with a test case. In the test case I provided a gradient image that had 128 colors in a 24bit DIB, I then converted that to an 8bit DIB that was created with a color table containing all 128 colors from the 24bit image. After conversion, the 8 bit image had only used 65 of the 128 colors.
To sum up their response:
This is not a bug, GDI does use a close enough calculation when down converting the color depth of an image. This is not really documented anywhere, and the only way to insure all of the original colors will convert exactly is to manually manipulate the pixels yourself.
Are you using SetDIBColorTable()? This article seems to imply that, when drawing to a DIB, it is not sufficient to call SelectPalette() but that SetDIBColorTable() also needs to be called to set the palette for the DIB:
However, if the application is using
a DIB section, you create a logical
palette from the DIB colour table as
usual and then also pass the DIB
colour table to the DIB section with a
call to SetDIBColorTable(). Despite
what the "Platform SDK" documentation
of RealizePalette() appears to imply,
RealizePalette() does not adjust the
colour table of the DIB section.
The article contains some more information on drawing into palettized DIBs that may be relevant (see the section "Palettes and DIB sections").
I vaguely remember that you also need to call RealizePalette(hdc) after a palette is selected into a DC. We ditched our palette code so long ago that the code isn't even in our source tree anymore. I see from your code that you alrady tried this, but I suggest that you might want to play with that some more.
I do remember that the palette code was pretty fragile, and we stopped using it as soon as we could.
Some older AVI files would have 8 bit palettized video with a palette imbedded in the file, so playback code for those files would need to load an realize a palette. I remember that realize didn't do anything unless you were the foreground app, but that SHOULD only apply to screen DC's and not memory DC's.
If you searched around for sample source code that could play palettized AVI's you might find something that shows the magic formula for getting palettes to work.
Sorry I can't be more help.
Does anyone know of a good resource that will show me how to load an image with C++ and spin it?
What I mean by spin is to do an actual animation of the image rotating and not physically rotating the image and saving it.
If I am not clear on what I am asking, please ask for clarification before downvoting.
Thanks
I would definitely default to OpenGL for this type of task, you can load the image into a Texture, then either redraw the image at different angles, or better yet you can just spin the 'camera' in the OpenGL engine. There are loads of OpenGL tutorials around, a quick google search will get you everything you need.
You could use SDL and the extension sdl_image and/or sdl_gfx
In Windows using GDI+ you could show rotated image in the following way:
Graphics graphics( GetSafeHwnd() ); // initialize from window handle
// You can construct Image objects from a variety of
// file types including BMP, ICON, GIF, JPEG, Exif, PNG, TIFF, WMF, and EMF.
Image image( L"someimage.bmp" );
graphics.RotateTransform( 30.0f ); // 30 - angle, in degrees.
graphics.DrawImage( &image, 0, 0 ); // draw rotated image
You could read here more detailed explanation.
Second solution is to use DirectX. You could create texture from file and later render it. It is not trivial solution, but it'll use hardware acceleration and will give you the best performance.
On Windows 7 there is available new API called Direct2D. I have not used it yet, but it looks promising.
Direct2D provides Win32 developers with the ability to perform 2-D graphics rendering tasks with superior performance and visual quality.
i agree with DeusAduro. OpenGL is a good way of doing this.
you can also do this with Qt
The "roll-your-own" solution is difficult.
I'd suggest looking into WPF - it might have some nice options in an image control.