Image and texture scaling

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Lonesome Ducky
Competition winner
Posts: 1123
Joined: Sun Jun 10, 2007 11:14 pm

Image and texture scaling

Post by Lonesome Ducky »

I just thought I'd show this code snippet for scaling because I couldn't find one on the search and I decided to add mine:

Code: Select all

ITexture* ScaleTexture(ITexture* tTex, IVideoDriver* vDriver, dimension2d<s32> dSize) {
	IImage* iImage1;
	iImage1 = vDriver->createImageFromData(tTex->getColorFormat(), tTex->getSize(), tTex->lock());
	ITexture* tNew;
	tNew = vDriver->addTexture(dSize, "Texture");
	IImage* iImage2 = vDriver->createImageFromData(tTex->getColorFormat(), dSize, tNew->lock());
	iImage1->copyToScaling(iImage2);
	tTex->unlock();
	tTex = vDriver->addTexture(tTex->getName().c_str(),iImage2);
	return tTex;
	iImage1->drop();
	iImage2->drop();
	vDriver->removeTexture(tNew);
}
Here is how to use this function, say tex is a texture:

Code: Select all

tex = ScaleTexture(tex,driver,dimension2d<s32>(64,64));
this should not be used to scale image every frames as it is pretty slow.

Hope this helps.
sp00n
Posts: 114
Joined: Wed Sep 13, 2006 9:39 am

Re: Image and texture scaling

Post by sp00n »

it looks unbeleivable:
Lonesome Ducky wrote:

Code: Select all

	return tTex;
	iImage1->drop();
	iImage2->drop();
	vDriver->removeTexture(tNew);
}
Hope this helps.
Hope anyone don't use it. Or it's an April's fool?
Please learn C first and up this code-strings before return ;)
Now comments:
1)For what is this string:

Code: Select all

iImage2 = vDriver->createImageFromData(tTex->getColorFormat(), dSize, tNew->lock());
2) why are you using ITexture* ScaleTexture(ITexture* tTex, IVideoDriver* vDriver, dimension2d<s32> dSize) and not using void ScaleTexture(...), if it in any case changes the original texture? :)
Lonesome Ducky
Competition winner
Posts: 1123
Joined: Sun Jun 10, 2007 11:14 pm

Post by Lonesome Ducky »

Well I just kinda threw it together a long time ago, so I haven't looked through it much because it worked the first time. I guess I won't have it return anything and just directly edit the texture. Now that you've said what you have, I realize how wrong my code is. Thanks for telling me anyways. I guess I was just having one of my blonde moments. :wink:

Code: Select all

void ScaleTexture(ITexture* &tTex, IVideoDriver* vDriver, dimension2d<s32> dSize) {
   IImage* iImage1;
   iImage1 = vDriver->createImageFromData(tTex->getColorFormat(), tTex->getSize(), tTex->lock());
   ITexture* tNew;
   tNew = vDriver->addTexture(dSize, "Texture");
   IImage* iImage2 = vDriver->createImageFromData(tTex->getColorFormat(), dSize, tNew->lock());
tNew->unlock();
   iImage1->copyToScaling(iImage2);
   tTex->unlock();
   tTex = vDriver->addTexture(tTex->getName().c_str(),iImage2);
   iImage1->drop();
   iImage2->drop();
   vDriver->removeTexture(tNew);

}
sp00n
Posts: 114
Joined: Wed Sep 13, 2006 9:39 am

Post by sp00n »

Lonesome Ducky wrote:Well I just kinda threw it together a long time ago, so I haven't looked through it much because it worked the first time. I guess I won't have it return anything and just directly edit the texture. Now that you've said what you have, I realize how wrong my code is. Thanks for telling me anyways. I guess I was just having one of my blonde moments. :wink:
heh, i said you :"learn C first", now i say: "learn C++ also"
what is it in your code:

Code: Select all

void ScaleTexture(ITexture* &tTex, IVideoDriver* vDriver, dimension2d<s32> dSize) 
i like this sequence:ITexture* &tTex
And one more - when i said about reason why you're using ITexture* instead void, i'd mean that in your previous code you're changing an original texture as a parameter and as a returning value(Microsoft style). I think it would be better if you'll still alive declaration ITexture*, but in usage takes another(not original) texture, but it's only my IMHO :)
hybrid
Admin
Posts: 14144
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

sp00n, you can learn new C++ code every day. The code "ptr_t *& p" means a reference to a pointer. Something which was written "ptr_t ** p" in goold old C times.
And what you really want to say is still somewhat unclear, maybe take the time to write up the code you mean, seems to be simpler than always throwing in some stuff others have to interpret. At least having a parameter which is changed and then returned is not so uncommon to C++ programmes. After all that's how iostreams work. And it allows for these wonderful statements "str << something << other".
Last edited by hybrid on Sat Jan 26, 2008 12:09 am, edited 1 time in total.
Lonesome Ducky
Competition winner
Posts: 1123
Joined: Sun Jun 10, 2007 11:14 pm

Post by Lonesome Ducky »

Well I'm really making a fool of myself. :oops: I just don't totally understand pointers yet, I've been reading my C++ for Dummies book again to try to learn about them. But I guess my small amount of knowledge has gotten me this far so I thought I knew them pretty well. Thanks guys, I'm gonna start hitting the good ol' books again.
sp00n
Posts: 114
Joined: Wed Sep 13, 2006 9:39 am

Post by sp00n »

hybrid wrote:sp00n, you can learn new C++ code every day. The code "ptr_t *& p" means a reference to a pointer. Something which was written "ptr_t ** p" in goold old C times.
yeah, i know it and i use it continual at my work, but in this case it hasn't sence.
And what you really want to say is still somewhat unclear, maybe take the time to write up the code you mean, seems to be simpler than always throwing in some stuff others have to interpret. At least having a parameter which is changed and then returned is not so uncommon to C++ programmes. After all that's how iostreams work. And it allows for these wonderful statements "str << something << other".
hmmm, i know it also, i had want to say that it's "Microsoft style" it means that we have one unnecessary pointer and it will be better if we'll return another pointer to the texture and an original texture stills in our program. Sorry for the bad English.

but in any case simply scaling function for the textures needed i think:)
this code (IMHO) must be look at it way:

Code: Select all

ITexture * ScaleTexture(ITexture* tTex, IVideoDriver* vDriver, dimension2d<s32> dSize, bool saveold=false;) 
{ 
   IImage* iImage1; 
   iImage1 = vDriver->createImageFromData(tTex->getColorFormat(), tTex->getSize(), tTex->lock()); 
   ITexture* tNew; 
   tNew = vDriver->addTexture(dSize, "Texture"); 
   IImage* iImage2 = vDriver->createImageFromData(tTex->getColorFormat(), dSize, tNew->lock()); 
   tNew->unlock(); 
   iImage1->copyToScaling(iImage2); 
   tTex->unlock(); 
   if (saveold)
  {
       tNew = vDriver->addTexture(tTex->getName().c_str(),iImage2); 
       iImage1->drop(); 
       iImage2->drop(); 
       return tNew;
  }
  else
  {
       tTex = vDriver->addTexture(tTex->getName().c_str(),iImage2); 
       vDriver->removeTexture(tNew); 
       iImage1->drop(); 
       iImage2->drop(); 
       return tTex;
   }
}
And usage of this is for two ways:

Code: Select all

NewScalingTex =ScaleTexture(oldTex, newsize, true); 
or

Code: Select all

oldTex=ScaleTexture(oldTex,newsize);
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

hybrid wrote:The code "ptr_t *& p" means a reference to a pointer.
Just as an aside for anyone following along, a natural language description of any type is done by reading from right to left. That's how the compiler does it. Anything 'left' over at the left (ho ho, I kill me) is assumed to apply to the last type found, but that's syntactic sugar.

Code: Select all

int const * * const foo;
If you're used to reading right to left, then you know unambiguously that's a constant pointer to a (non-constant) pointer to a constant int. If you're not, then you'll have to think about it, and thinking can get you killed, soldier. We've lost too many good devs that way.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Not all C/C++ declarations can easily be read from right-to-left. Some declarations are read from the inside out...

Code: Select all

// declare a function named `signal' that takes as arguments an int
// and a pointer to a function that returns void and takes an int, and
// returns a pointer to a function that returns a void and takes an int.
// you read this one from the inside out.
void (*signal(int, void (*)(int)))(int);

// this could be read from right to left, but is simpler if you read from the
// inside out. it declares a function `f that takes an int and returns a
// reference to an array of two characters.
char (&f(int))[2];

// this is a combination of the two which is very confusing, and is most
// definitely not read from right to left. it declares a function `g' that takes
// an int and a function pointer, and returns a reference to an array of 2
// function pointers.
void (*(&f(int, void (*)(int)))[2])(int);
Travis
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

Okay this function definitely annoyed the crap out of me while I was trying to get it to work. So I fixed the problem in my implementation, which used to look the same as the last version of this code that was posted. So to any who has been having problems with this code, use the following:

Code: Select all

ITexture* ScaleTexture(IVideoDriver* Driver, ITexture* SrcTexture, vector2di destSize)
{
	static u32 counter = 0;
	IImage* SrcImage;
	IImage* DestImage;
	ITexture* IntTexture;
	stringc SrcName = "NewTexture";
	SrcName += counter;
	
	IntTexture = Driver->addTexture(destSize, "IntermediateTexture");
	SrcImage = Driver->createImageFromData(SrcTexture->getColorFormat(), SrcTexture->getSize(),
		SrcTexture->lock());
	DestImage = Driver->createImageFromData(SrcTexture->getColorFormat(), destSize,
		IntTexture->lock());
		
	IntTexture->unlock();
	SrcImage->copyToScaling(DestImage);
	SrcTexture->unlock();
	
	Driver->removeTexture(IntTexture);
	IntTexture = Driver->addTexture(SrcName.c_str(), DestImage);
	SrcImage->drop();
	DestImage->drop();
	
	++counter;
	return IntTexture;
}
Example:

Code: Select all

ITexture* scaledTexture = ScaleTexture(driver, driver->getTexture("media/testTexture.png"), vector2di(512, 512));
Simple to use, and it actually works!

FIX1: The problem with all the code above that was provided for this was the fact that a texture was trying to be added with the same name, which meant the texture cache wasn't loading it because it thought it was already there. So the solution was to simply remove the texture from the cache and then create the new scaled texture.

FIX2: This function also fixes the fact that the other two scale functions kept one unused intermediate texture in the texture cache upon every call to the function, which if you are dealing with big textures would eat up a whole lot of memory. That has been fixed with this function too.

FIX3: Also another problem was the fact that the scaled texture was being put into a texture with a static named, which means that upon two calls to ScaleTexture() you would only get the same texture back. So I fixed that by simply putting an incremental counter in there.

NOTE: This implementation provides so that your scalee ( :D ) texture won't be deleted, so just the scaled texture will be returned, and your scalee will be kept in memory. You will have to remove that yourself if you want.

Overall, this has been tested, and proven to withstand, and maintain 100 scale calls without crashing. Tell me about any problems you have.
TheQuestion = 2B || !2B
sp00n
Posts: 114
Joined: Wed Sep 13, 2006 9:39 am

Post by sp00n »

thanks Halifax for fixing and clearing
i wrote my code above without testing(cause i nowhere used this scaling), so i'm really be ashamed of my code :oops:

thanks again and good luck :)
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

Halifax wrote:Simple to use, and it actually works!...Overall, this has been tested...Tell me about any problems you have.
How could it been tested if it doesn't compile.. You need to switch the size's type from vector2di to dimension2di..
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
sp00n
Posts: 114
Joined: Wed Sep 13, 2006 9:39 am

Post by sp00n »

2MasterGod

from irrlicht.chm, vector2d.h
typedef vector2d< s32 > vector2di
//Typedef for integer 2d vector.
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

Code: Select all

IntTexture = Driver->addTexture(destSize, "IntermediateTexture"); 
1.4 API wrote:virtual ITexture* irr::video::IVideoDriver::addTexture ( const core::dimension2d< s32 > & size,
const c8 * name,
ECOLOR_FORMAT format = ECF_A8R8G8B8
) [pure virtual]
His destSize is vector2di and the methods gets a dimension2di for size..
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
sp00n
Posts: 114
Joined: Wed Sep 13, 2006 9:39 am

Post by sp00n »

yeah, you're right
just change vector2di to dimension2di in the function declaration and it compiles ok :)
Post Reply