is it possible editing bitmaps

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.
mab_5_uk
Posts: 12
Joined: Sun Dec 24, 2006 12:11 am
Location: Swansea

is it possible editing bitmaps

Post by mab_5_uk »

Does any know if it is possible to editing bitmaps in irrlicht

any help would be apriciated
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

How do you mean? Edit as in MsPaint, or edit as in getting the color values in an array, modify them and put them back in the bitmap?
If you don't have anything nice to say, don't say anything at all.
mab_5_uk
Posts: 12
Joined: Sun Dec 24, 2006 12:11 am
Location: Swansea

Post by mab_5_uk »

How do you mean? Edit as in MsPaint, or edit as in getting the color values in an array, modify them and put them back in the bitmap?

well knowing both wood be good but i ment Edit as in MsPaint i wish to marg two Textures together
Strong99
Admin
Posts: 687
Joined: Fri Mar 31, 2006 7:06 pm
Location: Netherlands
Contact:

Post by Strong99 »

no irrlicht doesn't have, you have to write your own than.
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

with lock() and unlock() you can get access to the bitmap datas and edit them, but there are no functions for editing, you'll have to write them on your own... ;)
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
mab_5_uk
Posts: 12
Joined: Sun Dec 24, 2006 12:11 am
Location: Swansea

Post by mab_5_uk »

thaks Acki im looking into lock() and unlock() now but this may be to advast for my any tips or links to sites that can help wood be apriciated
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

Firsth check which format your texture is: yourTexture->getColorFormat ()
Most probably it will be ECF_A1R5G5B5 or ECF_A8R8G8B8. Firsth one is basicly 16 bit while second 32 bit color format. Look at Irrlicht API documentation for more info.

So lets assume your texture is ECF_A8R8G8B8 format and you want to set all pixels of texture to color of your choice:

Code: Select all

// get pointer to texture data which in this case is basicly array of u32 values, you need to cast since function returns void pointer, however you already know color format and thus what to cast to
u32* p = (u32*)yourTexture->lock();

// now use that pointer to acces array
for(u32 i=0; i < yourTexture->getSize().Width * yourTexture->getSize().Height; i++)
{
    p[i] = video::SColor(255,255,0,0).color;
}

// now unlock texture
yourTexture->unlock();
If your texture happen to be in ECF_A1R5G5B5 format, use u16 and video::SColor(255,255,0,0).toA1R5G5B5() instead.

Now lets say you want to change specific pixel based on 2d coordinates:

Code: Select all

u32* p = (u32*)yourTexture->lock();

u32 x = 5;
u32 y = 10;

p[y * yourTexture->getSize().Height + x] = video::SColor(255,0,255,0).color;

yourTexture->unlock();
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

for non power-of-two textures the width will still be a power of two with a blank stripe down the right edge. so a row always starts at getPitch()*y rather than getWidth()*bytesPerPixel*y
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
mab_5_uk
Posts: 12
Joined: Sun Dec 24, 2006 12:11 am
Location: Swansea

Post by mab_5_uk »

thanks for all the help giys im going to try some of the stuff out now il let you no how i get on :D
mab_5_uk
Posts: 12
Joined: Sun Dec 24, 2006 12:11 am
Location: Swansea

Post by mab_5_uk »

Hi Guys

Thanks for all your help so far all works up to now but the problem I have now though is i wanna get the colour information from the texture and store it into some kind of array would there be any possible way to do it, I thought of the Data members - irr::video::getRed(), irr::video::getGreen(), irr::video::getBlue() but how would i go about doing this.
Or Maybe those commands have absolutly nothing to do with retrieving colour information from ITextures.

Please Any Help would be much appreciated.


Also if i wanted to create a bitmap from this colour information is there a possible way to do this in IRRLICHT.
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

to create texture from array look at IVideoDriver class:
createImageFromData() then addTexture(const c8 *name, IImage *image)

If you look at SColor class you see that value this class holds is actualy u32 value. Means the same value you can pass or get from texture pointer if your color format is 32 bit. So if you do:

Code: Select all

video::SColor mycolor(p[0]);
you can use

Code: Select all

mycolor.getBlue()
to find out blue component of that pixel. So I would use SColor class to make array or store u32 directly.

Those irr::video::getRed() are slightly diferent story but close related. If you look carefuly that function accepts u16 value and returns u32 value. Means it is used to convert color stored as u16 to u32. This can be useful if your texture color format is not 32 bit but only 16 bit. There are other functions which can convert betveen 32 bit color and 16 bit color like: A1R5G5B5toA8R8G8B8 and A8R8G8B8toA1R5G5B5. But beware if you convert 32 bit value to 16 bit value some bits get lost on the way naturaly so if you convert from 32 bit to 16 and back, you dont gona end with same walue so avoid converting if you can.

I would recomend you to store data in original format ...eighter u32 or u16. Then if you want to work with it in RGB mode use SColor or some other functions mentioned above.
mab_5_uk
Posts: 12
Joined: Sun Dec 24, 2006 12:11 am
Location: Swansea

Post by mab_5_uk »

hey arras you have been a great help. But i still dont seem to get the result i what. this is what im trying to do:

First of all im trying to merge these two textures together:

Image + Image

So i get this texture:

Image

I thought i could do this by making a template:

Image

then replacing the black with the Grass texture and white with the Path texture

this is the code i used

Code: Select all

const c8* testimg = "Template.bmp";
const c8* testimga = "Grass.jpg";
const c8* testimgb = "Path.jpg";

ITexture* TestBit;
ITexture* TestBita;
ITexture* TestBitb;

Code: Select all

        TestBit=driver->getTexture(testimg);
        TestBita=driver->getTexture(testimga);
        TestBitb=driver->getTexture(testimgb);

Code: Select all

                    u32* ImgTemp = (u32*)TestBit->lock();
                    u32* ImgA = (u32*)TestBita->lock();
                    u32* ImgB = (u32*)TestBitb->lock();
                    for(u32 i=0; i < TestBit->getSize().Width * TestBit->getSize().Height; i++) 
                    {
                        s32 TempA,TempR,TempG,TempB;
                        TempA = video::SColor(getAlpha(ImgTemp[i])).color;
                        TempR = video::SColor(getRed(ImgTemp[i])).color;
                        TempG = video::SColor(getGreen(ImgTemp[i])).color;
                        TempB = video::SColor(getBlue(ImgTemp[i])).color;
                        
                        s32 aa,ar,ab,ag;
                        aa = video::SColor(getAlpha(ImgA[i])).color;
                        ar = video::SColor(getRed(ImgA[i])).color;
                        ag = video::SColor(getGreen(ImgA[i])).color;
                        ab = video::SColor(getBlue(ImgA[i])).color;
                        
                        s32 ba,br,bg,bb;
                        ba = video::SColor(getAlpha(ImgB[i])).color;
                        br = video::SColor(getRed(ImgB[i])).color;
                        bg = video::SColor(getGreen(ImgB[i])).color;
                        bb = video::SColor(getBlue(ImgB[i])).color;
                        
                        if (TempR == 0)
                            ImgTemp[i] = video::SColor(aa,ar,ag,ab).color;
                        if (TempR > 0)
                            ImgTemp[i] = video::SColor(ba,br,bg,bb).color;
                    }
                    TestBit->unlock();
                    TestBita->unlock();
                    TestBitb->unlock();
but this is the result im getting

Image

do you know where im going wrong and if so can you send me the right code.

plus when i have made this new image i wish to save it as a bitmap.
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

This code should work:

Code: Select all

const c8* testimg = "Template.bmp";
    const c8* testimga = "Grass.jpg";
    const c8* testimgb = "Path.jpg";

    video::ITexture* TestBit;
    video::ITexture* TestBita;
    video::ITexture* TestBitb;
    
    TestBit=driver->getTexture(testimg);
    TestBita=driver->getTexture(testimga);
    TestBitb=driver->getTexture(testimgb);

    u32* ImgTemp = (u32*)TestBit->lock();
    u32* ImgA = (u32*)TestBita->lock();
    u32* ImgB = (u32*)TestBitb->lock();
    for(u32 i=0; i < TestBit->getSize().Width * TestBit->getSize().Height; i++)
    {
                        s32 TempA,TempR,TempG,TempB;
                        TempR = video::SColor(ImgTemp[i]).getRed();
                       
                        if (TempR == 0)
                            ImgTemp[i] = ImgA[i];
                        if (TempR > 0)
                            ImgTemp[i] = ImgB[i];
    }
    TestBit->unlock();
    TestBita->unlock();
    TestBitb->unlock();
also you may simplifi it a little bit and use getLuminance() instead of getRed() if you test against blac and white or gray image:

Code: Select all

video::ITexture* TestBit = driver->getTexture("Template.bmp");
    video::ITexture* TestBita = driver->getTexture("Grass.jpg");
    video::ITexture* TestBitb = driver->getTexture("Path.jpg");
    
    u32* ImgTemp = (u32*)TestBit->lock();
    u32* ImgA = (u32*)TestBita->lock();
    u32* ImgB = (u32*)TestBitb->lock();
    
    for(u32 i=0; i < TestBit->getSize().Width * TestBit->getSize().Height; i++) 
    {            
        if (video::SColor(ImgTemp[i]).getLuminance() == 0)
            ImgTemp[i] = ImgA[i];
        else 
            ImgTemp[i] = ImgB[i];
    }
    
    TestBit->unlock();
    TestBita->unlock();
    TestBitb->unlock();
To save your texture to file use this code:

Code: Select all

void *p = TestBit->lock();
    
    video::IImage *image = video::IImage *image = driver->createImageFromData(video::ECF_A8R8G8B8, TestBit->getSize(), p);
    
    driver->writeImageToFile(image, "result.bmp");
    
    TestBit->unlock();
mab_5_uk
Posts: 12
Joined: Sun Dec 24, 2006 12:11 am
Location: Swansea

Post by mab_5_uk »

hi arras you are a star the First bit bit of code you sent me works grate. :D

But when i add the save code and build it im getting

'class irr::video::IVideoDriver' has no member named 'writeImageToFile'

would you know whats gone rong :?
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

I dont have idea:
http://irrlicht.sourceforge.net/docu/cl ... r.html#a74
virtual bool irr::video::IVideoDriver::writeImageToFile(IImage *image, const c8 *filename) [pure virtual]

Writes the provided image to disk file.

Requires that there is a suitable image writer registered for writing the image to disk

Parameters:
image,: Image to write to disk
filename,: name of the file to write

Returns:
Returns true on success
What Irrlicht version are you using? For me it compile fine on OpenGl and Irrlicht 1.3
Post Reply