No Rotate and Mirror methods for IImage
No Rotate and Mirror methods for IImage
Subj. It's too strange that engine like irrlicht has not such methods.
Sorry for my English, i'm from Russia.
If i makes mistakes in phrases you can correct me btw. ^_^
If i makes mistakes in phrases you can correct me btw. ^_^
Re: No Rotate and Mirror methods for IImage
Usually you don't want to rotate the image but you want to draw the image rotated. Which you can probably already do by setting the right matrices. But yes, doing that easier and from within the gui for example would be nice. I've seen some patches for that already (and done my own), but none of those really was engine quality (including my own which was just a hack to make it work in an ugly way).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Re: No Rotate and Mirror methods for IImage
Hi, maybe you can use these functions from my CImageFactory class ( remember this class does everything in software )
full class can be found here, with filters like sharpening and smoothing also resizing functions ( nearest, bilinear, bicubic interpolation ) and much drawing stuff
http://benjaminhampe.be.ohost.de/Irrlic ... eFactory.h
http://benjaminhampe.be.ohost.de/Irrlic ... actory.cpp
Here is the excerpt of rotation functions within the class you are looking for
Usage
Load image, i.e. earth.jpg from media dir and rotate 24 degrees ccw.
Result
but it lacks some smoothing and sharpening, also the borders of the image are very aliased, but it works
full class can be found here, with filters like sharpening and smoothing also resizing functions ( nearest, bilinear, bicubic interpolation ) and much drawing stuff
http://benjaminhampe.be.ohost.de/Irrlic ... eFactory.h
http://benjaminhampe.be.ohost.de/Irrlic ... actory.cpp
Here is the excerpt of rotation functions within the class you are looking for
Code: Select all
// Copyright (C) 2002-2013 BenjaminHampe@gmx.de
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CImageFactory.h"
#include <irrlicht.h>
#include <../source/Irrlicht/CImage.h>
#include <../source/Irrlicht/os.h>
//! quick copy hole image
IImage* CImageFactory::cloneImage( IImage* src ) const
{
if (!src)
return 0;
IImage* dst = new CImage( src->getColorFormat(), src->getDimension() );
if (!dst)
return 0;
void* srcPtr = src->lock();
void* dstPtr = dst->lock();
memcpy( dstPtr, srcPtr, src->getPitch() * src->getDimension().Height );
dst->unlock();
// dst->setColorKeyEnabled( IsColorKeyEnabled );
// dst->setColorKey( ColorKey );
// dst->setMemoryOwner( true );
return dst;
}
IImage* CImageFactory::rotateLeft( IImage* src ) const
{
if (!src)
return 0;
const core::dimension2du& Size = src->getDimension();
IImage* dst = new CImage( src->getColorFormat(), Size );
if (!dst)
return 0;
for (u32 y=0; y<Size.Height; y++)
{
for (u32 x=0; x<Size.Width; x++)
{
SColor color = src->getPixel(x,y);
dst->setPixel(y, Size.Width-1-x, color);
}
}
return dst;
}
IImage* CImageFactory::rotateRight( IImage* src ) const
{
if (!src)
return 0;
const core::dimension2du& Size = src->getDimension();
IImage* dst = new CImage( src->getColorFormat(), Size );
if (!dst)
return 0;
for (u32 y=0; y<Size.Height; y++)
{
for (u32 x=0; x<Size.Width; x++)
{
SColor color = src->getPixel(x,y);
dst->setPixel(Size.Height-1-y, x, color);
}
}
return dst;
}
bool CImageFactory::flipH( IImage* dst ) const
{
if (!dst) return false;
const core::dimension2du& Size = dst->getDimension();
u32 HalfWidth = Size.Width >> 1;
SColor color1, color2;
for (u32 y=0; y<Size.Height; y++)
{
for (u32 x=0; x<HalfWidth; x++)
{
color1 = dst->getPixel(x,y);
color2 = dst->getPixel(Size.Width-1-x,y);
dst->setPixel(x,y,color2);
dst->setPixel(Size.Width-1-x,y,color1);
}
}
return true;
}
bool CImageFactory::flipV( IImage* dst ) const
{
if (!dst) return false;
const core::dimension2du& Size = dst->getDimension();
u32 HalfHeight = Size.Height >> 1;
SColor color1, color2;
for (u32 y=0; y<HalfHeight; y++)
{
for (u32 x=0; x<Size.Width; x++)
{
color1 = dst->getPixel(x,y);
color2 = dst->getPixel(x,Size.Height-1-y);
dst->setPixel(x,y,color2);
dst->setPixel(x,Size.Height-1-y,color1);
}
}
return true;
}
bool CImageFactory::rotate180( IImage* dst ) const
{
if (!dst) return false;
const core::dimension2du& Size = dst->getDimension();
u32 m = Size.Height >> 1;
SColor color1, color2;
for (u32 y=0; y<m; y++)
{
for (u32 x=0; x<Size.Width; x++)
{
color1 = dst->getPixel(x,y);
color2 = dst->getPixel(x,Size.Height-1-y);
dst->setPixel(x,y,color2);
dst->setPixel(x,Size.Height-1-y,color1);
}
}
return true;
}
IImage* CImageFactory::rotate( IImage* src, f32 angleDegreesCCW, SColor* colorKey ) const
{
if (!src)
return 0;
const core::dimension2du& Size = src->getDimension();
// Winkel
while (angleDegreesCCW<0.0f) { angleDegreesCCW+=360.0f; }
while (angleDegreesCCW>=360.0f) { angleDegreesCCW-=360.0f; }
//
if (core::equals(angleDegreesCCW,0.0f))
{
return cloneImage(src);
}
else if (core::equals(angleDegreesCCW,90.0f))
{
return rotateLeft(src);
}
else if (core::equals(angleDegreesCCW,270.0f))
{
return rotateRight(src);
}
else if (core::equals(angleDegreesCCW,180.0f))
{
IImage* tmp = cloneImage(src);
rotate180(tmp);
return tmp;
}
else
{
// alpha
const f32 a=(360.0f-angleDegreesCCW)*core::DEGTORAD;
const f32 sa=sinf(a);
const f32 ca=cosf(a);
// gamma
const f32 g=angleDegreesCCW*core::DEGTORAD;
const f32 sg=sinf(g);
const f32 cg=cosf(g);
// BERECHNNUNG des Mittelpunktes von MEM
const f32 mXh=0.5f*(f32)Size.Width;
const f32 mYh=0.5f*(f32)Size.Height;
// BERECHNNUNG der Eckpunkte
const f32 Ax= mXh, Ay=-mYh;
const f32 Bx=-mXh, By=-mYh;
const f32 Cx=-mXh, Cy= mYh;
const f32 Dx= mXh, Dy= mYh;
// TRANSFORMATION der Eckpunkte
f32 Anx=Ax*ca - Ay*sa;
f32 Any=Ax*sa + Ay*ca;
f32 Bnx=Bx*ca - By*sa;
f32 Bny=Bx*sa + By*ca;
f32 Cnx=Cx*ca - Cy*sa;
f32 Cny=Cx*sa + Cy*ca;
f32 Dnx=Dx*ca - Dy*sa;
f32 Dny=Dx*sa + Dy*ca;
// BERECHNUNG der FINAL WIDTH and HEIGHT
f32 minX=0.0f, maxX=0.0f;
f32 minY=0.0f, maxY=0.0f;
if (Anx<minX) minX=Anx; if (Any<minY) minY=Any;
if (Anx>maxX) maxX=Anx; if (Any>maxY) maxY=Any;
if (Bnx<minX) minX=Bnx; if (Bny<minY) minY=Bny;
if (Bnx>maxX) maxX=Bnx; if (Bny>maxY) maxY=Bny;
if (Cnx<minX) minX=Cnx; if (Cny<minY) minY=Cny;
if (Cnx>maxX) maxX=Cnx; if (Cny>maxY) maxY=Cny;
if (Dnx<minX) minX=Dnx; if (Dny<minY) minY=Dny;
if (Dnx>maxX) maxX=Dnx; if (Dny>maxY) maxY=Dny;
f32 fdx=maxX-minX;
f32 fdy=maxY-minY;
u32 dx=core::abs_(core::round32(fdx));
u32 dy=core::abs_(core::round32(fdy));
core::stringc txt = "New Image with size (";
txt += dx;
txt += ", ";
txt += dy;
txt += ")";
os::Printer::log(txt.c_str(), ELL_INFORMATION);
// FINAL MEMBLOCK
IImage* dst = new CImage( src->getColorFormat(), core::dimension2du(dx,dy));
if (!dst)
return 0;
const core::dimension2du& Size2 = dst->getDimension();
// BERECHNUNG des Mittelpunktes von FINAL
f32 fdxh=0.5f*fdx;
f32 fdyh=0.5f*fdy;
// LET'S ROTATE
s32 x,y;
SColor color;
f32 x0,y0,x1,y1;
os::Printer::log("OK", ELL_INFORMATION);
// Fuer alle Punkte im Zielbild den entsprechenden Punkt im Ausgangsbild
// suchen. Dadurch entstehen keine Luecken im Bild.
for (u32 j=0; j<dy; j++)
{
for (u32 i=0; i<dx; i++)
{
if ( (i<Size2.Width) && (j<Size2.Height) )
{
x0=(f32)i-fdxh; // relativ zu FinalMem Mittelpunkt
y0=(f32)j-fdyh; // relativ zu FinalMem Mittelpunkt
x1=(cg*x0-sg*y0)+mXh; // relativ zu SourceMem Mittelpunkt
y1=(cg*y0+sg*x0)+mYh; // relativ zu SourceMem Mittelpunkt
x=core::round32(x1);
y=core::round32(y1);
// PIXEL von SourceMem
if ((x>=0) && (y>=0) && (x<Size.Width) && (y<Size.Height))
{
color=src->getPixel((u32)x, (u32)y);
}
else
{
if (colorKey)
color=*colorKey;
else
color.color = 0;
}
dst->setPixel( i,j,color );
}
}
}
return dst;
}
return 0;
}
Load image, i.e. earth.jpg from media dir and rotate 24 degrees ccw.
Code: Select all
video::IImage* img = driver->createImageFromFile( "../../media/earth.jpg");
video::CImageFactory factory;
video::IImage* img2 = factory.rotate( img, 24.0f );
driver->writeImageToFile( img2, "./rotated_earth.png");
img->drop();
img2->drop();
but it lacks some smoothing and sharpening, also the borders of the image are very aliased, but it works