Page 1 of 1

Creating a buffer for image manipulation

Posted: Thu Mar 23, 2023 2:25 pm
by omnikam
Could someone put me on the right path, I'm trying to use a buffer to store an image and then perform some manipulations, and then display the altered image
Unfortunately it's not working correctly I'm pretty sure drawingcolour and pixelcolour are not used in purebasic, but the rest of the code should be understood
The reason I'm trying to get this working is because they removed the usebuffer() command which messed up lots of cool post prossesing effects. So I'm hoping this will be a way around it

This is a code snipped, not functional
The process is to load an image into a buffer, perform some changes to the buffered image and display the image buffer

Code: Select all

; Load an image into a memory buffer
LoadImage(0, "image.bmp")
imageWidth = ImageWidth(0)
imageHeight = ImageHeight(0)
imageBufferSize = imageWidth * imageHeight * 4  ; 4 bytes per pixel (RGBA)
imageBuffer.l = AllocateMemory(imageBufferSize)
CopyImage(ImageOutput(0), imageBuffer)

; Create a new memory buffer to draw onto
drawingBuffer.l = CreateImage(imageWidth, imageHeight, #PB_Image_BGRA)

; Distort the image buffer by drawing onto the drawing buffer
For y = 0 To imageHeight - 1
  For x = 0 To imageWidth - 1
    ; Calculate the new x and y coordinates based on a sine wave
    newX = x + Sin(y / 10.0) * 10.0
    newY = y + Sin(x / 10.0) * 10.0
    
    ; Get the pixel value from the original coordinates
    pixel = PeekI(imageBuffer + (y * imageWidth + x) * 4)
    
    ; Set the pixel value at the new coordinates
    DrawingColor(pixel)
    DrawingPixel(newX, newY)
  Next
Next

; Display the distorted image buffer
DrawingBuffer(drawingBuffer, 100, 100, imageWidth, imageHeight)

; Free the memory buffers
FreeMemory(imageBuffer)
FreeImage(drawingBuffer)

Re: Creating a buffer for image manipulation

Posted: Thu Mar 23, 2023 2:29 pm
by Fred
You can use DrawingBuffer() for this

Re: Creating a buffer for image manipulation

Posted: Thu Mar 23, 2023 2:32 pm
by omnikam
I used DrawingBuffer at the end, but wasn't entirely sure if I used it correctly

Re: Creating a buffer for image manipulation

Posted: Thu Mar 23, 2023 3:24 pm
by Fred
BTW, Plot() and Point() are very fast in PB

Re: Creating a buffer for image manipulation

Posted: Thu Mar 23, 2023 3:49 pm
by omnikam
Thanks Fred I changed it to use plot and point

Code: Select all

; Load an image into a memory buffer
LoadImage(0, "image.bmp")
imageWidth = ImageWidth(0)
imageHeight = ImageHeight(0)
imageBufferSize = imageWidth * imageHeight * 4  ; 4 bytes per pixel (RGBA)
imageBuffer.l = AllocateMemory(imageBufferSize)
CopyImage(ImageOutput(0), imageBuffer)

; Create a new memory buffer to draw onto
drawingBuffer.l = CreateImage(imageWidth, imageHeight, #PB_Image_BGRA)

; Distort the image buffer by drawing onto the drawing buffer
For y = 0 To imageHeight - 1
  For x = 0 To imageWidth - 1
    ; Calculate the new x and y coordinates based on a sine wave
    newX = x + Sin(y / 10.0) * 10.0
    newY = y + Sin(x / 10.0) * 10.0
    
    ; Get the pixel value from the original coordinates
    pixel = PeekI(imageBuffer + (y * imageWidth + x) * 4)
    
    ; Set the pixel value at the new coordinates
   Point(pixel)
    Plot(newX, newY)
  Next
Next

; Display the distorted image buffer
DrawingBuffer(drawingBuffer, 100, 100, imageWidth, imageHeight)

; Free the memory buffers
FreeMemory(imageBuffer)
FreeImage(drawingBuffer)

Re: Creating a buffer for image manipulation

Posted: Thu Mar 23, 2023 4:38 pm
by jamirokwai
Just coded a function to flip an image top-down. It uses the Buffer, Fred is referring to!
The function will copy all lines from top to bottom into allocated memory but from bottom to top. Then it copies everything back to the DrawingBuffer.

@fred. I would assume, using Point & Plot is slower? But that may depend on the size of the image.

Edit: This is no general and all purpose function. It works for 32 bit images (hence the *4). And in case of images with odd height, it should avoid copying the middle line.

Code: Select all

Procedure MirrorY(theimageid)   ; Ctrl+M
    Protected linewidth, y, maxy, *tempimage, *sourceimage, tempimage
    
    *tempimage = AllocateMemory(ImageWidth(theimageid) * ImageHeight(theimageid) * 4)
    
    If IsImage(theimageid)
      StartDrawing(ImageOutput(theimageid))
      *sourceimage = DrawingBuffer()
      maxy = OutputHeight()
      linewidth = OutputWidth() * 4
      
      For y = 0 To maxy
        CopyMemory(*sourceimage + y * linewidth, *tempimage + (maxy - y) * linewidth, linewidth)
      Next y
      
      CopyMemory(*tempimage, *sourceimage, linewidth * maxy)
      
      StopDrawing()
      
      FreeMemory(*tempimage)
    EndIf
  EndProcedure
Edit #2: For the record. This is, what demivec sent me. Thanks for that! Works great.
This next code reflects the comment, Fred made below.

Code: Select all

Procedure MirrorY(theimageid)   ; Ctrl+M
    Protected linewidth, y, maxy, *tempimage, *sourceimage, tempimage, linepitch, midheight
    
    If IsImage(theimageid)
      StartDrawing(ImageOutput(theimageid))
      *sourceimage = DrawingBuffer()
      maxy = OutputHeight()
      linewidth = OutputWidth() * 4
      linepitch = DrawingBufferPitch()
      
      *tempimage = AllocateMemory(linepitch * maxy)

      CopyMemory(*sourceimage, *tempimage, linepitch * maxy)

      midheight = maxy / 2 - 1
      maxy - 1
      For y = 0 To midheight
        CopyMemory(*tempimage + y * linewidth, *sourceimage + (maxy - y) * linewidth, linewidth)
        CopyMemory(*tempimage + (maxy - y) * linewidth, *sourceimage + y * linewidth, linewidth)
      Next y
      
      StopDrawing()
      
      FreeMemory(*tempimage)
    EndIf
  EndProcedure

Re: Creating a buffer for image manipulation

Posted: Fri Mar 24, 2023 8:26 am
by omnikam
@jamirokwai.Thankyou, gives me more of an idea how to use it

Re: Creating a buffer for image manipulation

Posted: Fri Mar 24, 2023 9:15 am
by Fred
You should use DrawingBufferPitch() and DrawingBufferFormat() to be on the safe side when using DrawingBuffer()

Re: Creating a buffer for image manipulation

Posted: Fri Mar 24, 2023 1:36 pm
by omnikam
On every example given i receive a memory access violation error when i actually load any image and try to transform it, even the MirorY example resulted in error

Re: Creating a buffer for image manipulation

Posted: Fri Mar 24, 2023 1:51 pm
by Caronte3D
Probably you doesn't create a 32bits image, try to use: CreateImage(#image,width,height,32) when you create the image or modify the above procedure to work with 24 bits (so *3 instead of *4).

Re: Creating a buffer for image manipulation

Posted: Fri Mar 24, 2023 4:58 pm
by jamirokwai
Yes, the 4 is hardcoded for 32 bit-images. You can use DrawingBufferPixelFormat() and replace the 4 with the appropriate result.

https://www.purebasic.com/documentation ... ormat.html