Aqua-Soft Forums: Zoom effect for transparent window - Aqua-Soft Forums

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Zoom effect for transparent window Rate Topic: -----

#1 User is offline   Smaky Icon

  • Group: Member
  • Posts: 586
  • Joined: 19-April 08

Posted 10 December 2008 - 07:59 PM

Contninuing on my Docket task I am now trying to add a "Zoom" effect to the window that contains alpha & tranparent info.

I have created the following funtions that gets called when the window is first shown & hide:

VOID SimpleZoomComicStripWindow(HWND hWnd, Gdiplus::Bitmap *bitmap, int numSteps)
{
	// center the dialog
	CenterWindow(hWnd, TRUE);
 
	// Show it _first_
	::ShowWindow(hWnd, SW_SHOW);
 
	// Zoom the window
	if (numSteps > 0)
	{
		for (int i = 1; i < numSteps; i++)
		{
			Gdiplus::Bitmap *modifiedBitmap = GetZoomedBitmap(bitmap, numSteps, i);
			UpdateComicStripWindow(hWnd, modifiedBitmap, i*(255/numSteps));
			delete modifiedBitmap;
		}
		UpdateComicStripWindow(hWnd, bitmap, 255);
	}
	else if (numSteps < 0)
	{
		numSteps = -numSteps;
		for (int i = numSteps; i > 1; i--)
		{
			Gdiplus::Bitmap *modifiedBitmap = GetZoomedBitmap(bitmap, numSteps, i);
			UpdateComicStripWindow(hWnd, modifiedBitmap, i*(255/numSteps));
			delete modifiedBitmap;
		}
		UpdateComicStripWindow(hWnd, bitmap, 0);
	}
}
 
 
Gdiplus::Bitmap *GetZoomedBitmap(Gdiplus::Bitmap *originalBitmap, int numSteps, int curStep)
{
	if (!originalBitmap)
		return NULL;
 
	UINT width = originalBitmap->GetWidth();
	UINT height = originalBitmap->GetHeight();
	numSteps = (numSteps > height) ? height : numSteps;
	UINT sliceHeight =  height/numSteps;
 
	FLOAT scaleFactorX = (numSteps) ? (FLOAT)width/(FLOAT)numSteps : 1;
	FLOAT scaleFactorY = (numSteps) ? (FLOAT)height/(FLOAT)numSteps : 1;
 
	// Create a new bitmap to hold the modified image
	Gdiplus::Bitmap *modifiedBitmap = new Gdiplus::Bitmap(width, height, PixelFormat32bppPARGB);
 
	// Create a graphics object to draw the modified image
	Gdiplus::Graphics modifiedGraphics(modifiedBitmap);
	modifiedGraphics.SetInterpolationMode(Gdiplus::InterpolationModeHighQuality);
	modifiedGraphics.SetSmoothingMode(SmoothingModeAntiAlias);
	modifiedGraphics.SetCompositingMode(Gdiplus::CompositingModeSourceCopy); // Used to preserve alpha-channel data
 
	// Create a Rect object that specifies the destination of the image.
	Rect destRect((width - (scaleFactorX * curStep))/2, 0, scaleFactorX * curStep, scaleFactorY * curStep);
 
	modifiedGraphics.DrawImage(originalBitmap, destRect, 0, 0, width, height, UnitPixel, NULL, NULL, NULL);
 
	return modifiedBitmap;
}


As you can see, I am creating a scaled version of the composited bitmap so the effect of the window being zoomed & coming from tranaparent to opaque will be shown.

The problem I am experimenting is:
1- I have seen that when the wiidow is shown/hide each time the system takes about 10MB of memory that is not being freed until I close the dock (ObjectDock in my case). Although I am calling delete modifiedBitmap; it seems it is not being really freed... am I doing something wrong here?
2- If I add code to cal SetWindowPos at each step increment (to animate the zoom so it will come from the docklet to the center of the screen) I get quite an ungly animation... it looks too steppy & flickers a lot... what strategy should I use to get a better transition effect from minized to zoomed?

Thanks for your help.
0

#2 User is offline   matonga Icon

  • Group: Developers
  • Posts: 1,286
  • Joined: 04-September 06

Posted 10 December 2008 - 10:11 PM

1- No idea, your code seems OK.

2- There is a better alternative, though it is fairly more complex:

Make the window so big that it will cover both the comic strip destination and the dock icon position.

Even easier (but worse in terms of performance): make a full screen window.

Then do the animation there.

So:

- SetWindowPos would be called just to put the window in position x = 0, y = 0.
- Then calling CenterWindow would be useless.
- The comic strip window would have same size than screen.
- You would draw all the animation, in screen coordinates.

GetZoomedBitmap could be modified to this:

Gdiplus::Bitmap *GetZoomedBitmap(Gdiplus::Bitmap *originalBitmap, int numSteps, int curStep, SIZE screenSize, POINT origin, POINT destination) {
	...

	// Create a new bitmap to hold the modified image
	Gdiplus::Bitmap *modifiedBitmap = new Gdiplus::Bitmap(screenSize.cx, screenSize.cy, PixelFormat32bppPARGB);

	...

	// Create a Rect object that specifies the destination of the image.
	float origin_factor, destination_factor;
	origin_factor = (1.0 - (destination_factor = (float)curStep / numSteps));
	Rect destRect(
		origin.x * origin_factor + destination.x * destination_factor,
		origin.y * origin_factor + destination.y * destination_factor,
		scaleFactorX * curStep, scaleFactorY * curStep);

	...
}


Please note: this will look rather crispy in old computers (for e.g. in an AMD 2400+, nVidia FX 5200, Windows XP).

PS: funny thing is, I'm using something similar to this to do the zoom effect when clicking the Quick Look icon in Finger XP (not released yet... though available in Mac OS X Source List thread).
0

#3 User is offline   Smaky Icon

  • Group: Member
  • Posts: 586
  • Joined: 19-April 08

Posted 11 December 2008 - 08:02 AM

I found the bug related to the memory issues I reported before. It was not really related to the code shown but to the code that retrieved the AlphaChanel HBITMAP used to update the window. I was not doing a DeleteObject(HBITMAP) and so, the memory was being severly leaked.

Also found other small memory leaking errors in the process here and there... it seems that the problem is fixed now. Thanks matonga... I will study your advice on the animation... for the time being I will keep a simple zoom+fade-in that looks nice.
0

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic