Image Scaling problem. Get distorted image.

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
2DGamer
Posts: 7
Joined: Tue Nov 10, 2009 3:59 pm

Image Scaling problem. Get distorted image.

Post by 2DGamer »

I'm having problems scaling a texture.
I'm just working with some 2D stuff first, using draw2DImage.

When I use any of the copyToScaling functions, to enlarge a texture for example, my image gets distorted, though it becomes the correct size and all the extra pixels get created . It looks sort of rotated 45 degrees and it starts too far to the right and wraps around.

I can't upload an image at the moment.

Code: Select all

//! Create a temporary IImage of the texture, so we can copy (from) the pixels to create the transformed image/texture.
irr::video::IImage * image = pVideoDriver->createImageFromData(texture->getColorFormat(), irr::core::dimension2d<irr::u32>(textureFrame.getSize()), const_cast<irr::video::ITexture *>(texture)->lock() );

//! create a new scaled version of the IImage.
irr::video::IImage * scaledTransformedImage = pVideoDriver->createImage(texture->getColorFormat(), irr::core::dimension2d<irr::u32>(scaledTransformedFrame.getSize()));

image->copyToScalingBoxFilter(scaledTransformedImage);

//! unlock the texture.
const_cast<irr::video::ITexture *>(texture)->unlock();

this->m_pTransformedTexture = 
pVideoDriver->addTexture( ((irr::core::stringc)texture->getName() += (irr::core::stringc)".png").c_str(), scaledTransformedImage);

//! drop the images.
image->drop();
scaledTransformedImage->drop();
scaledTransformedFrame is the correct size, as is textureFrame.
The texture draws normally when not scaled.

Code: Select all

//! Draw the transformed texture.
pVideoDriver->draw2DImage(transformedTexture, ptDest);
Actually, even if I use copyTo function (no scaling), the new texture is distorted.
It looks weird because I'm not applying any rotation, but after using the copyTo function, it's rotated and not aligned to the left.
I'm not sure what to do.
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

I have that problem.
Don't know why yet.
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

I solved it... sadly without knowing what I was doing wrong.

Post by Ulf »

I solved it... sadly without knowing what I was doing wrong...

I found that if I use the createImageFromData function to create the original image from the texture, the image is distorted.
Even if you copy it back into another texture of equal size it will be distorted.
Maybe I am using it wrong, but I played with it for hours.

So, I use the createImage function. The one that takes a ITexture as a parameter.
This way it seems that it doesn't need to lock the texture.
I found that strange, though positive.
Can anyone confirm that?
Does createImage NOT need to lock the texture?
Because I don't get any warning in my compiler about a slow NPOT texture lock and unlock.
This is a naive question, but is that HW accelerated?
**EDIT**
I don't think it is, I'm just wondering why it doesn't unlock the texture.
More so, why it doesn't need to unlock the texture. Or if it does unlock the texture privately, why doesn't it say?
HW acceleration is when you can manipulate data directly in the GPU, is it?
**EDIT**

Code: Select all

//! Create an IImage of the texture, so we can copy the pixels to create the transformed texture.
irr::video::IImage * image = pVideoDriver->createImage(const_cast<irr::video::ITexture *>(texture), irr::core::vector2di(0, 0), texture->getSize() );

//! temporary CImage for the transformated texture.
irr::video::IImage * transformedImage;

//! set the bounds box of the transformed texture.
irr::core::recti transformedFrame(0, 0, 127, 127);

irr::core::dimension2di transformedSize = transformedFrame.getSize();

//! Create a temporary CImage for the transformated texture.
transformedImage = pVideoDriver->createImage(texture->getColorFormat(), irr::core::dimension2d<irr::u32>(transformedSize));

image->copyToScalingBoxFilter(transformedImage);

//! create the transformed texture from the transformed image.
irr::video::ITexture * pTransformedTexture = 
	pVideoDriver->addTexture( ((irr::core::stringc)texture->getName() += (irr::core::stringc)".png").c_str(),  transformedImage);

//! drop the images.
image->drop();
transformedImage->drop();
}
Is there a known problem with createImageFromData?
Or must I have been using it incorrectly?

Anyway, I can now scale textures, and it does not seem to lock and unlock the textures.
I wish somebody could explain it.
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Well, it does all this for you internally:

Code: Select all

IImage* CNullDriver::createImage(ITexture* texture, const core::position2d<s32>& pos, const core::dimension2d<u32>& size)
{
        if (pos==core::position2di(0,0) && size == texture->getSize())
        {
                IImage* image = new CImage(texture->getColorFormat(), size, texture->lock(true), false);
                texture->unlock();
                return image;
        }
So the createImageFromData is basically called in the function. Shouldn't really do any difference. If you can provide an example which reproduces differences between the two functions, I'd like to look into it.
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

I stripped it all down from my program and found that I was wrong.
So createImageFromData does work.
Must have been something else in my program.

I used the code below to test it. I played around with it a bit trying to get the fault, but it didn't happen. Results of images are all fine.

Code: Select all

#include <irrlicht.h>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif

int main()
{
	IrrlichtDevice *device =
		createDevice( video::EDT_SOFTWARE, dimension2d<u32>(640, 480), 16,
			false, false, false, 0);

	if (!device)
		return 1;

	//! Video Driver
	IVideoDriver* driver = device->getVideoDriver();

	//! fireball texture
	irr::video::ITexture * fireballTexture = driver->getTexture("../../media/fireball.bmp");

	//! create image of the fireball texture using "createImage"
	irr::video::IImage * fireBallImage = driver->createImage(fireballTexture, irr::core::vector2di(0, 0), fireballTexture->getSize() );

	//! create image of the fireball texture using "createImageFromData"
	irr::video::IImage * fireBallImageFromData = driver->createImageFromData(fireballTexture->getColorFormat(), fireballTexture->getSize(), fireballTexture->lock());
	fireballTexture->unlock();

	//! create a texture copy of the image made using "createImageFromData"
	irr::video::ITexture * fireballTextureFromData = 
		driver->addTexture( ((irr::core::stringc)fireballTexture->getName() += (irr::core::stringc)"1.png").c_str(), fireBallImageFromData);

	//! To scale the image. double size
	irr::core::dimension2di transformedSize(128, 128);
	
	//! Create an empty Image.
	irr::video::IImage * transformedImage = driver->createImage(fireballTexture->getColorFormat(), irr::core::dimension2d<irr::u32>(transformedSize));

	//! Copy from original fireball image into the empty image.
	fireBallImageFromData->copyToScalingBoxFilter(transformedImage);

	//! create the transformed texture from the transformed image.
	irr::video::ITexture * transformedTexture = 
		driver->addTexture( ((irr::core::stringc)fireballTexture->getName() += (irr::core::stringc)"2.png").c_str(), transformedImage);

	fireBallImage->drop();
	fireBallImageFromData->drop();
	transformedImage->drop();

	//! for draw2DImage function, to define the texture rect.
	recti fireballTextureFrame(0,0, 63, 63);
	recti transformedTextureFrame(0, 0, 127, 127);

	while(device->run())
	{
		driver->beginScene(true, true, SColor(255,100,101,140));

		driver->draw2DImage(fireballTexture, irr::core::vector2di(64, 64), fireballTextureFrame);
		driver->draw2DImage(fireballTextureFromData, irr::core::vector2di(64, 192), fireballTextureFrame);
		driver->draw2DImage(transformedTexture, irr::core::vector2di(64, 320), transformedTextureFrame);

		driver->endScene();
	}

	device->drop();

	return 0;
}

/*
That's it. Compile and run.
**/
I replaced createImageFromData with createImage in my project.
It doesn't make a difference to me, but later I will try to get createImageFromData working in my project.
So I can discover if I was doing something wrong previously, or if there is some kind of problem under certain circumstances.
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
Post Reply