Posted: Fri Sep 09, 2005 1:16 pm
It's perfectly possible, you only need to read and dump the x positions in reverse order.Isn't it possible to copy the memory backwards?
It's perfectly possible, you only need to read and dump the x positions in reverse order.Isn't it possible to copy the memory backwards?
fweil wrote:AJirenius,
Here is a sample code that allow to H/V flip an image.
The main part manages the H/V flip by pushing H and V keyboard keys.
It uses API image structures for a fast memory dump of theprocefore image bessing pixels in memory instead of using Point() and Plot() commands.
This is easy to use with any image, gadget image or sprite.
Code: Select all
Enumeration #Window_Main #Gadget_Image #Image EndEnumeration Procedure Create_Image(ImageWidth, ImageHeight) ImageID = CreateImage(#Image, ImageWidth, ImageHeight) StartDrawing(ImageOutput()) Box(0, 0, ImageWidth, ImageHeight, #Black) For i = 0 To 10000 Plot(Random(ImageWidth), Random(ImageHeight), Random($FFFFFF)) Next DrawingMode(1) BackColor(0, 0, 0) FrontColor(255, 255, 255) Locate(20, 20) DrawText("Image sample") StopDrawing() ProcedureReturn ImageID EndProcedure Procedure Image_To_Memory(Image, ImageWIdth, ImageHeight, ImageDepth, Address) hBmp = UseImage(Image) hDC = StartDrawing(ImageOutput()) bmi.BITMAPINFO bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER) bmi\bmiheader\biWidth = ImageWidth bmi\bmiheader\biHeight = ImageHeight bmi\bmiheader\biPlanes = 1 bmi\bmiheader\biBitCount = ImageDepth bmi\bmiheader\biCompression = #BI_RGB GetDIBits_(hDC, hBmp, 1, ImageHeight, Address, bmi, #DIB_RGB_COLORS) Dim Undo(ImageWidth, ImageHeight) CopyMemory(Address, @Undo(), (ImageWidth * ImageHeight - 1) * 4) StopDrawing() EndProcedure Procedure Memory_To_Image(Address, Image, ImageWIdth, ImageHeight, ImageDepth) hBmp = CreateImage(Image, ImageWidth, ImageHeight) hDC = StartDrawing(ImageOutput()) bmi.BITMAPINFO bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER) bmi\bmiheader\biWidth = ImageWidth bmi\bmiheader\biHeight = ImageHeight bmi\bmiheader\biPlanes = 1 bmi\bmiheader\biBitCount = ImageDepth bmi\bmiheader\biCompression = #BI_RGB SetDIBits_(hDC, hBmp, 1, ImageHeight, Address, bmi, #DIB_RGB_COLORS) StopDrawing() ProcedureReturn hBmp EndProcedure ; ; An horizontal flip consists in flipping the array ; For a fast rendering and a short source code, I prefer to use a set of two arrays ; Procedure Image_Horizontal_Flip(Image.l) UseImage(Image) ImageWidth = ImageWidth() ImageHeight = ImageHeight() ImageDepth = ImageDepth() Dim Pixels1(ImageHeight - 1, ImageWidth - 1) Dim Pixels2(ImageHeight - 1, ImageWidth - 1) Image_To_Memory(Image, ImageWidth, ImageHeight, ImageDepth, @Pixels1()) For x = 0 To ImageWidth - 1 For y = 0 To ImageHeight - 1 Pixels2(y, x) = Pixels1(y, ImageWidth - 1 - x) Next Next ProcedureReturn Memory_To_Image(@Pixels2(), Image, ImageWidth, ImageHeight, ImageDepth) EndProcedure ; ; A vertical flip consists in flipping the array ; As for horizontal flip, for a fast rendering and a short source code, I prefer to use a set of two arrays ; Procedure Image_Vertical_Flip(Image.l) UseImage(Image) ImageWidth = ImageWidth() ImageHeight = ImageHeight() ImageDepth = ImageDepth() Dim Pixels1(ImageHeight - 1, ImageWidth - 1) Dim Pixels2(ImageHeight - 1, ImageWidth - 1) Image_To_Memory(Image, ImageWidth, ImageHeight, ImageDepth, @Pixels1()) For x = 0 To ImageWidth - 1 For y = 0 To ImageHeight - 1 Pixels2(y, x) = Pixels1(ImageHeight - 1 - y, x) Next Next ProcedureReturn Memory_To_Image(@Pixels2(), Image, ImageWidth, ImageHeight, ImageDepth) EndProcedure WindowWidth = 640 WindowHeight = 480 ImageWidth = WindowWidth - 20 ImageHeight = WindowHeight - 20 If OpenWindow(#Window_Main, 0, 0, WindowWidth, WindowHeight, #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered, "MyWindow") AddKeyboardShortcut(#Window_Main, #PB_Shortcut_Escape, #PB_Shortcut_Escape) AddKeyboardShortcut(#Window_Main, #PB_Shortcut_H, #PB_Shortcut_H) AddKeyboardShortcut(#Window_Main, #PB_Shortcut_V, #PB_Shortcut_V) If CreateGadgetList(WindowID(#Window_Main)) ImageGadget(#Gadget_Image, 10, 10, ImageWidth, ImageHeight, Create_Image(ImageWidth, ImageHeight)) EndIf Quit = #False Repeat Select WaitWindowEvent() Case #PB_Event_CloseWindow Quit = #True Case #PB_Event_Menu Select EventMenuID() Case #PB_Shortcut_Escape Quit = #True Case #PB_Shortcut_H SetGadgetState(#Gadget_Image, Image_Horizontal_Flip(#Image)) Case #PB_Shortcut_V SetGadgetState(#Gadget_Image, Image_Vertical_Flip(#Image)) EndSelect EndSelect Until Quit EndIf CallDebugger End
Code: Select all
; purebasic survival guide - pb3.93
; graphics 6.pb - 27.02.2005 ejn (blueznl)
; http://www.xs4alnl/~bluez/datatalk/pure1.htm
;
; - mirroring a bitmap in memory
; - reading a bitmap file structure without purebasic commands
; - using images in a datasection
;
w_main_nr = 1
w_main_h = OpenWindow(w_main_nr,10,10,245,200,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"test")
;
; remember, reading from a file or from memory is basically the same thing, now if the image
; is already in memory, i can rotate it in memory, at least that's the theory :-)
;
; let's draw something first
;
image1_h = CatchImage(2,?image1_data)
StartDrawing(WindowOutput())
DrawImage(image1_h,10,10)
StopDrawing()
;
;
; checking the size of the image told me, that it was exactly the same size as the file, as expected :-)
;
; Debug ?image2_data_end - ?image2_data
;
; now the trick is: what's inside that file ie. inside that bitmap? a little search on the internet
; showed the following...
;
; a bitmap is always build up with four parts:
;
; - bitmapfileheader
; - bitmapinfoheader
; - rgbquad
; - byte
;
; let's start with the file header
;
*bitmapfileheader.BITMAPFILEHEADER ; actually, i only care about the offset
*bitmapfileheader = ?image1_data
;
; Debug *bitmapfileheader\bfType ; should always report 19778
; size = *bitmapfileheader\bfSize ; size of whole structure including headers
;
offset = *bitmapfileheader\bfOffBits ; this is where bitmap data is supposed to be
;
*bitmapinfoheader.BITMAPINFOHEADER
*bitmapinfoheader = *bitmapfileheader+SizeOf(BITMAPFILEHEADER)
;
; If *bitmapinfoheader\biCompression = 0 ; check for compressed images
; EndIf ; not implemented
;
image1_width = *bitmapinfoheader\biWidth ; size
image1_height = *bitmapinfoheader\biHeight ;
bits_pixel = *bitmapinfoheader\biBitCount ; bits per pixel
bytes_pixel = bits_pixel/8 ; bytes per pixel
bytes_row = image1_width*bytes_pixel ; bytes per row (unadjusted)
bytes_row = bytes_row+(bytes_row % 4) ; padd to multiples of 4
;
; colour table size depends on the number of bits per pixel
;
; - 1 - colour table has two entries
; - 4 - colour table has 16 entries
; - 8 - colour table has 256 entries
; - 24 - colour table has no entries
;
; Select pixel_bits
; Case 24
; colourtable_size = 0
; Default
; colourtable_size = Pow(2,pixel_bits) * 4
; EndSelect
; offset = 54+colourtable_size
;
; you can calculate the position of the first pixel, or use the value we found before
;
; so the first pixel must be at image2_data+offset
; well we now know where it is so we can change it!
;
; let's give the image a blue stripe on one side, why not?
;
*p = *bitmapfileheader+offset
For y = 0 To image1_width-1
For x = 0 To image1_width / 2
PokeB(*p+y*bytes_row+x*bytes_pixel,255)
Next x
Next y
;
; and show it...
;
image1_h = CatchImage(2,?image1_data)
StartDrawing(WindowOutput())
DrawImage(image1_h,90,10)
StopDrawing()
;
; note that i draw directly on the window, so the displayed contents will be overwritten if i move another window over it
; unless i take care of refresh myself... which i do not here :-)
;
; now let's mirror it
;
For y = 0 To image1_height-1
For x = 0 To Int(image1_width/2)
Select bits_pixel
Case 1 ; you add the variants yourself
Case 2
Case 4
Case 8
Case 24 ; 24 bits rgb
;
; where are those darn pixels
;
*p1.BYTE = *p+y*bytes_row+x*3
*p2.BYTE = *p+y*bytes_row+(image1_width-x-1)*3
;
; now swap 'm... blue...
;
b = *p1\b
*p1\b = *p2\b
*p2\b = b
;
; green...
;
g = *p1\b
*p1\b = *p2\b
*p2\b = g
;
; and red...
;
r = *p1\b
*p1\b = *p2\b
*p2\b = r
;
EndSelect
Next x
Next y
;
; and show it one more time
;
image1_h = CatchImage(2,?image1_data)
StartDrawing(WindowOutput())
DrawImage(image1_h,170,10)
StopDrawing()
;
Repeat
event = WaitWindowEvent()
Until event = #PB_Event_CloseWindow Or event = 513
;
; store the image in a datasection
;
DataSection
;
image1_data:
IncludeBinary("graphics\lightcircle.bmp")
image1_data_end:
;
EndDataSection