[bb] Clipboard Image functions by markcw [ 1+ years ago ]

Started by BlitzBot, June 29, 2017, 00:28:40

Previous topic - Next topic

BlitzBot

Title : Clipboard Image functions
Author : markcw
Posted : 1+ years ago

Description : I recently wrote functions to copy/paste FreeImage bitmaps to/from the clipboard, so i thought i would do the same for Blitz3D images. They're a bit slower than the FreeImage functions, because they use read/writepixelfast.

You need a file named "User32.decls" in your "userlibs" folder with these.
Code: BASIC
.lib "User32.dll"

; Clipboard Functions
Api_CloseClipboard%():"CloseClipboard"
Api_EmptyClipboard%():"EmptyClipboard"
Api_GetClipboardData%(uFormat):"GetClipboardData"
Api_IsClipboardFormatAvailable%(format):"IsClipboardFormatAvailable"
Api_OpenClipboard%(hwnd):"OpenClipboard"
Api_SetClipboardData%(uFormat,hData):"SetClipboardData"
And a file named "Kernel32.decls" in your "userlibs" folder with these. [/i]

Code :
Code: blitzbasic
.lib "Kernel32.dll"

; Memory Management Functions
Api_GlobalAlloc%(uFlags,dwBytes):"GlobalAlloc"
Api_GlobalLock%(hMem):"GlobalLock"
Api_GlobalUnlock%(hMem):"GlobalUnlock"
Api_RtlCopyMemory(Destination,Source*,Length):"RtlMoveMemory"
Api_RtlMoveMemory(Destination*,Source,Length):"RtlMoveMemory"


Comments :


markcw(Posted 1+ years ago)

 So here is an example using the CopyImageToClipboard function.This only creates 24-bit bitmaps.
Code: BASIC
;Copy Image to Clipboard function, by markcw on 28 Jul 06

Graphics3D 640,480,0,2
SetBuffer BackBuffer()

image=LoadImage("yourname.bmp") ;load image

width=ImageWidth(image) ;get image info
height=ImageHeight(image)

ok=CopyImageToClipboard(image) ;copy image to clipboard

While Not KeyHit(1)

 Cls
 DrawImage image,50,50 ;draw the image

 Text 0,0,"OK, paste the current clipboard data to whatever"
 Text 0,12,"program you use to see the results of the image copy."
 Text 0,24,"image="+image+" width="+width+" height="+height+" ok="+ok

Flip
Wend

Function CopyImageToClipboard(himage)
 ;Copy a given Blitz3D image to the clipboard
 ;From "Copying a DIB to the clipboard", by John Simmons
 ;(http://www.codeproject.com)

 Local width,height,sizeBits,sizeInfo,sizeDIB,btmp,x,y,offset,hDIB,pbmi

 width=ImageWidth(himage)
 height=ImageHeight(himage)

 ;calculate bits, DWORD-aligned scanline (Width * BitCount) * Height
 sizeBits=((width*24+31)/32*4)*height
 sizeInfo=40 ;sizeof(BITMAPINFOHEADER)
 sizeDIB=sizeInfo+sizeBits ;total size

 btmp=CreateBank(sizeDIB) ;bank to store DIB

 ;calculate DWORD-aligned offset of bits for proper alignment
 ;we'll use biSize to store each pixel, we can fill it in after
 LockBuffer(ImageBuffer(himage))
 For y=0 To height-1
  offset=((width*24+31)/32*4)*y+sizeInfo ;start of next scanline
  For x=0 To width-1
   PokeInt btmp,0,ReadPixelFast(x,height-1-y,ImageBuffer(himage)) ;biSize
   PokeByte btmp,offset+(x*3),PeekByte(btmp,0) ;blue
   PokeByte btmp,offset+(x*3)+1,PeekByte(btmp,1) ;green
   PokeByte btmp,offset+(x*3)+2,PeekByte(btmp,2) ;red
  Next
 Next
 UnlockBuffer(ImageBuffer(himage))

 ;fill in the info header for our 24-bit DIB
 PokeInt btmp,0,sizeInfo ;biSize
 PokeInt btmp,4,width ;biWidth
 PokeInt btmp,8,height ;biHeight
 PokeShort btmp,12,1 ;biPlanes, must be 1
 PokeShort btmp,14,24 ;biBitCount
 PokeInt btmp,16,0 ;biCompression, RGB=0/RLE8=1/RLE4=2/BITFIELDS=3
 PokeInt btmp,20,sizeBits ;biSizeImage, zeros here mean "default"
 PokeInt btmp,24,0 ;biXPelsPerMeter
 PokeInt btmp,28,0 ;biYPelsPerMeter
 PokeInt btmp,32,0 ;biClrUsed
 PokeInt btmp,36,0 ;biClrImportant

 ;alloc memory block to store our DIB
 hDIB=Api_GlobalAlloc(66,sizeDIB) ;GHND=66, MOVEABLE=2|ZEROINIT=64

 If Not hDIB ;major bummer if we couldn't get memory block
  FreeBank btmp
  Return False ;fail code
 EndIf

 pbmi=Api_GlobalLock(hDIB) ;lock memory and get pointer to it

 Api_RtlCopyMemory(pbmi,btmp,sizeDIB) ;copy DIB to memory

 Api_GlobalUnlock(hDIB) ;unlock the DIB

 ;send the DIB to the clipboard
 If Api_OpenClipboard(0) ;hwnd
  Api_EmptyClipboard() ;free last data
  Api_SetClipboardData(8,hDIB) ;CF_DIB=8, hdata[bitmap]
  Api_CloseClipboard()
 EndIf

 FreeBank btmp
 Return True ;success code

End Function



markcw(Posted 1+ years ago)

 And here is an example using the PasteImageFromClipboard function. This will convert from 1/4/8-bit as well as 16/24/32-bit bitmaps.
Code: BASIC
;Paste Image from Clipboard function, by markcw on 29 Jul 06

Graphics3D 640,480,0,2
SetBuffer BackBuffer()

image=PasteImageFromClipboard() ;paste image from clipboard

width=ImageWidth(image) ;get image info
height=ImageHeight(image)

While Not KeyHit(1)

 Cls
 DrawImage image,50,50 ;draw the image

 Text 0,0,"image="+image+" width="+width+" height="+height

Flip
Wend

Function PasteImageFromClipboard()
 ;Paste the clipboard to a new Blitz3D image
 ;From "Copying a DIB to the clipboard", by John Simmons
 ;(http://www.codeproject.com)

 Local hDIB,himage,pbmi,btmp,sizeInfo,sizePal,width,height,bpp
 Local sizeBits,sizeDIB,x,y,offset,index,bytespp

 ;receive the bitmap from the clipboard as a DIB
 If Api_OpenClipboard(0) ;hwnd
  hDIB=Api_GetClipboardData(8) ;CF_DIB=8
  Api_CloseClipboard()
 EndIf

 If Not hDIB ;if we didn't get a DIB, return a dummy image
  himage=CreateImage(1,1)
  Return himage
 EndIf

 pbmi=Api_GlobalLock(hDIB) ;lock memory and get pointer to it

 btmp=CreateBank(40) ;initialize bank, we will resize it later

 Api_RtlMoveMemory(btmp,pbmi,40) ;move info header to bank
 sizeInfo=PeekInt(btmp,0) ;biSize

 ;calculate palette, Clipboard DIBs use the BITMAPINFO struct
 sizePal=PeekInt(btmp,32) ;biClrUsed
 If Not sizePal
  If PeekShort(btmp,14)<16 ;no color table for 16/24/32
   sizePal=1 Shl PeekShort(btmp,14) ;biBitCount, colors=2/16/256
  Else
   sizePal=PeekInt(btmp,16) ;biCompression, 16/32 use BI_BITFIELDS=3
  EndIf
 EndIf
 sizePal=sizePal*4 ;sizeof(RGBQUAD)

 width=PeekInt(btmp,4) ;biWidth
 height=PeekInt(btmp,8) ;biHeight
 bpp=PeekShort(btmp,14) ;biBitCount
 bytespp=bpp/8 ;bytes per pixel

 ;calculate bits, DWORD-aligned scanline (Width * BitCount) * Height
 sizeBits=((width*bpp+31)/32*4)*height
 sizeDIB=sizeInfo+sizePal+sizeBits ;total size

 ResizeBank btmp,sizeDIB ;resize bank to store DIB
 Api_RtlMoveMemory(btmp,pbmi,sizeDIB) ;move DIB to bank

 Api_GlobalUnlock(hDIB) ;unlock the DIB

 himage=CreateImage(width,height) ;new image to write

 ;calculate DWORD-aligned offset of bits for proper alignment
 ;we'll use biSize to store each pixel, we don't need it any more
 LockBuffer(ImageBuffer(himage))
 For y=0 To height-1
  offset=((width*bpp+31)/32*4)*y+sizeInfo+sizePal ;start of next scanline
  For x=0 To width-1
   If bpp=1
    index=PeekByte(btmp,offset+(x/8)) ;1-bit, looks nasty but it works
    ;work out the bit, invert it, bitmask the byte and convert to 0/1
    index=(index And (1 Shl (7-(x Mod 8)))) Shr (7-(x Mod 8))
   EndIf
   If bpp=4
    index=PeekByte(btmp,offset+(x/2)) ;4-bit, work out the nibble
    If x Mod 2 Then index=index And 15 ;get bits 0-3
    If Not x Mod 2 Then index=index Shr 4 ;get bits 4-7
   EndIf
   If bpp=8
    index=PeekByte(btmp,offset+x) ;8-bit, we have our index
   EndIf
   If bpp=24 Or bpp=32 ;get rgb offset
    PokeByte btmp,0,PeekByte(btmp,offset+(x*bytespp)) ;blue
    PokeByte btmp,1,PeekByte(btmp,offset+(x*bytespp)+1) ;green
    PokeByte btmp,2,PeekByte(btmp,offset+(x*bytespp)+2) ;red
   ElseIf bpp=16 ;rgb=565
    PokeByte btmp,0,(PeekShort(btmp,offset+(x*bytespp)) And 31) Shl 3 ;blue
    PokeByte btmp,1,((PeekShort(btmp,offset+(x*bytespp)) And 2016) Shr 5) Shl 2 ;green
    PokeByte btmp,2,((PeekShort(btmp,offset+(x*bytespp)) And 63488) Shr 11) Shl 3 ;red
   Else ;get palette index, 1/4/8-bit
    PokeByte btmp,0,PeekInt(btmp,sizeInfo+(index*4))
    PokeByte btmp,1,PeekInt(btmp,sizeInfo+(index*4)+1)
    PokeByte btmp,2,PeekInt(btmp,sizeInfo+(index*4)+2)
   EndIf
   WritePixelFast x,height-1-y,PeekInt(btmp,0),ImageBuffer(himage) ;biSize
  Next
 Next
 UnlockBuffer(ImageBuffer(himage))

 FreeBank btmp
 Return himage ;image handle

End Function



DjBigWorm(Posted 1+ years ago)

 This is really good, Thank you for sharing just what I have been looking for in a long while.


Ts Inventions(Posted 1+ years ago)

 Wow, this seems pretty interesting...I too have been wondering how to read/write ANY data from the clipboard in blitz for a very long time!So with this you can copy an image section/selection in M.S. Paint and then draw it into a graphics buffer in your Blitz program? [/i]