|
Post by jeffg737 on Nov 9, 2022 11:03:12 GMT -5
I am running Liberty BASIC v4.03 under Windows 7, 64 bit. I need a method to (1) load a bitmap image of size 8872 x 6472 pixels, (2) extract a series of sub-images from it, using the upper-left and lower-right coordinates (or some other method) to choose each sub-image, and (3) save each of the resulting sub-images to a file. I have tried the techniques described at libertybasiccom.proboards.com/thread/1165/large-image-outside-graphic-window, but I am not getting the desired results. Any help or advice would be greatly appreciated. Thank you all.
|
|
|
Post by Rod on Nov 9, 2022 11:54:44 GMT -5
The one limitation is that the bmp you want to extract must be visible on your screen. So imagine you have loaded this large bmp. You have a smaller graphicbox to display it. This graphicbox cannot be larger than your visible display.
Now simply draw the large bmp to the smaller graphicbox but set the coordinates to suit. So x and y will be negative values to skew the portion you want to see into view.
-500 -500 will skew a 1000x1000 bmp to display its mid position in a much smaller graphicbox.
Once displayed you can getbmp save bmp etc.
|
|
|
Post by Walt Decker on Nov 9, 2022 13:57:04 GMT -5
UNTESTED!!!
'
STRUCT tRect, _ X AS LONG, _ Y AS LONG, _ X1 AS LONG, _ Y1 AS LONG
GRAPHICBOX #DMO.GFX, 0, 0, 200, 200 OPEN "DEMO" FOR WINDOW AS #DMO
GfxHndl = HWND(#DMO.GFX) CALLDLL #user32, "GetClientRect", GfxHndl AS ULONG, tRect AS STRUCT, RetVal AS VOID
GfxWide = tRect.X1.struct GfxHigh = tRect.Y1.struct
'ASSUMING THAT THE BITMAP IS 1000 X 1000
LOADBMP "DMOBMP", YourBitmapName
NumSectionsWide = INT(1000 / GfxWide) '<--- number of sections in bitmap NunSectionsHigh = IND(1000 / GfxHigh)
'<===== DISPLAY TOP LEFT CORNER OF BITMAP ===> Sectionx = 0 Sectiony = 0 X = -1 * Sectionx * NumSectionsWide '<--- calculate which portion of Y = -1 * Sectiony * NumSectionsHigh 'bitmap to display
PRINT #DMO.GFX, "DOWN" PRINT #DMO.GFX, "DRAWBITMAP DMOBMP";X;" ";Y PRINT #DMO.GFX, "FLUSH"
CALLDLL #kernel32, "Sleep", 1000 AS LONG, RetVal AS VOID
'<===== DISPLAY TOP PORTION OF BITMAP ===>
Sectionx = 1 X = -1 * Sectionx * NumSectionsWide
PRINT #DMO.GFX, "DOWN" PRINT #DMO.GFX, "DRAWBITMAP DMOBMP";X;" ";Y PRINT #DMO.GFX, "FLUSH"
CALLDLL #kernel32, "Sleep", 1000 AS LONG, RetVal AS VOID
'<===== DISPLAY LEFT SIDE OF BITMAP ===>
Sectiony = 1 Y = -1 * Sectiony * NumSectionsHigh X = 0 PRINT #DMO.GFX, "DOWN" PRINT #DMO.GFX, "DRAWBITMAP DMOBMP";X;" ";Y UNLOADBMP "DMOBMP" WAIT '
There are actually better API functions to do the above.
|
|
|
Post by Rod on Nov 9, 2022 14:02:26 GMT -5
We don’t need API to achieve this. Native loadbmp, drawbmp and bmpsave are all that’s needed.
|
|
|
Post by Walt Decker on Nov 9, 2022 14:05:16 GMT -5
I did not say that API was needed. I said there are better ways using API.
|
|
|
Post by Rod on Nov 9, 2022 15:23:41 GMT -5
There are even better machine code solutions!
|
|
|
Post by jeffg737 on Nov 9, 2022 16:25:53 GMT -5
Thank you for your reply.
I do not need to see my original loaded 8872 x 6472 pixel bitmap image or any of the copied bitmap images. I just need to copy a part of my original bitmap image from specified coordinates x1,y1 (upper left hand corner) and x2,y2 (lower right hand corner), and then save this copy to a file, all unseen.
|
|
|
Post by tsh73 on Nov 9, 2022 16:47:02 GMT -5
I was thinking 9000x6500 is too big for LB but I made that bitmap in Paint draw something on it and LB LOADBMP it and DRAWBMP with offset after I change offset, press Draw - it works, several times (until bored) (but a memory usage show 520 Mb and before I added CLS it crashed with Out Of Memory on second Draw )
So I can confirm - it does work. At least for me.
Put path to your big bitmap in [Load] section and try.
'Form created with the help of Freeform 3 v07-31-2015 'Generated on Nov 10, 2022 at 00:25:32
[setup.main.Window]
'-----Begin code for #main
nomainwin WindowWidth = 520 WindowHeight = 610 UpperLeftX=int((DisplayWidth-WindowWidth)/2) UpperLeftY=int((DisplayHeight-WindowHeight)/2)
'-----Begin GUI objects code
graphicbox #main.graphicbox5, 7, 67, 500, 500 button #main.button1,"Draw",[Draw], UL, 145, 17, 96, 25 TextboxColor$ = "white" 'put offset in a bitmap here textbox #main.txtX, 10, 7, 100, 25 textbox #main.txtY, 10, 32, 100, 25 button #main.button6,"Load",[Load], UL, 260, 17, 96, 25
'-----End GUI objects code
open "untitled" for window as #main print #main.graphicbox5, "down; fill white; flush" print #main, "font ms_sans_serif 10" print #main, "trapclose [quit.main]"
#main.graphicbox5, "line 0 0 500 500" #main.graphicbox5, "line 0 500 500 0" #main.graphicbox5, "getbmp bmp 0 0 500 500"
[main.inputLoop] 'wait here for input event wait
[Draw] 'Perform action for the button named 'button1'
#main.txtX "!contents? x$" X=val(x$) #main.txtY "!contents? y$" Y=val(y$) #main.graphicbox5 "cls" #main.graphicbox5 "drawbmp bmp ";0-X;" ";0-Y
wait
[Load] 'Perform action for the button named 'button6' loadbmp "bmp", "C:\Temp\60k.bmp" 'made 9000x6500 bitmap with Paint
'Insert your own code here
wait
[quit.main] 'End the program close #main end
|
|
|
Post by tsh73 on Nov 9, 2022 16:53:25 GMT -5
Well, native LB could load, show at any offset/save any visible parts. Obviously "all unseen" requires different approach.
|
|
|
Post by tsh73 on Nov 9, 2022 17:14:59 GMT -5
|
|
|
Post by Walt Decker on Nov 9, 2022 17:29:58 GMT -5
I do not think this will work, but
1) create a graphic box without border off your window 2) calculate the number of sections in both horizontal an vertical directions 3) calculate the negative x, y offset for each section 4) load the bitmap using LOADBMP "YOURTAG", BMP PATH AND NAME 5) draw the bitmap to the graphic box 6) get the result from the graphic box using "GETBMP YOURTAG 0 0 ";Gfxwide;" ";Gfxhigh 7) save the bitmap 8) unload the bitmap
If that does not work you will have to use User32.dll functions and either or both gdi32.dll/gdiplus.dll functions to accomplish the task.
|
|
|
Post by tenochtitlanuk on Nov 9, 2022 17:37:17 GMT -5
Old hands on the Forum will know I do such processing with ImageMagick. Straight off the 'net I found this code line... convert 8872x6472.bmp +repage -crop 1000x1000 tiles\tile%04d.bmp worked for me from the command line. I use LB under Linux/Wine. LB can call ImageMagick ( see the examples on my website) But simpler to do it yourself directly. I create a 8872x6472.bmp colour gradient file. Image shows the images the above command created in a few seconds- all the possible tiles. Lots of help online for how to select a particular single tile... INCIDENTALLY- tsh73 (anatoly) beat me to giving a native LB code example. My immediate reaction was why not use UpperLeftX and UpperLeftY to offset the graphic window off-screen, but with my setup at least LB doesn't use negatives. And I had thought it did! EDIT Ninja'd by Anatoly...
|
|
|
Post by Rod on Nov 10, 2022 4:44:32 GMT -5
Nice. It would of course be possible to manipulate the file directly and extract sub image data. The data can easily be written back out as a .bmp. There are several examples of direct .bmp file manipulation posted on the forum.
Essentially you read the header of the main file, decide how the sub images are to be sized and create a header for that size. Then suck out the image data and write it out with the new header.
It gets complicated if the input image can change format. If it is always going to be a 24 bit bmp then it gets a little easier. But how are the sub image sizes to be decided?
With this method there are less memory issues and no graphics display to deal with, it is all hidden.
|
|
|
Post by Walt Decker on Nov 10, 2022 17:57:21 GMT -5
Here is a little dll I put together from bits from other dlls. There are only 2 functions in it, both are shown in the sub. The zip contains: SPLIT_000._BAS SPLITGFX.DLL BLOCKS.PNG
|
|
|
Post by tenochtitlanuk on Nov 11, 2022 17:32:43 GMT -5
Could you clarify what the results should be? For me on Linux/Wine/LB I got the repeated set of sub-images shown below. Is that what is supposed to happen? I EXPECTED images 75x75 but not the row- repetition. nor for the edge cases to be as shown, since 1000/75 is non-integer. Sorry, I don't get it. My IM demo did what I expected.
|
|