Fastest way to "learn" an image's pixels?
-
- Addict
- Posts: 1264
- Joined: Wed Feb 28, 2007 9:13 am
- Location: London
Fastest way to "learn" an image's pixels?
I'm working on an image distortion routine, which needs every pixel's RGBA value for processing. The way I've got it just now is that the image is simply scanned beforehand, and its pixels' values stored in a 2-dimensional array. This takes time!
Unfortunately, using Point() during the distorting is not appropriate (nor possible), because at that time a completely new image is being drawn, based on the original.
Does anyone know of a "shortcut" to achieve what I want to achieve?
Also, would the prospects of a solution change if I didn't need every pixel's RGBA value? Distortion being as it is, the image is squashed, meaning that some of its original pixels are just irrelevant. Is there a way to handle two different images at once, and use Point() on the original image only when a pixel value is needed for the new image?
Unfortunately, using Point() during the distorting is not appropriate (nor possible), because at that time a completely new image is being drawn, based on the original.
Does anyone know of a "shortcut" to achieve what I want to achieve?
Also, would the prospects of a solution change if I didn't need every pixel's RGBA value? Distortion being as it is, the image is squashed, meaning that some of its original pixels are just irrelevant. Is there a way to handle two different images at once, and use Point() on the original image only when a pixel value is needed for the new image?
Re: Fastest way to "learn" an image's pixels?
Code: Select all
Procedure CopyMemoryToImage(Memory, ImageNumber)
Protected TemporaryDC, TemporaryBitmap.BITMAP, TemporaryBitmapInfo.BITMAPINFO
TemporaryDC = CreateDC_("DISPLAY", #Null, #Null, #Null)
GetObject_(ImageID(ImageNumber), SizeOf(BITMAP), TemporaryBitmap.BITMAP)
TemporaryBitmapInfo\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
TemporaryBitmapInfo\bmiHeader\biWidth = TemporaryBitmap\bmWidth
TemporaryBitmapInfo\bmiHeader\biHeight = -TemporaryBitmap\bmHeight
TemporaryBitmapInfo\bmiHeader\biPlanes = 1
TemporaryBitmapInfo\bmiHeader\biBitCount = 32
TemporaryBitmapInfo\bmiHeader\biCompression = #BI_RGB
SetDIBits_(TemporaryDC, ImageID(ImageNumber), 0, TemporaryBitmap\bmHeight, Memory, TemporaryBitmapInfo, #DIB_RGB_COLORS)
DeleteDC_(TemporaryDC)
EndProcedure
Procedure CopyImageToMemory(ImageNumber, Memory)
Protected TemporaryDC, TemporaryBitmap.BITMAP, TemporaryBitmapInfo.BITMAPINFO
TemporaryDC = CreateDC_("DISPLAY", #Null, #Null, #Null)
GetObject_(ImageID(ImageNumber), SizeOf(BITMAP), TemporaryBitmap.BITMAP)
TemporaryBitmapInfo\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
TemporaryBitmapInfo\bmiHeader\biWidth = TemporaryBitmap\bmWidth
TemporaryBitmapInfo\bmiHeader\biHeight = -TemporaryBitmap\bmHeight
TemporaryBitmapInfo\bmiHeader\biPlanes = 1
TemporaryBitmapInfo\bmiHeader\biBitCount = 32
TemporaryBitmapInfo\bmiHeader\biCompression = #BI_RGB
GetDIBits_(TemporaryDC, ImageID(ImageNumber), 0, TemporaryBitmap\bmHeight, Memory, TemporaryBitmapInfo, #DIB_RGB_COLORS)
DeleteDC_(TemporaryDC)
EndProcedure
then you call it like
Code: Select all
global mem = allocatememory(imagewidth(img)*imagheight(img) << 2)
copyImageToMemory(img,mem)
;create a pointer to the memory *px.long
define *px.long
x=0
while x<width
x=y
while y<height
*px = *mem + ((x + (y * width)) << 2 )
R=*px\l & $FF
G=*px\l >> 8 & $FF
B=*px\l >> 16 & $FF
y+1
wend
x+1
wend
;to set a pixel
*px\l = RGB(R,G,B)
maybe syntax errors in that as I just typed it direct in the box and it looks funny with the new theme

- Kaeru Gaman
- Addict
- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
Re: Fastest way to "learn" an image's pixels?
if you do it right, none of the original pixels are ever irrelevant.some of its original pixels are just irrelevant.
you need to calculate a new pixel's color from a weighted average of the surrounding source pixels, quite like antialias or smoothing.
... from what I see at first glance, idle's routines should help you best to directly access the images' mem. that's fast as fast can.
oh... and have a nice day.
Re: Fastest way to "learn" an image's pixels?
By pity Idle, don't do that to me. My tears are flowing when I see that:
Get outside the main loop all this unneeded calculations. It doesn't have to be there. Our poor processor is working for nothing. Please. Do it for me!
Edit> I'm sorry, i didn't see that
Code: Select all
global mem = allocatememory(imagewidth(img)*imagheight(img) << 2)
copyImageToMemory(img,mem)
;create a pointer to the memory *px.long
define *px.long
x=0
while x<width
x=y
while y<height
*px = *mem + ((x + (y * width)) << 2 )
R=*px\l & $FF
G=*px\l >> 8 & $FF
B=*px\l >> 16 & $FF
y+1
wend
x+1
wend
;to set a pixel
*px\l = RGB(R,G,B)
Edit> I'm sorry, i didn't see that
Forget what I saidmaybe syntax errors in that as I just typed it direct in the box and it looks funny with the new theme

Re: Fastest way to "learn" an image's pixels?
well I did say might be errors but I couldn't see them, the result of being dyslexic.
-
- Addict
- Posts: 1264
- Joined: Wed Feb 28, 2007 9:13 am
- Location: London
Re: Fastest way to "learn" an image's pixels?
Thanks, Idle. The code works great!
What doesn't have to be there? Could the code be simplified?all this unneeded calculations. It doesn't have to be there
-
- Addict
- Posts: 1264
- Joined: Wed Feb 28, 2007 9:13 am
- Location: London
Re: Fastest way to "learn" an image's pixels?
Sorry, one more thing...What about the alpha channel?
And would this lineneed to be changed to?
Code: Select all
*px = *mem + ((x + (y * width)) << 2 )
R=*px\l & $FF
G=*px\l >> 8 & $FF
B=*px\l >> 16 & $FF
And would this line
Code: Select all
TemporaryBitmapInfo\bmiHeader\biCompression = #BI_RGB
Code: Select all
TemporaryBitmapInfo\bmiHeader\biCompression = #RGBA
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
Re: Fastest way to "learn" an image's pixels?
It's not a premature optimisation to see that this line in a two levels loop will be damn slow, and is totally useless, as its parts are coming directly from the loops.
So, without fully optimising, we try to have all the multiplications replaced by additions/substractions (as mul are really slow!) and we can get something like that :
Code: Select all
*px = *mem + ((x + (y * width)) << 2 )
So, without fully optimising, we try to have all the multiplications replaced by additions/substractions (as mul are really slow!) and we can get something like that :
Code: Select all
;create a pointer to the memory *px.long
Define *px.long
x=0
*px = *mem
width2=width+width
While x<width
*opx=*px
While y<height
R=*px\l & $FF
G=*px\l >> 8 & $FF
B=*px\l >> 16 & $FF
*px+width2
Wend
*px = *opx+2
Wend
;to set a pixel
*px\l = RGB(R,G,B)
Re: Fastest way to "learn" an image's pixels?
yes that much better for 2d access.
As for the alpha channel I don't think it's preserved in the dib, gdi doesn't support alpha channels.
if it did then its would just be a case of
A=*px\l >> 24 & $FF
Think you need another solution!
As for the alpha channel I don't think it's preserved in the dib, gdi doesn't support alpha channels.
if it did then its would just be a case of
A=*px\l >> 24 & $FF
Think you need another solution!
Re: Fastest way to "learn" an image's pixels?
Why doesn't anybody uses gdi+? Is there some issue?
Re: Fastest way to "learn" an image's pixels?
in my case because I don't know the API, perhaps Netmaestro would be better to ask.
-
- Addict
- Posts: 1264
- Joined: Wed Feb 28, 2007 9:13 am
- Location: London
Re: Fastest way to "learn" an image's pixels?
I've followed this advice, but it doesn't seem to speed up the process at all. 62ms either way!we try to have all the multiplications replaced by additions/substractions (as mul are really slow!)
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
Re: Fastest way to "learn" an image's pixels?
is that with the debugger off, djes method should be faster.
you could also try to switch the loop order in case it's causing it to page the memory.
it's no good asking a dyslexic for advice given two choices.
why don't you post what your trying to do exactly like are you trying to morph an image or deform an image and do you need it to have transparency
you could also try to switch the loop order in case it's causing it to page the memory.
it's no good asking a dyslexic for advice given two choices.
why don't you post what your trying to do exactly like are you trying to morph an image or deform an image and do you need it to have transparency
Re: Fastest way to "learn" an image's pixels?
Here is a method which is about 8% faster on my machine, idle. 

Code: Select all
Procedure CopyImageToMemory(ImageID, Memory)
Output=ImageOutput(ImageID)
hDC=StartDrawing(Output)
TemporaryBitmapInfo.BITMAPINFO
TemporaryBitmapInfo\bmiHeader\biSize=SizeOf(BITMAPINFOHEADER)
TemporaryBitmapInfo\bmiHeader\biWidth=ImageWidth(ImageID)
TemporaryBitmapInfo\bmiHeader\biHeight=ImageHeight(ImageID)
TemporaryBitmapInfo\bmiHeader\biPlanes=1
TemporaryBitmapInfo\bmiHeader\biBitCount=Imagedepth(ImageID)
TemporaryBitmapInfo\bmiHeader\biCompression=#BI_RGB
GetDIBits_(hDC,ImageID(ImageID),0,ImageHeight(ImageID),Memory,TemporaryBitmapInfo,#DIB_RGB_COLORS)
StopDrawing()
EndProcedure
-
- Addict
- Posts: 1264
- Joined: Wed Feb 28, 2007 9:13 am
- Location: London
Re: Fastest way to "learn" an image's pixels?
It's a while ago now, but here is the final version I came up with:
Code: Select all
Procedure.b ImageIntoPixelArray(img.i,Array arr.i(2),free.b) ; final version for an independent 2D array
If Not IsImage(img) : ProcedureReturn #False : EndIf
iw = ImageWidth(img)
ih = ImageHeight(img)
*mem = AllocateMemory(iw*ih << 2)
CopyImageToMemory(img,*mem)
If free
FreeImage(img)
EndIf
*px.LONG = *mem
For x = 0 To iw-1
ycounter = 0
For y = 0 To ih-1
calc = x+ycounter
*px = *mem + (calc<<2)
;If *px\l
arr(x,y) = RGBA(*px\l >> 16 & $FF, *px\l >> 8 & $FF, *px\l & $FF, *px\l >> 24 & $FF)
;EndIf
ycounter+iw
Next y
Next x
FreeMemory(*mem)
ProcedureReturn #True
EndProcedure
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."