Advertisement Jump to content
Sign in to follow this  
Silvo

[SDL, C++, SDL_gfx] SDL_gfx's rotozoomSurface() crops image

This topic is 4547 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I just installed SDL_gfx today, and after a while of trying to figure out how to install it, and then how to use the rotozoom function, I worked it out. Now I have a problem. Here is my blitting function, Dont worry about reading it all:
void Blit(int x, int y, Part::Image imageA) {
		time.Set();
		Function::Print(log, "Iron::Mgr::Image::Load(" + imageA.image + ")", ironTime, true);
		Function::Print(log, "Checking for existing image...", time);
		if (imagePool.find(imageA.image) == imagePool.end()) {	//	Cant find image name in imagePool
			Function::Print(log, imageA.image + " not in pool, creating " + imageA.image + "...", time);
			Surface* temp = NULL;
			Surface* tempcpy = NULL;
			temp = IMG_Load(imageA.image.c_str());
			if (temp != NULL) {	//	Image loaded fine
				Function::Print(log, imageA.image + " opened fine, adding to pool", time);
				tempcpy = SDL_DisplayFormat(temp);
				Uint32 colourkey = SDL_MapRGB(tempcpy->format, 0x0, 0xFE, 0xFE);
				SDL_SetColorKey(tempcpy, SDL_RLEACCEL | SDL_SRCCOLORKEY, colourkey);
				imagePool[imageA.image] = SDL_DisplayFormat(tempcpy);
			} else {	//	Image did not load OK
				Function::Print(log, "ERROR: " + imageA.image + " was not loaded OK. Probably does not exist. Non critical error, " + imageA.image + " will not be blitted", time);
				Function::Print(errorLog, "ERROR: " + imageA.image + " could not be loaded. Continuing", ironTime);
				return;
			}
			SDL_FreeSurface(temp);
			SDL_FreeSurface(tempcpy); // - surface cannot be freed - being used in the imagePool
		}
		Function::Print(log, "Blitting image...", time);
		SDL_Rect offset;
		SDL_Rect clip;
		offset.x = x;
		offset.y = y;
		clip.x = imageA.x;
		clip.y = imageA.y;
		clip.w = imageA.w;
		clip.h = imageA.h;
		SDL_Rect zero;
		zero.x = 0;
		zero.y = 0;
		SDL_Surface* roto = SDL_DisplayFormat(imagePool[imageA.image]);
		SDL_BlitSurface(imagePool[imageA.image], &clip, roto, &zero);
		SDL_Surface* roto2 = NULL;
		roto2 = SDL_DisplayFormat(rotozoomSurface(roto, imageA.angle, imageA.zoom, IRON_SMOOTH));
		SDL_BlitSurface(roto2, &clip, screen, &offset);
		Function::Print(log, "Finished blitting!", time);
		Function::Print(log, "Done!", ironTime, true);
	}


Basically I have a class that stands in place of an SDL_Surface, and contains x, y, w, h, angle, zoom and filename members, and this Blit() function will grab the bit of the picture from its std::map. But that's not the trouble... rotozoomSurface returns an SDL_Surface* to it's newly rotated and zoomed image. However, the surface is the same size as the one passed in to it, and rotozoomSurface() crops its new image to fit on the surface, resulting in a portion of an image rather than the whole image. I tried changing this: roto2 = rotozoomSurface(roto, imageA.angle, imageA.zoom, IRON_SMOOTH); to this: roto2 = SDL_DisplayFormat( rotozoomSurface(roto, imageA.angle, imageA.zoom, IRON_SMOOTH) ); hoping that the image it returns will be the new size, but that doesnt work. Does anyone know any tips or tricks to get the rotated/zoomed image in its new size?? Also, it seems to have shredded my colourkeying, but I havent looked into that yet. Thanks!

Share this post


Link to post
Share on other sites
Advertisement
I have never used SDL_gfx before, but I bet when you call rotozoom it does it's job with the actual size of the surface. If that's what is doing, then I suggest to make the surface initially bigger than the actual image size, so you can rotate it correctly. This would involve to care about margins, so what you may want to do is to load the image, then blit it to another (bigger) surface in the center (a matter of adding a value to x and y), and then rotate it.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
The rotozoomSUrface does return the surface with new size.
try doing this:

roto2 = SDL_DisplayFormat(rotozoomSurface(roto, imageA.angle, imageA.zoom, IRON_SMOOTH));

dest.x = 0;
dest.y = 0;
dest.w = roto2.w;
dest.h = roto2.h;

SDL_BlitSurface(roto2, NULL, screen, NULL);


Shoul work just fine.

---
http://gamescreators.sf.net - Linux game programers site

Share this post


Link to post
Share on other sites
Thanks! All fixed.

The mistake was that after blitting the portion of the image wanted to roto, and then putting the rotated and zoomed image into roto2, I was still blitting the same size image as the one I grabbed. So, the new code is:

SDL_Surface* roto = SDL_DisplayFormat(imagePool[imageA.image]);
SDL_BlitSurface(imagePool[imageA.image], &clip, roto, &zero);
SDL_Surface* roto2 = NULL;
roto2 = SDL_DisplayFormat(rotozoomSurface(roto, imageA.angle, imageA.zoom, IRON_SMOOTH));
clip.x = 0;
clip.y = 0;
clip.w = roto2->w;
clip.h = roto2->h;
SDL_BlitSurface(roto2, &clip, screen, &offset);

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!