|

Motive
How many of you developers are using GDI+? I reckon, not many. As a seasoned
Windows C++ programmer developing for desktop applications, I've been
using the archaic GDI on regular basis. Since the release of GDI+ (see (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdicpp)
I've been using GDI+ in new applications and also converting existing
applications to use GDI+. There numerous compelling reasons why you should be
using GDI+, here are some:
- Successor to GDI
- Compatible with .NET
- Optimizes many of the capabilities of GDI
- Supports: Gradient Brushes, Independent Path Objects, Transformations and
the Matrix Object, Scalable Regions, Alpha Blending and support for multiple
image formats:
- BMP
- GIF
- JPEG
- Exif
- PNG
- TIFF
- ICON
- WMF
- EMF
During my development of Windows GUI based applications with GDI+, I've come
across the need to display animated GIFs, whilst GDI+ does not support
displaying animated GIFs directly, in can be done with a little coding.
Implementation
Firstly lets look at drawing a simple image using GDI+.
void CMyWnd::OnPaint()
{
CPaintDC dc(this);
Graphics graphics(&dc);
Image image(L"Test.Gif");
graphics.DrawImage(&image, 0, 0, image.GetWidth(), image.GetHeight());
}
Straight away we can see the simplistic C++ interface for using GDI objects.
This makes it a sure fire way for using GDI objects. There is no need for using
SelectObject to select GDI objects in and out of the device context.
For those of the readers who are not familiar with the format of an animated
GIF, animated GIF is actually a series of GIF frames with a delay time
associated each
frame, therefore each frame can have a different delay time.
My implementation of encapsulating an animated GIF functionality derives a
class called
from ImageEx from the GDI+ Image class. The first task
is to determine whether or not a GIF is of the animated kind. The following code
demonstrates this:
bool ImageEx::TestForAnimatedGIF()
{
UINT count = 0;
count = GetFrameDimensionsCount();
GUID* pDimensionIDs = new GUID[count];
GetFrameDimensionsList(pDimensionIDs, count);
m_nFrameCount = GetFrameCount(&pDimensionIDs[0]);
int nSize = GetPropertyItemSize(PropertyTagFrameDelay);
m_pPropertyItem = (PropertyItem*) malloc(nSize);
GetPropertyItem(PropertyTagFrameDelay, nSize, m_pPropertyItem);
delete pDimensionIDs;
return m_nFrameCount > 1;
}
m_pPropertyItem->value is actually a pointer to an array of
longs, each long is a delay time which corresponds to a GIF frame. Because
GetPropertyItem returns a different size depending on what property using
interested in, a Size is require and its the programmer responsibility to
allocate and deallocate the memory associated with GetPropertyItem.
The size is determined by calling GetPropertyItemSize supplying
property tag your interested in.
Once the number of frames and delay times
have been retrieved from the image, a thread is created which calls to
DrawFrameGIF until the object destructs. See DrawFrameGIF
below:
bool ImageEx::DrawFrameGIF()
{
::WaitForSingleObject(m_hPause, INFINITE);
GUID pageGuid = FrameDimensionTime;
long hmWidth = GetWidth();
long hmHeight = GetHeight();
HDC hDC = GetDC(m_hWnd);
if (hDC)
{
Graphics graphics(hDC);
graphics.DrawImage(this, m_rc.left, m_rc.top, hmWidth, hmHeight);
ReleaseDC(m_hWnd, hDC);
}
SelectActiveFrame(&pageGuid, m_nFramePosition++);
if (m_nFramePosition == m_nFrameCount)
m_nFramePosition = 0;
long lPause = ((long*) m_pPropertyItem->value)[m_nFramePosition] * 10;
DWORD dwErr = WaitForSingleObject(m_hExitEvent, lPause);
return dwErr == WAIT_OBJECT_0;
}
One other interesting aspect of this class is it has the ability of loading a
image directly as a resource from an executable. I usually import my GIF into a
project and give it a resource type of "GIF" and then rename the resource ID from a
numeric constant to a string (see the example code).
Conclusion
If you familiar with the concepts and programming of GDI, GDI+ provides some
advance features and the interface almost mirrors the .NET GDI namespace. The
sample apps and code include the full listings for implementing animated GIF in
your code applications. For code reference just search for GDI+ within the code.
One thing I haven't included in this article is starting up and shutting the GDI+
subsystem.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 79 (Total in Forum: 79) (Refresh) | FirstPrevNext |
|
 |
|
|
Hello Everybody, I am developing an application which involves maps. There is a picture box which contains the map. The user should be able to indicate streets using concentric (and transparent) circles and ovals.
Could anyone tell me how to be able to draw concentric , transparent circles. The next questions is that the ovals should be rotatable so that the streets can be precisely marked. Thank you.
Minad
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
This question is far to generic, what mapping database are you using?
If you're struggling developing software, then I'd recommend gardening.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hello, It is a simple application there is no database. When the application is run there is a picture box with a city map and a save button to save this image in the picture box.
Before saving the image I would like to indicate few buildings, streets etc using concentric circles and ovals.
Here is how I do it On double click of picturebox do the following Graphics *g=Graphics::FromImage(this->pictureBox1->Image); g->DrawEllipse(pen1,90,90,70,70); g->DrawEllipse(pen1,45,45,65,65);
This draws a concentric circles but the problem is I would like it to be red in colour(this is not a problem) and transparent (this is).
The next question is the user should be able to draw ovals (red, transparent) and the user should be able to rotate this oval to pinpoint something on the map. Thanks for replying to my post.
Minad
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Surely
Pen pen1 = new Pen(Color.FromARGB(128,Color.Red));
Works?
If you're struggling developing software, then I'd recommend gardening.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
We lowly VB programmers can not use this C code.
I am using VB express.
Does anyone have code to create an animated GIF in VB express? (Express is a subset of the Studio version.)
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Easy one, move to C++!
We made the buttons on the screen look so good you'll want to lick them. Steve Jobs
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi all, I wanted to know is there any way to get programatically, if any .gif image is having multiple images. So programatically can we decide if the image supports any motion or not.
Thanks in advance, Mukta
|
| Sign In·View Thread·PermaLink | 2.00/5 (3 votes) |
|
|
|
 |
|
|
Hi,
I worked with your code given in the artcle it worked well.But in addtion i needed to rotate the image in given angles.
So I started to do use Image object in GDI+.My intention was to make a Image object and manupulate its position and orientation.(As given in msdn page titled Drawing, Positioning, and Cloning Images - refer the link below)
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdicpp/GDIPlus/AboutGDIPlus/IntroductiontoGDIPlus/OverviewofGDIPlus.asp[^]
I tried to insert a image to my main frame using "Image" in GDI+. But a runtime error (unhandled exception) is occuring when im going to run the program.The details are as follows.
I have included <"gdiplus.h" in StdAfx.h. There were no issues on that.But the problem started when i tried to insert a image using the guidelines given in above msdn link(.Drawing, Positioning, and Cloning Images - GDI+)
As per that method I used the following code:
CPaintDC dc(this); Graphics myGraphics(dc.m_hDC);
Image myImage(L"robot.gif"); // this line creates the problem myGraphics.DrawImage(&myImage, 20, 10);
The program Built & compiled successfully in VC++ 6.0.But didn't run.It gaves a error.
When I insert that code to a .NET project the error message says that ;"Unhandled exception at 0x7c9105f8 in tttdk.exe: 0xC0000005: Access violation reading location 0x00000010." When I break it , it shows the location of the error in the following cpp file.
D:\VS\VC\atlmfc\src\atl\atls\allocate.cpp
..
...
CAtlTraceCategory *CAtlAllocator::GetCategory(int iCategory) const
{
if(iCategory == m_pProcess->CategoryCount())
return NULL;
ATLASSERT((iCategory < m_pProcess->CategoryCount()) || (iCategory == -1));
CAtlTraceCategory *pCategory = NULL;
if(iCategory >= 0)
{
BYTE *pb = reinterpret_cast(m_pProcess) + m_pProcess->MaxSize(); // this is the location of the error
pCategory = reinterpret_cast(pb) - iCategory - 1;
}
return pCategory;
}
..............
Please help me regarding the above matter ASAP.or else tell me way to Insert a GIF image to a MFC frame and to change its position and rotate by given angles time to time.
Thisara
ENTC UoM
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
GdiplusStartup might need to be called in the same THREAD that Image constructor is run. At least this is what solved my problem. http://www.techvanguards.com/com/tutorials/tips.htm http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdicpp/GDIPlus/GDIPlusreference/classes/imageclass/imageconstructors/image_53filename_useembeddedcolormanagement.asp
Infro
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
i have the same error,i have not modify the source,exception occur when i set struct member alignment with 1 byte.Why?
ddzh
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
This should work under borland builder 5.o, as it now dependencies on any of the Microsoft frameworks.
We made the buttons on the screen look so good you'll want to lick them. Steve Jobs
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
|
dont know if this is exactly a gdi+ question, but been triing to set up a animated gif with transparecy.
1 try: setting up gif with one chosen color of background to be transparent. no solution because gif has white background and white spots in middle of the image too, i dont want both of them transparent
2 try: with image ready and photoshop, using magic wand to change background to transparent. this actualy makes transparency as i want it, but there is another problem, let say there are 2 frames and on each the object is not on the same spot so when the animation is running the frames overwritre each other and color parts of the previous frames stay on image until the frameset is ended
How can i set frames of gif image to disapear when their time is up so the next transparent frame has all the transparency it needs
thx, liq
|
| Sign In·View Thread·PermaLink | 1.67/5 (3 votes) |
|
|
|
 |
|
|
if your using code similar to this example this can be accomplished by using RedrawWindow() with RDW_ERASE flag. this assumes your window your rendering on is processing the WM_ERASEBKGND message. Then render your image.
Or, you could use a version like I have implimented that instead of rendering direct to the window, the thread simply invalidates the window for the rectangle with the image and then the paint operation for the window calls a draw function in the ImageEx to do the actual rendering. In this case I found it helpful to add another event object so the thread can wait till it is told to draw before proceeding to the frame wait. This prevents the image from jumping on heavily loaded systems. However this can make the animation look jerky.
Doing transparent rendering of GIFs without using photoshop's wand, which is just registering transparent entries in the GIF's pallete isn't difficult. Just pick a color for the image to be the transparent color, probably like your doing already for bitmaps.
Use ImageAttributes class to setup for the transparency. use the SetColorKey() high == low color if your not using a range of colors that are transparent the default adjustment is normally fine.
Now instead DrawImage used in the example use one that takes ImageAttributes as a parameter. That will produce the transparent redering...
NOTE: you cannot use a COLORREF directly with the ImageAttributes. The COLOR image is hardware representations... in 32bpp I believe its the same... but 16bpp isn't... Easy way around this is to have a location that is alway transparent, and grab the pixel color using Image->GetPixel()...
if you only have a COLORREF then you must convert. I will bless you with a solution to this...
with clr == COLORREF and img == Image *
if( PixelFormat16bppRGB555 == img->GetPixelFormat() ){ return Gdiplus::Color( (GetRValue(clr) & 0xF8) | (GetRValue(clr)>>5), (GetGValue(clr) & 0xF8) | (GetGValue(clr)>>5), (GetBValue(clr) & 0xF8) | (GetBValue(clr)>>5) ); }else if( PixelFormat16bppRGB565 == img->GetPixelFormat() ){ return Gdiplus::Color( (GetRValue(clr) & 0xF8) | (GetRValue(clr)>>5), (GetGValue(clr) & 0xFC) | (GetGValue(clr)>>6), (GetBValue(clr) & 0xF8) | (GetBValue(clr)>>5) ); }
|
| Sign In·View Thread·PermaLink | 1.00/5 (2 votes) |
|
|
|
 |
|
|
I solve this problem calling Graphics::Clear(), into the method ImageEx::DrawFrameGif(). When the Graphics::Clear() is called it paint the background according to color specified by parameter. So I get the COLORREF of the 3D Face dialog, using GetSysColor( COLOR_3DFACE ) and convert this value to ARGB using the method Color::SetFromCOLORREF(), than I just pass this value in the Graphics::Clear() method.
Example: ImageEx::DrawFrameGif() { ... HDC hDC = GetDC(m_hWnd); if (hDC) { Graphics graphics(hDC); //////////// Modify here//////////// // clear the background with the COLOR_3DFACE color Color color; color.SetFromCOLORREF( GetSysColor( COLOR_3DFACE ) ); graphics.Clear(color); //////////////////////////////////// graphics.DrawImage(this, m_pt.x, m_pt.y, hmWidth, hmHeight); ReleaseDC(m_hWnd, hDC); } ... }
Claudio Sampaio Manaus-AM Brasil
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Maybe unnecessary to clear all DC, try below:
bool ImageEx::DrawFrameGIF() {
::WaitForSingleObject(m_hPause, INFINITE);
GUID pageGuid = FrameDimensionTime;
long hmWidth = GetWidth(); long hmHeight = GetHeight();
HDC hDC = GetDC(m_hWnd); if (hDC) { CRect rc(m_pt.x, m_pt.y, m_pt.x+hmWidth, m_pt.y+hmHeight); InvalidateRect(m_hWnd, rc, TRUE); //UpdateWindow(m_hWnd); Graphics graphics(hDC); graphics.DrawImage(this, m_pt.x, m_pt.y, hmWidth, hmHeight); ReleaseDC(m_hWnd, hDC); }
SelectActiveFrame(&pageGuid, m_nFramePosition++); if (m_nFramePosition == m_nFrameCount) m_nFramePosition = 0;
long lPause = ((long*) m_pPropertyItem->value)[m_nFramePosition] * 10;
DWORD dwErr = WaitForSingleObject(m_hExitEvent, lPause);
return dwErr == WAIT_OBJECT_0; }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hey Guys,
The InvalidateRect method is bad because it flickers. The color fill method is bad because it doesn't work if you have a bitmap or image behind the transparent gif. So what you really need to do is grab what is behind the transparent gif. So here is how you do that
1. First create three member variables in ImageEx.h
HBITMAP m_hBackgroundBitmap, m_hOldBitmap; HDC m_hBackgroundDC;
2. In the InitAnimation function initialize the variables to null
m_hBackgroundBitmap = NULL; m_hBackgroundDC = NULL;
3. In DrawFrameGIF function insert the code as follows
CRect rc2(0,0, hmWidth, hmHeight);
//we only want to create the back buffer once if(m_hBackgroundDC == NULL && m_hBackgroundBitmap == NULL) { m_hBackgroundDC = CreateCompatibleDC(hDC); m_hBackgroundBitmap = CreateCompatibleBitmap(hDC, hmWidth, hmHeight); m_hOldBitmap = (HBITMAP)SelectObject(m_hBackgroundDC, m_hBackgroundBitmap); BitBlt(m_hBackgroundDC, 0,0, hmWidth, hmHeight, hDC, m_pt.x, m_pt.y, SRCCOPY); }
if (hDC) { Graphics graphics(hDC); //draw background that we saved earlier (essentially erasing image from before) BitBlt(hDC, m_pt.x, m_pt.y,hmWidth, hmHeight, m_hBackgroundDC, 0,0, SRCCOPY); graphics.DrawImage(this, m_pt.x, m_pt.y, hmWidth, hmHeight); ReleaseDC(m_hWnd, hDC); }
4. Clean up our mess in the destroy function
void ImageEx::Destroy() { SelectObject(m_hBackgroundDC, m_hOldBitmap); DeleteDC(m_hBackgroundDC); DeleteObject(m_hBackgroundBitmap); }
And there you have it. This will allow the transparent gif to display correctly over top of anything that his behind it.
Cheers, Greg
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Thank you, it is perfect. But... I have a transparent animated gif. I show it from the program directly on the desktop. On XP it works fine. But on Vista the animated gif appeares in a black rect (it is not transparent).
Any idea?
Istvan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi, First: thanks very much, nice article, which helped me very! But I've got a little problem. How can I get the Rendering Time of each frame? You know, in a GIF every frame has got a time which says how long this frame should be rendered.
sorry for my bad english, but I'd be so pleased if you could help me
regards, Kohaku-Chan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
|
I have created Gif File Like this. Image img1("simple.gif"); Now I want to change the Color Pallete of the Gif File. How do I change it?.please any one know about that ,send me reply immediatelly.
|
| Sign In·View Thread·PermaLink | 1.50/5 (2 votes) |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|