How do I clear an image?

New to FreeBASIC? Post your questions here.
datwill310
Posts: 355
Joined: May 29, 2015 20:37

How do I clear an image?

Post by datwill310 »

Warning: noob question alert.

How do I make an image all one colour when there are lots of colours within the image (therefore I can't use paint), and without being slow (using line and drawing rectangle over entire image which gets slow with large ones, and doesn't work with my example because it's like drawing a rectangle in air :P).
Direct pixel manipulation, right?

Code: Select all

'clear graphic
	for y as integer = 0 to 617 'height of graphic
		'address of first pixel/row = graphic+sizeof(fb.IMAGE)
		dim as ulong ptr row = graphic+sizeof(fb.IMAGE)+y*graphic->pitch
		for x as integer = 0 to gw-1 'holds graphic's width
			row[x] = rgba(0, 0, 0, 0)
		next
	next
I am trying to set every pixel's value to empty, i.e. entirely alpha so that you can see through image if it was drawn over something. Unfortunately, my game likes to crash when I do this :|.
What am I doing wrong?
And is it just me or should this be a part of FB? We have cls for the screen (both for graphic and text ports) but what about image buffers? This would be helpful for a lot of programmers I feel :/
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: How do I clear an image?

Post by MrSwiss »

1) loop counters (x, y), use UInteger on all up-counting loops.
(faster than Integer, no sign checks needed)
2) replace RGBA macro, with pre-set (ULong) Color (&h00FF00FF), aka: magic-pink.
3) use "w - 1/h - 1" (as constant or litteral), aka: get calculations out of parameters

Just what I've seen on your snippet, on "short notice".
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: How do I clear an image?

Post by datwill310 »

MrSwiss wrote:2) replace RGBA macro, with pre-set (ULong) Color (&h00FF00FF), aka: magic-pink.
Yes I have tried using the mask colour but sort of semi-alpha pixels can have pink still in them when I used trans.
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: How do I clear an image?

Post by fxm »

datwill310 wrote:

Code: Select all

'clear graphic
	for y as integer = 0 to 617 'height of graphic
		'address of first pixel/row = graphic+sizeof(fb.IMAGE)
		dim as ulong ptr row = graphic+sizeof(fb.IMAGE)+y*graphic->pitch
		for x as integer = 0 to gw-1 'holds graphic's width
			row[x] = rgba(0, 0, 0, 0)
		next
	next
What is the type of the pointer "graphic"
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: How do I clear an image?

Post by datwill310 »

fxm wrote:What is the type of the pointer "graphic"
fb.IMAGE buffer, it is a pointer.
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: How do I clear an image?

Post by fxm »

Perhaps try with:

Code: Select all

      dim as ulong ptr row = cast(ulong ptr, cast(ubyte ptr, graphic)+sizeof(fb.IMAGE)+y*graphic->pitch)
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: How do I clear an image?

Post by datwill310 »

fxm wrote:Perhaps try with:

Code: Select all

      dim as ulong ptr row = cast(ulong ptr, cast(ubyte ptr, graphic)+sizeof(fb.IMAGE)+y*graphic->pitch)
Thank you :) it works!
My approach is slow though :|, at least when I run it (I'm dealing with very large images, thousands of pixels). Do you know of anyway to clear the screen which is faster?
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: How do I clear an image?

Post by MrSwiss »

A Sub clearing an image:

Code: Select all

Sub CLR_IMG(ByVal pimg As Any Ptr, ByVal wth As Long, ByVal hgt As Long)
    Dim As ULong    clr = &h00FF00FF

    For y As UInteger = 0 To hgt
        For x As UInteger = 0 To wth
            Put pimg, (x, y), clr, PSet
        Next
    Next
End Sub
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: How do I clear an image?

Post by datwill310 »

MrSwiss wrote:A Sub clearing an image:

Code: Select all

Sub CLR_IMG(ByVal pimg As Any Ptr, ByVal wth As Long, ByVal hgt As Long)
    Dim As ULong    clr = &h00FF00FF

    For y As UInteger = 0 To hgt
        For x As UInteger = 0 To wth
            Put pimg, (x, y), clr, PSet
        Next
    Next
End Sub
Thanks for the help MrSwiss!
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: How do I clear an image?

Post by Tourist Trap »

datwill310 wrote: How do I make an image all one colour when there are lots of colours within the image (therefore I can't use paint), and without being slow (using line and drawing rectangle over entire image which gets slow with large ones, and doesn't work with my example because it's like drawing a rectangle in air :P).
Sorry, I just jump into this. I know that fxm has proposed something so it should be sufficent. But for this task I personnally do this in 2 steps:

Code: Select all

imageDestroy( imageptr )
imageptr = imageCreate(......)   ''choose a filling colour here
Just don't forget to always destroy an image before you reinitialize it with create, or you will have some memory leak, above all if you do this in a loop.

Sincerely clearing the image in a loop like this, for me, be useful only to clean a subbox inside the image, not the full image itself. Unless there is a speed issue that I ignore of course.

(edit: seen the answer below , all is right so)
Last edited by Tourist Trap on May 25, 2017 16:57, edited 2 times in total.
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: How do I clear an image?

Post by datwill310 »

Tourist Trap wrote:
datwill310 wrote: How do I make an image all one colour when there are lots of colours within the image (therefore I can't use paint), and without being slow (using line and drawing rectangle over entire image which gets slow with large ones, and doesn't work with my example because it's like drawing a rectangle in air :P).
Sorry, I just jump into this. I know that fxm has proposed something so it should be sufficent. But for this task I personnally do this in 2 steps:

Code: Select all

imageDestroy( imageptr )
imageptr = imageCreate(......)   ''choose a filling colour here
Just don't forget to always destroy an image before you reinitialize it with create, or you will have some memory leak, above all if you do this in a loop.
Yes it works very well but I'm finding it is slow to use repeatedly with large images.
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: How do I clear an image?

Post by Tourist Trap »

datwill310 wrote: Yes it works very well but I'm finding it is slow to use repeatedly with large images.
Have you tried to have an array with 2 indexes , 0 , 1. Where 0 is a cleared image of the colour you need, and 1 some image of the same size. I mean then you could do at any time:

Code: Select all

imageptr(1) = imageptr(0)
This is not tested, just an idea. So here you never destroy anything, just change the address of your imageptr(1) so that it is a clean image already prepared (imageptr 0) or a true image. I don't know, it seems simple.

Of course, this means that you have always everything loaded at any time, maybe it would be delicate with big pictures. Also I don't know what is slow, if it's imageDestroy or imageCreate or both of them.

Here is some uggly example, but there you only swap integers (addresses) of an array. So it really is simple. Left now to see if it fits your needs. Anyway here it's what it looks like:

Code: Select all

#include "fbgfx.bi"

dim as fb.IMAGE ptr     redImagePtr
dim as fb.IMAGE ptr     randomImagePtr

screenRes 400, 400, 32

redImagePtr     => imageCreate(200, 200, rgb(255,0,0), 32)
randomImagePtr  => imageCreate(200, 200, 0, 32)

dim as fb.IMAGE ptr     arrayOfImage(1)

arrayOfImage(0) => redImagePtr
arrayOfImage(1) => randomImagePtr

randomize TIMER
do
    '
    for i as integer = 1 to 10
        circle randomImagePtr, _ 
            (400*rnd(), 400*rnd()), _ 
            50*rnd(), _ 
            rgb(100*rnd(),100*rnd(),255*rnd())
    next i
    '
    arrayOfImage(1) => randomImagePtr
    put (100, 100), arrayOfImage(1), pset
    sleep 100
    '
    arrayOfImage(1) = arrayOfImage(0)
    put (100, 100), arrayOfImage(1), pset
    sleep 100
    '
loop until inkey()=chr(27)

imageDestroy redImagePtr
imageDestroy randomImagePtr

'eof
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: How do I clear an image?

Post by Tourist Trap »

Just because I asked, it seems that imageCreate() is the bottleneck:

Code: Select all

#include "fbgfx.bi"

screenRes 800, 400, 32

dim as fb.IMAGE ptr     imagePtrArray(99)

dim as double           creationTimeSingle
dim as double           creationTimeCumulated

dim as double           destructionTimeSingle
dim as double           destructionTimeCumulated

dim as integer          n
do
    ? n
    ? "destroy 100 images", 
    destructionTimeSingle   = TIMER
    for i as integer = 0 to 99
        imageDestroy (imagePtrArray(i))
    next i
    destructionTimeSingle   = TIMER - destructionTimeSingle
    destructionTimeCumulated += destructionTimeSingle
    ? destructionTimeCumulated
    
    ? "create 100 images", 
    creationTimeSingle   = TIMER
    for i as integer = 0 to 99
        imagePtrArray(i) = imageCreate(800, 400, rgb(100,100,100), 32)
    next i
    creationTimeSingle   = TIMER - creationTimeSingle
    creationTimeCumulated += creationTimeSingle
    ? creationTimeCumulated
    
    n += 1
loop until inkey()=chr(27) orElse n>25

?
? "creation time for: "; n*100; " images"
? creationTimeCumulated
? "destruction time for: "; n*100; " images"
? destructionTimeCumulated

getKey()

'(eof)
When I use a color depth of 16 and not 32 as usual, it speeds up ImageCreate by a factor of 6 on my computer:

Code: Select all

#include "fbgfx.bi"

screenRes 800, 400, 32

dim as fb.IMAGE ptr     imagePtrArray(99)

dim as double           creationTimeSingleBpp16
dim as double           creationTimeCumulatedBpp16

dim as double           creationTimeSingleBpp32
dim as double           creationTimeCumulatedBpp32

dim as double           destructionTimeSingle
dim as double           destructionTimeCumulated


dim as integer          n
do
    ? n
    ? "destroy 100 images", 
    destructionTimeSingle   = TIMER
    for i as integer = 0 to 99
        imageDestroy (imagePtrArray(i))
    next i
    destructionTimeSingle   = TIMER - destructionTimeSingle
    destructionTimeCumulated += destructionTimeSingle
    ? destructionTimeCumulated
    
    ? "create 100 images BPP=2", 
    creationTimeSingleBpp16   = TIMER
    for i as integer = 0 to 99
        imagePtrArray(i) = imageCreate(800, 400, rgb(100,100,100), 2)
    next i
    creationTimeSingleBpp16   = TIMER - creationTimeSingleBpp16
    creationTimeCumulatedBpp16 += creationTimeSingleBpp16
    ? creationTimeCumulatedBpp16
    
    for i as integer = 0 to 99
        imageDestroy (imagePtrArray(i))
    next i
    
    ? "create 100 images BPP=32", 
    creationTimeSingleBpp32   = TIMER
    for i as integer = 0 to 99
        imagePtrArray(i) = imageCreate(800, 400, rgb(100,100,100), 32)
    next i
    creationTimeSingleBpp32   = TIMER - creationTimeSingleBpp32
    creationTimeCumulatedBpp32 += creationTimeSingleBpp32
    ? creationTimeCumulatedBpp32
    
    n += 1
loop until inkey()=chr(27) orElse n>25

?
? "creation time for: "; n*100; " images of depth 16"
? creationTimeCumulatedBpp16
? "creation time for: "; n*100; " images of depth 32"
? creationTimeCumulatedBpp32
? "destruction time for: "; n*100; " images"
? destructionTimeCumulated

getKey()

'(eof)
thesanman112
Posts: 538
Joined: Jul 15, 2005 4:13

Re: How do I clear an image?

Post by thesanman112 »

image create is going to be slow because there is a lot of stuff going on with your computer memory, it has to assign a portion of that memory to your image so its going to take time, what might even be quicker is to assign a 'magic pink' page and take a piece of it each time to make a new image, using a buffer of ANY KIND is going to be faster then having to create a new image each time. Once bufferes are created to swap and modify with, then there shouldn't be any speed issues after that.
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: How do I clear an image?

Post by Tourist Trap »

thesanman112 wrote:iusing a buffer of ANY KIND is going to be faster then having to create a new image each time. Once bufferes are created to swap and modify with, then there shouldn't be any speed issues after that.
Do you mean that ImageCreate should only be called once, or (if we expect changes on the image) we should use some ANY PTR and work with it like exhibited by fxm?
Post Reply