Creating a buffer for image manipulation

Just starting out? Need help? Post your questions and find answers here.
omnikam
User
User
Posts: 27
Joined: Sat Apr 15, 2017 10:58 am

Creating a buffer for image manipulation

Post 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)
Fred
Administrator
Administrator
Posts: 16581
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Creating a buffer for image manipulation

Post by Fred »

You can use DrawingBuffer() for this
omnikam
User
User
Posts: 27
Joined: Sat Apr 15, 2017 10:58 am

Re: Creating a buffer for image manipulation

Post by omnikam »

I used DrawingBuffer at the end, but wasn't entirely sure if I used it correctly
Fred
Administrator
Administrator
Posts: 16581
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Creating a buffer for image manipulation

Post by Fred »

BTW, Plot() and Point() are very fast in PB
omnikam
User
User
Posts: 27
Joined: Sat Apr 15, 2017 10:58 am

Re: Creating a buffer for image manipulation

Post 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)
jamirokwai
Enthusiast
Enthusiast
Posts: 771
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Re: Creating a buffer for image manipulation

Post 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
Last edited by jamirokwai on Fri Mar 24, 2023 10:35 am, edited 1 time in total.
Regards,
JamiroKwai
omnikam
User
User
Posts: 27
Joined: Sat Apr 15, 2017 10:58 am

Re: Creating a buffer for image manipulation

Post by omnikam »

@jamirokwai.Thankyou, gives me more of an idea how to use it
Fred
Administrator
Administrator
Posts: 16581
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Creating a buffer for image manipulation

Post by Fred »

You should use DrawingBufferPitch() and DrawingBufferFormat() to be on the safe side when using DrawingBuffer()
omnikam
User
User
Posts: 27
Joined: Sat Apr 15, 2017 10:58 am

Re: Creating a buffer for image manipulation

Post 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
User avatar
Caronte3D
Addict
Addict
Posts: 1014
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: Creating a buffer for image manipulation

Post 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).
jamirokwai
Enthusiast
Enthusiast
Posts: 771
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Re: Creating a buffer for image manipulation

Post 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
Regards,
JamiroKwai
Post Reply