Still pretty new to PB.
I want to do some RGB or grayscale image Pixel data (image manipulation) work. I'd like these ops to work fast. This is probably best done by working directly on memory - and if necessary, using some simple assembly language routines (I did this for 8-bit MPU's many years ago, so I'd like to have another try). The alternative seems to be DRAWing on images using PLOT and POINT which I suspect will be too slow.
I see plenty of PB commands for allocating/manipulating memory addresses as well as CatchImage.
How do I load an image from disk into memory and then get it's memory start address?
Help appreciated.
Work on image in memory
Assuming your on windows.
If you're intending to manipulate the image and save it back to file then it's probably better to use GDI methods.
The internal PB 2D functions are pretty fast, however if speed is really a concern then you will get a bit more speed from using a DIB.
This is generally the method I use found on the forum
[/code]
If you're intending to manipulate the image and save it back to file then it's probably better to use GDI methods.
The internal PB 2D functions are pretty fast, however if speed is really a concern then you will get a bit more speed from using a DIB.
This is generally the method I use found on the forum
Code: Select all
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
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
UsePNGImageDecoder()
UseJPEGImageDecoder()
If OpenWindow(0,0,0,800,600,"test",#PB_Window_SizeGadget | #PB_Window_SystemMenu | #PB_Window_MinimizeGadget |#PB_Window_MaximizeGadget | #PB_Window_ScreenCentered)
If FileSize("legion.jpg")= -1
InitNetwork()
ReceiveHTTPFile("http://www.idlearts.com/images/legion.jpg","legion.jpg")
EndIf
img1 = LoadImage(#PB_Any,"legion.jpg")
If img1
width = ImageWidth(img1)
height = ImageHeight(img1)
ResizeWindow(0,0,0,width,height)
ImageGadget(0,0,0,width,height,ImageID(img1))
*mem = AllocateMemory(width*height*4) ;32 bit image
CopyImageToMemory(img1,*mem)
Global *px.long, color.i
For x = 0 To width-1
For y = 0 To height-1
*px = *mem + ((x + (y * width)) << 2 )
;(BGR format)
B= *px\l & FF
G = *px\l >> 8 & $FF
R = *px\l >> 16 & $FF
*px\l = r << 16 ;set the pixel red
Next
Next
copymemorytoimage(*mem,img1)
SetGadgetState(0,ImageID(img1))
If *mem
FreeMemory(*mem)
*mem=0
EndIf
EndIf
EndIf
MessageRequester("DSA test","Image is now red")
- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
Also assuming Windows: here's another sample to study and play with. Note the speed of using a structured pointer to manipulate the color bits vs. point/plot:
Code: Select all
Declare Swap24(*bmp.BITMAP)
Declare Swap24_POINT_PLOT(img)
; Load the image into memory
UseJPEGImageDecoder()
LoadImage(0, #PB_Compiler_Home+"examples\sources\data\r2skin.jpg")
; Get information about the image
GetObject_(ImageID(0), SizeOf(BITMAP), @bmp.BITMAP)
With bmp
Debug \bmWidth
Debug \bmHeight
Debug \bmWidthBytes
Debug \bmBitsPixel
Debug \bmBits
EndWith
OpenWindow(0,0,0,bmp\bmWidth,bmp\bmHeight+70,"",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
ImageGadget(0,0,0,0,0,ImageID(0))
ButtonGadget(1,250,522,200,20,"Swap via structured pointer")
ButtonGadget(2,50,522,200,20,"Swap via point/plot")
ProgressBarGadget(3, 0,552,512,20,0,ImageWidth(0)*ImageHeight(0))
disabledebugger
Repeat
ev=WaitWindowEvent()
Select ev
Case #PB_Event_Gadget
Select EventGadget()
Case 1
Swap24(@bmp)
SetGadgetState(0,ImageID(0))
Case 2
Swap24_POINT_PLOT(0)
SetGadgetState(0,ImageID(0))
EndSelect
EndSelect
Until ev=#PB_Event_CloseWindow
Procedure Swap24(*bmp.BITMAP)
SetGadgetState(3,0) : cc=0
*buffer.RGBTRIPLE = *bmp\bmBits
While *buffer <= *bmp\bmBits+*bmp\bmWidthBytes**bmp\bmHeight-SizeOf(RGBTRIPLE)
Swap *buffer\rgbtBlue, *buffer\rgbtRed
*buffer+SizeOf(RGBTRIPLE) : cc+1
If cc%1000=0:SetGadgetState(3, cc):EndIf
Wend
EndProcedure
Procedure Swap24_POINT_PLOT(img)
SetGadgetState(3,0) : cc=0
StartDrawing(ImageOutput(img))
For j=0 To ImageHeight(img)-1
For i=0 To ImageWidth(img)-1
color = Point(i,j)
Plot(i,j, RGB(Blue(color),Green(color),Red(color)))
cc+1
If cc%1000=0:SetGadgetState(3, cc):EndIf
Next
Next
StopDrawing()
EndProcedure
BERESHEIT
Thanks for that. A bit complex for this noob - useful for me to try to work through it though.
Can I rephrase the question?
Is it realistic for me to work on a bitmap in memory without making any operating system calls? You say that the native PB commands are pretty quick.
The app is fairly simple - sort of very limited Photoshop - and I'm thinking about it running on a basic netbook (altho, I know zip about Linux at the moment).
Can I rephrase the question?
Is it realistic for me to work on a bitmap in memory without making any operating system calls? You say that the native PB commands are pretty quick.
The app is fairly simple - sort of very limited Photoshop - and I'm thinking about it running on a basic netbook (altho, I know zip about Linux at the moment).
- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
Re:
Sorry to bump an old topic but is there any way to convert these two functions for Mac OSX?idle wrote:Code: Select all
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 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

Re: Work on image in memory
here is an example of reading every pixel in an image, in memory, no Point()/Plot(), all OS:
Code: Select all
Structure RGB
r.a
g.a
b.a
EndStructure
Procedure ReadImage(hImg)
Protected *imgbuf, *pixel.RGB, Pixbytes, Rowbytes, x,y, width, height
If StartDrawing(ImageOutput(hImg))
width = ImageWidth(hImg)
height = ImageHeight(hImg)
Pixbytes = ImageDepth(hImg)/8
Rowbytes = DrawingBufferPitch()
*imgbuf = DrawingBuffer()
For y = 0 To height-1
*pixel = *imgbuf + (y * Rowbytes)
For x = 0 To width-1
Debug "RGB = " + Hex(*pixel\r)+" "+Hex(*pixel\g)+" "+Hex(*pixel\b) ;RGB on Linux/Mac, BGR on Windows
*pixel + Pixbytes
Next x
Next y
StopDrawing()
EndIf
EndProcedure
UsePNGImageDecoder(): UseJPEGImageDecoder()
Define hImg = LoadImage(#PB_Any,"c:\test.jpg")
If hImg = 0: MessageRequester("Error","Couldnt load image"): End: EndIf
ReadImage(hImg)
Re: Work on image in memory
Which function is that?Keya wrote:here is an example of reading every pixel in an image, in memory, no Point()/Plot(), all OS:Code: Select all
Structure RGB r.a g.a b.a EndStructure Procedure ReadImage(hImg) Protected *imgbuf, *pixel.RGB, Pixbytes, Rowbytes, x,y, width, height If StartDrawing(ImageOutput(hImg)) width = ImageWidth(hImg) height = ImageHeight(hImg) Pixbytes = ImageDepth(hImg)/8 Rowbytes = DrawingBufferPitch() *imgbuf = DrawingBuffer() For y = 0 To height-1 *pixel = *imgbuf + (y * Rowbytes) For x = 0 To width-1 Debug "RGB = " + Hex(*pixel\r)+" "+Hex(*pixel\g)+" "+Hex(*pixel\b) ;RGB on Linux/Mac, BGR on Windows *pixel + Pixbytes Next x Next y StopDrawing() EndIf EndProcedure UsePNGImageDecoder(): UseJPEGImageDecoder() Define hImg = LoadImage(#PB_Any,"c:\test.jpg") If hImg = 0: MessageRequester("Error","Couldnt load image"): End: EndIf ReadImage(hImg)
