Page 1 of 2

is it possible editing bitmaps

Posted: Sun Apr 22, 2007 1:56 pm
by mab_5_uk
Does any know if it is possible to editing bitmaps in irrlicht

any help would be apriciated

Posted: Sun Apr 22, 2007 2:39 pm
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?

Posted: Sun Apr 22, 2007 2:55 pm
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

Posted: Sun Apr 22, 2007 3:04 pm
by Strong99
no irrlicht doesn't have, you have to write your own than.

Posted: Sun Apr 22, 2007 4:37 pm
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... ;)

Posted: Sun Apr 22, 2007 4:58 pm
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

Posted: Sun Apr 22, 2007 6:47 pm
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();

Posted: Sun Apr 22, 2007 7:34 pm
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

Posted: Sun Apr 22, 2007 9:44 pm
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

Posted: Tue Apr 24, 2007 10:53 pm
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.

Posted: Thu Apr 26, 2007 6:52 am
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.

Posted: Thu Apr 26, 2007 11:15 pm
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.

Posted: Fri Apr 27, 2007 12:32 am
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();

Posted: Fri Apr 27, 2007 10:17 am
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 :?

Posted: Fri Apr 27, 2007 11:11 am
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