(Solved) math for resising images for screen display

Just starting out? Need help? Post your questions and find answers here.
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4790
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

(Solved) math for resising images for screen display

Post by Fangbeast »

I want to take an image from a database (i can do that), resize it on screen to account for the window frame widths and titlebar height, resize it so it looks fairly 'natural' (Close to the original image) and centre on screen.

I am having a little trouble with the math though. The example below has vague references to gadgets and windows and is only attempting to illustrate my illogic and not reproduce the entire 11,000 line program.

Can anyone see where I am going wrong with my math? Yes, I know I don't know what I am doing when it comes to math calculations so tell me something I don't know:):)




ExamineDesktops()

..Get the desktop work area

DesktopWidth.i = DesktopWidth(0)
DesktopHeight.i = DesktopHeight(0)

..Get the menu and frame widths of the opened window

WinFrameWidth.i = (WindowWidth(#MyWindow, #PB_Window_FrameCoordinate) - WindowWidth(#MyWindow, #PB_Window_InnerCoordinate)) / 2
TitleBarHeight.i = GetWindowTitleBarDetails(#MyWindow)

..The original height and width of a picture loaded from a database blob

PictureHorizontal.i = 2022
PictureVertical.i = 800

..Do desktop related height and width calculations before displaying

HorizontalWidth.i = PictureHorizontal.i - (WinFrameWidth.i * 2)
VerticalHeight.i = PictureVertical.i - TitleBarHeight.i - (WinFrameWidth.i * 2)

..Some debug stuff for me

Debug "Current window frame width: " + Str(WinFrameWidth.i)
Debug "Current window titlebar height: " + Str(TitleBarHeight.i)
Debug "Original picture width: " + Picture\Horizontal
Debug "Original picture height: " + Picture\Vertical
Debug "Picture width minus frame: " + Str(HorizontalWidth.i)
Debug "Picture height minus frame: " + Str(VerticalHeight.i)

..Do desktop related height and width calculations before displaying

If HorizontalWidth.i > DesktopWidth ; If the horizontal width is greater than the desktop
NewWidth.i = DesktopWidth ; Resize it to the desktop width minus the menu bar and frame
ElseIf HorizontalWidth.i < DesktopWidth ; If the horizontal width is less than the desktop
NewWidth.i = PictureHorizontal) ; Resize it to the original picture width minus the menu bar and frame
EndIf

..

If VerticalHeight.i > DesktopHeight ; If the vertical height is greater than the desktop
NewHeight.i = DesktopHeight ; Resize it to the desktop height
ElseIf VerticalHeight.i < DesktopHeight ; If the vertical height is less than the desktop
NewHeight.i = PictureVertical ; Resize it To the original picture minus the menu bar And frame
EndIf

..Now set the resized image to the image gadget

If PictureHandle.i
ResizeWindow(#MyWindow, #PB_Ignore, #PB_Ignore, NewWidth.i, Newheight.i)
ResizeGadget(#MyGadget, #PB_Ignore, #PB_Ignore, NewWidth.i, Newheight.i)
ResizeImage(PictureHandle.i, NewWidth.i, Newheight.i, #PB_Image_Smooth)
SetGadgetState(#MyGadget, ImageID(PictureHandle.i))
EndIf
Last edited by Fangbeast on Fri Dec 18, 2015 7:24 am, edited 1 time in total.
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
infratec
Always Here
Always Here
Posts: 7623
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: math for resising images for screen display

Post by infratec »

Hi,

try this:

Code: Select all

#MyWindow = 0
#MyGadget = 0


Define.f WidthFactor, HeightFactor, Factor

ExamineDesktops()

;..Get the desktop work area

DesktopWidth = DesktopWidth(0)
DesktopHeight = DesktopHeight(0)


Debug "Desktop: " + Str(DesktopWidth) + " x " + Str(DesktopHeight)

OpenWindow(#MyWindow, 0, 0, 300, 200, "FangBeast Resizer", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
ImageGadget(#MyGadget, 0, 0, 0, 0, 0)


WinFrameWidth.i = (WindowWidth(#MyWindow, #PB_Window_FrameCoordinate) - WindowWidth(#MyWindow, #PB_Window_InnerCoordinate))
WinFrameHeigth.i = (WindowHeight(#MyWindow, #PB_Window_FrameCoordinate) - WindowHeight(#MyWindow, #PB_Window_InnerCoordinate))

;..The original height And width of a picture loaded from a database blob


PictureHandle = CreateImage(#PB_Any, 4022, 1000)
PictureWidth = ImageWidth(PictureHandle)
PictureHeight = ImageHeight(PictureHandle)


NewWinWidth = PictureWidth + WinFrameWidth
NewWinHeight = PictureHeight + WinFrameHeigth

;..Do desktop related height And width calculations before displaying

WidthFactor = 1.0
HeightFactor = 1.0
Factor = 1.0

If NewWinWidth > DesktopWidth
  Debug "A"
  WidthFactor = DesktopWidth / NewWinWidth
EndIf

If NewWinHeight > DesktopHeight
  Debug "B"
  HeightFactor = DesktopWidth / NewWinHeight
EndIf

If WidthFactor < HeightFactor
  Factor = WidthFactor
EndIf

If HeightFactor < WidthFactor
  Factor = HeightFactor
EndIf

Debug Factor

;..Some Debug stuff For me

Debug "NewWindow (outer size): " + Str(NewWinWidth * Factor)  + " x " + Str(NewWinHeight * Factor)

NewWinWidth = NewWinWidth * Factor - WinFrameWidth
NewWinHeight = NewWinHeight * Factor - WinFrameHeigth

Debug "NewWindow (inner size): " + Str(NewWinWidth)  + " x " + Str(NewWinHeight)



;..Now set the resized image To the image gadget

If PictureHandle
  Debug "Located at: " + Str((DesktopWidth - NewWinWidth - WinFrameWidth) / 2) + " / " + Str((DesktopHeight - NewWinHeight - WinFrameHeigth) / 2)
  
  ResizeWindow(#MyWindow, (DesktopWidth - NewWinWidth - WinFrameWidth) / 2, (DesktopHeight - NewWinHeight - WinFrameHeigth) / 2, NewWinWidth, NewWinHeight)
  ResizeImage(PictureHandle.i, NewWinWidth, NewWinHeight, #PB_Image_Smooth)
  SetGadgetState(#MyGadget, ImageID(PictureHandle.i))
EndIf


Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
It took so long, cause I need to write a working code :wink:

But...
The height of the taskbar is not included.

Bernd
Last edited by infratec on Wed Dec 16, 2015 11:48 am, edited 2 times in total.
User avatar
TI-994A
Addict
Addict
Posts: 2741
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: math for resising images for screen display

Post by TI-994A »

Fangbeast wrote:...resize it so it looks fairly 'natural' (Close to the original image) and centre on screen.
If, by looking fairly natural, you mean to proportionately display an image at full-screen size, this should do it:

Code: Select all

LoadImage(0, #PB_Compiler_Home + "Examples/Sources/Data/Geebee2.bmp")
wFlags = #PB_Window_SystemMenu | #PB_Window_Maximize
OpenWindow(0, #PB_Any, #PB_Any, 400, 200, "ImageViewer", wFlags)

aspectRatio.f = ImageHeight(0) / ImageWidth(0)
imgWidth = WindowWidth(0)
imgHeight = imgWidth * aspectRatio
img_X = 0
img_Y = (WindowHeight(0) - imgHeight) / 2
If imgHeight > WindowHeight(0)
  aspectRatio = ImageWidth(0) / ImageHeight(0)
  imgHeight = WindowHeight(0)
  imgWidth = imgHeight * aspectRatio
  img_X = (WindowWidth(0) - imgWidth) / 2
  img_Y = 0  
EndIf

ResizeImage(0, imgWidth, imgHeight)
ImageGadget(0, img_X, img_Y, 0, 0, ImageID(0))

While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
Here's a slightly more fancy version that initially sizes the window to the dimensions of the image (if it's not bigger), and resizes and centres the image as the window is resized:

Code: Select all

UseJPEGImageDecoder()
UsePNGImageDecoder()

Procedure SizeImage()
  CopyImage(1, 0)
  aspectRatio.f = ImageHeight(0) / ImageWidth(0)
  imgWidth = WindowWidth(0)
  imgHeight = imgWidth * aspectRatio
  img_X = 0
  img_Y = (WindowHeight(0) - imgHeight) / 2
  If imgHeight > WindowHeight(0)
    aspectRatio = ImageWidth(0) / ImageHeight(0)
    imgHeight = WindowHeight(0)
    imgWidth = imgHeight * aspectRatio
    img_X = (WindowWidth(0) - imgWidth) / 2
    img_Y = 0  
  EndIf  
  If imgWidth And imgHeight
    ResizeImage(0, imgWidth, imgHeight)
    SetGadgetState(0, ImageID(0))
    ResizeGadget(0, img_X, img_Y, #PB_Ignore, #PB_Ignore)
  EndIf
EndProcedure

imgTypes.s = "Images|*.bmp;*.jpg;*.png | All files (*.*) | *.*"
If LoadImage(1, OpenFileRequester("Select Image:", "", imgTypes, 0))
  
  wFlags = #PB_Window_MaximizeGadget | #PB_Window_Maximize | 
           #PB_Window_ScreenCentered | #PB_Window_SizeGadget
  OpenWindow(0, #PB_Any, #PB_Any, 600, 400, "ImageViewer", wFlags)
  ImageGadget(0, 0, 0, 0, 0, 0)
  
  If ImageWidth(1) > WindowWidth(0) Or ImageHeight(1) > WindowHeight(0)
    SizeImage()
  Else
    wFlags ! #PB_Window_Maximize
    OpenWindow(0, #PB_Any, #PB_Any, ImageWidth(1), ImageHeight(1), "", wFlags)
    ImageGadget(0, 0, 0, 0, 0, ImageID(1))
  EndIf
  
  BindEvent(#PB_Event_SizeWindow, @SizeImage())
  While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend 
EndIf
Hope it helps; assuming it's what you're looking for, of course. :wink:
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
infratec
Always Here
Always Here
Posts: 7623
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: math for resising images for screen display

Post by infratec »

Ups..

forgot 'ScreenCentered'.

Is fixed now.
infratec
Always Here
Always Here
Posts: 7623
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: math for resising images for screen display

Post by infratec »

It looks like that ResizeWindow() is buggy at x and y.

It looks that the border of the window is not respected.

Hm....
Maybe it's a win7 behaviour, because if you maximize any program, you don't see the rounded edges of the windows.

Bernd
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4790
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: math for resising images for screen display

Post by Fangbeast »

infratec wrote:It looks like that ResizeWindow() is buggy at x and y.

It looks that the border of the window is not respected.

Hm....
Maybe it's a win7 behaviour, because if you maximize any program, you don't see the rounded edges of the windows.

Bernd
But something else went wrong with your code here. Desktop Height was 900, you created an image of 1000 as a height but resized it (vertically) to 1/3r'd of the desktop?

What I wanted to do was:

If image is smaller than the desktop, no resizing must occur, must be centred in the window
If image is larger than the desktop (vertical AND horizontal), it must be resized to the desktop size.
If image vertical OR horizontal is larger than the desktop, some sort of proportional resizing must occur.

Sometimes, only one dimension is larger than the desktop (Either vertical or horizontal) and resizing looks odd when I try it. (Squashed, squished, squashed).

Paint Shop Pro (Years ago) had a lovely image resampler for their resizing filter that made any image look good resized, even when it was stamp sized. Would have loved to have that.
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4954
Joined: Sun Apr 12, 2009 6:27 am

Re: math for resising images for screen display

Post by RASHAD »

Hi Fang
Taking the Task Bar Size & Position into consideration
With some modification it will be fantastic (Your turn now :D )

# 1:

Code: Select all

UsePNGImageDecoder()
UseJPEGImageDecoder()
UseJPEG2000ImageDecoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()

Procedure Sizeh()
If IsImage(0)
    CopyImage(0,1)
    GetClientRect_(WindowID(0),cr.RECT)
    hScale.f = (cr\right-cr\left)/ImageWidth(1)
    vScale.f = (cr\bottom-cr\top)/ImageHeight(1)
    If hScale > vScale
        Scale.f = vScale*0.9
    Else
        Scale.f = hScale*0.9
    EndIf
    ResizeImage(1,Scale*ImageWidth(1),Scale*ImageHeight(1))                                    
    x = (cr\right-cr\left-ImageWidth(1))/2
    y = (cr\bottom-ImageHeight(1))/2    
    SetGadgetState(0,ImageID(1))
    ResizeGadget(0,x,y,ImageWidth(1),ImageHeight(1))                  
    ResizeGadget(1,10,cr\bottom-30,80,20)
Else
  GetClientRect_(WindowID(0),cr.RECT)
  ResizeGadget(1,10,cr\bottom-30,80,20)  
EndIf
EndProcedure

OpenWindow(0,0,0,800,600,"Window & TaskBar",#PB_Window_SystemMenu| #PB_Window_MaximizeGadget| #PB_Window_ScreenCentered|#PB_Window_SizeGadget) 
ImageGadget(0,0,0,40,40,0)
ButtonGadget(1,10,570,80,20,"Load Image") 

BindEvent(#PB_Event_SizeWindow,@Sizeh())
 
Repeat
   Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
               Quit = 1
               
      Case #PB_Event_Gadget
          Select EventGadget()
           Case 1
              FileName$ = OpenFileRequester("Open image", "", "All supported formats|*.bmp;*.gif;*.jpg;*.jpeg|BMP image (*.bmp)|*.bmp|JPEG image (*.jpg;*.jpeg)|*.jpg;*.jpeg|GIF image (*.gif)|*.gif", 0)
              If FileName$                  
                LoadImage(0,FileName$)
                CopyImage(0,1)
                GetClientRect_(WindowID(0),cr.RECT)
                hScale.f = (cr\right-cr\left)/ImageWidth(1)
                vScale.f = (cr\bottom-cr\top)/ImageHeight(1)
                If hScale > vScale
                    Scale.f = vScale*0.9
                Else
                    Scale.f = hScale*0.9
                EndIf
                ResizeImage(1,Scale*ImageWidth(1),Scale*ImageHeight(1))                                    
                x = (cr\right-cr\left-ImageWidth(1))/2
                y = (cr\bottom-ImageHeight(1))/2                
                SetGadgetState(0,ImageID(1))
                ResizeGadget(0,x,y,ImageWidth(1),ImageHeight(1))                  
                ResizeGadget(1,10,cr\bottom-30,80,20)
              EndIf         
          EndSelect
               
       Case #PB_Event_MaximizeWindow
          If IsImage(0)
            CopyImage(0,1)
            SystemParametersInfo_(#SPI_GETWORKAREA,0,r.RECT,0)
            GetClientRect_(WindowID(0),cr.RECT)
            hScale.f = (r\right-r\left)/ImageWidth(1)
            vScale.f = (r\bottom-r\top)/ImageHeight(1)
            If hScale > vScale
                Scale.f = vScale
            Else
                Scale.f = hScale
            EndIf
            ResizeImage(1,Scale*ImageWidth(1),Scale*ImageHeight(1))                                    
            x = (cr\right-cr\left-ImageWidth(1))/2
            y = (cr\bottom-ImageHeight(1))/2
            SetGadgetState(0,ImageID(1))
            ResizeGadget(0,x,y,ImageWidth(1),ImageHeight(1))                  
            ResizeGadget(1,10,cr\bottom-30,80,20)
          EndIf
   EndSelect

Until Quit = 1
# 2:
No API

Code: Select all

UsePNGImageDecoder()
UseJPEGImageDecoder()
UseJPEG2000ImageDecoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()

Procedure Sizeh()
If IsImage(0)
    CopyImage(0,1)
    hScale.f = WindowWidth(0,#PB_Window_InnerCoordinate)/ImageWidth(1)
    vScale.f = WindowHeight(0,#PB_Window_InnerCoordinate)/ImageHeight(1)
    If hScale > vScale
        Scale.f = vScale*0.9
    Else
        Scale.f = hScale*0.9
    EndIf
    ResizeImage(1,Scale*ImageWidth(1),Scale*ImageHeight(1))                                   
    x = (WindowWidth(0,#PB_Window_InnerCoordinate)-ImageWidth(1))/2
    y = (WindowHeight(0,#PB_Window_InnerCoordinate)-ImageHeight(1))/2
    SetGadgetState(0,ImageID(1))
    ResizeGadget(0,x,y,ImageWidth(1),ImageHeight(1))                 
    ResizeGadget(1,10,WindowHeight(0,#PB_Window_InnerCoordinate)-30,80,20)
Else
    ResizeGadget(1,10,WindowHeight(0,#PB_Window_InnerCoordinate)-30,80,20)
EndIf
EndProcedure

OpenWindow(0,0,0,800,600,"Window & TaskBar",#PB_Window_SystemMenu| #PB_Window_MaximizeGadget| #PB_Window_ScreenCentered|#PB_Window_SizeGadget)
ImageGadget(0,0,0,40,40,0)
ButtonGadget(1,10,570,80,20,"Load Image")

BindEvent(#PB_Event_SizeWindow,@Sizeh())
 
Repeat
   Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
               Quit = 1
               
      Case #PB_Event_Gadget
          Select EventGadget()
           Case 1
              FileName$ = OpenFileRequester("Open image", "", "All supported formats|*.bmp;*.gif;*.jpg;*.jpeg|BMP image (*.bmp)|*.bmp|JPEG image (*.jpg;*.jpeg)|*.jpg;*.jpeg|GIF image (*.gif)|*.gif", 0)
              If FileName$                 
                LoadImage(0,FileName$)
                CopyImage(0,1)
                hScale.f = WindowWidth(0,#PB_Window_InnerCoordinate)/ImageWidth(1)
                vScale.f = WindowHeight(0,#PB_Window_InnerCoordinate)/ImageHeight(1)
                If hScale > vScale
                    Scale.f = vScale*0.9
                Else
                    Scale.f = hScale*0.9
                EndIf
                ResizeImage(1,Scale*ImageWidth(1),Scale*ImageHeight(1))                                   
                x = (WindowWidth(0,#PB_Window_InnerCoordinate)-ImageWidth(1))/2
                y = (WindowHeight(0,#PB_Window_InnerCoordinate)-ImageHeight(1))/2
                SetGadgetState(0,ImageID(1))
                ResizeGadget(0,x,y,ImageWidth(1),ImageHeight(1))               
                ResizeGadget(1,10,WindowHeight(0,#PB_Window_InnerCoordinate)-30,80,20)
              EndIf         
          EndSelect
               
       Case #PB_Event_MaximizeWindow
          If IsImage(0)
            CopyImage(0,1)
            hScale.f = WindowWidth(0,#PB_Window_InnerCoordinate)/ImageWidth(1)
            vScale.f = WindowHeight(0,#PB_Window_InnerCoordinate)/ImageHeight(1)
            If hScale > vScale
                Scale.f = vScale
            Else
                Scale.f = hScale
            EndIf
            ResizeImage(1,Scale*ImageWidth(1),Scale*ImageHeight(1))                                   
            x = (WindowWidth(0,#PB_Window_InnerCoordinate)-ImageWidth(1))/2
            y = (WindowHeight(0,#PB_Window_InnerCoordinate)-ImageHeight(1))/2
            SetGadgetState(0,ImageID(1))
            ResizeGadget(0,x,y,ImageWidth(1),ImageHeight(1))                 
            ResizeGadget(1,10,WindowHeight(0,#PB_Window_InnerCoordinate)-30,80,20)
          EndIf
   EndSelect

Until Quit = 1
Edit :Enhanced and bugs fixed
Egypt my love
fromVB
User
User
Posts: 82
Joined: Sun Jul 29, 2012 2:27 am

Re: math for resising images for screen display

Post by fromVB »

TI-994A wrote:

Code: Select all

UseJPEGImageDecoder()
UsePNGImageDecoder()

Procedure SizeImage()
  CopyImage(1, 0)
  aspectRatio.f = ImageHeight(0) / ImageWidth(0)
  imgWidth = WindowWidth(0)
  imgHeight = imgWidth * aspectRatio
  img_X = 0
  img_Y = (WindowHeight(0) - imgHeight) / 2
  If imgHeight > WindowHeight(0)
    aspectRatio = ImageWidth(0) / ImageHeight(0)
    imgHeight = WindowHeight(0)
    imgWidth = imgHeight * aspectRatio
    img_X = (WindowWidth(0) - imgWidth) / 2
    img_Y = 0  
  EndIf  
  If imgWidth And imgHeight
    ResizeImage(0, imgWidth, imgHeight)
    SetGadgetState(0, ImageID(0))
    ResizeGadget(0, img_X, img_Y, #PB_Ignore, #PB_Ignore)
  EndIf
EndProcedure

imgTypes.s = "Images|*.bmp;*.jpg;*.png | All files (*.*) | *.*"
If LoadImage(1, OpenFileRequester("Select Image:", "", imgTypes, 0))
  
  wFlags = #PB_Window_MaximizeGadget | #PB_Window_Maximize | 
           #PB_Window_ScreenCentered | #PB_Window_SizeGadget
  OpenWindow(0, #PB_Any, #PB_Any, 600, 400, "ImageViewer", wFlags)
  ImageGadget(0, 0, 0, 0, 0, 0)
  
  If ImageWidth(1) > WindowWidth(0) Or ImageHeight(1) > WindowHeight(0)
    SizeImage()
  Else
    wFlags ! #PB_Window_Maximize
    OpenWindow(0, #PB_Any, #PB_Any, ImageWidth(1), ImageHeight(1), "", wFlags)
    ImageGadget(0, 0, 0, 0, 0, ImageID(1))
  EndIf
  
  BindEvent(#PB_Event_SizeWindow, @SizeImage())
  While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend 
EndIf
Perfect! Exactly what I needed - a generic aspect ratio calculator. Thank you TI-994A! :D

One question: why do you open the window and image gadget twice? :?
User avatar
TI-994A
Addict
Addict
Posts: 2741
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: math for resising images for screen display

Post by TI-994A »

fromVB wrote:...why do you open the window and image gadget twice?
Thanks, fromVB. Glad you find it useful.

Rather than fiddling with desktops, the simplest approach would be to obtain the full-screen dimensions from a maximized window. This saves a lot of hassle, especially if there are multiple desktops.

However, if the image dimensions are smaller than a maximized window, the window (same window number) is re-initialised without the maximized flag, while still benefiting from the screen-centred flag. Again, this saves the hassle of fiddling with desktops to centre the window. Accordingly, if the window is re-initialised, the image gadget has to be as well.

It should also be noted that the DesktopWidth() and DesktopHeight() functions do not account for the desktop's taskbar.

Hope it answers your question. :wink:
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: math for resising images for screen display

Post by davido »

@TI-994A,

An excellent, concise, example.
Thank you very much for sharing. :D
DE AA EB
infratec
Always Here
Always Here
Posts: 7623
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: math for resising images for screen display

Post by infratec »

A new try.

It was a nightmare to retrieve the taskbar size.
It works now on Win7 (others not tested)

Code: Select all

#PictureWidth = 1000
#PictureHeigth = 4000

#MyWindow = 0
#MyGadget = 0


Define.f WidthFactor, HeightFactor, Factor

ExamineDesktops()

DesktopWidth = DesktopWidth(0)
DesktopHeight = DesktopHeight(0)

Debug "Desktop: " + Str(DesktopWidth) + " x " + Str(DesktopHeight)

TestWin = OpenWindow(#PB_Any, 0, 0, 0, 0, "", #PB_Window_SystemMenu|#PB_Window_Invisible|#PB_Window_Maximize)
Debug "MaxWinInner: " + Str(WindowWidth(TestWin, #PB_Window_InnerCoordinate)) + " x " + Str(WindowHeight(TestWin, #PB_Window_InnerCoordinate))
Debug "MaxWinOuter: " + Str(WindowWidth(TestWin, #PB_Window_FrameCoordinate)) + " x " + Str(WindowHeight(TestWin, #PB_Window_FrameCoordinate))
Debug "WinLocation: " + Str(WindowX(TestWin)) + " / " + Str(WindowY(TestWin))

TaskBarHeight = WindowHeight(TestWin, #PB_Window_FrameCoordinate) - WindowHeight(TestWin, #PB_Window_InnerCoordinate) - WindowY(TestWin)
CloseWindow(TestWin)

Debug "Taskbarheight: " + Str(TaskBarHeight) + " horror to get this!"




OpenWindow(#MyWindow, 0, 0, 300, 200, "FangBeast Resizer", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
ImageGadget(#MyGadget, 0, 0, 0, 0, 0)


WinFrameWidth.i = (WindowWidth(#MyWindow, #PB_Window_FrameCoordinate) - WindowWidth(#MyWindow, #PB_Window_InnerCoordinate))
WinFrameHeigth.i = (WindowHeight(#MyWindow, #PB_Window_FrameCoordinate) - WindowHeight(#MyWindow, #PB_Window_InnerCoordinate))

Debug "Winframewidth: " + Str(WinFrameWidth)
Debug "Winframeheight: " + Str(WinFrameHeigth)

;..The original height And width of a picture loaded from a database blob


PictureHandle = CreateImage(#PB_Any, #PictureWidth, #PictureHeigth)
PictureWidth = ImageWidth(PictureHandle)
PictureHeight = ImageHeight(PictureHandle)



MaxInnerWidth = DesktopWidth - WinFrameWidth
MaxInnerHeight = DesktopHeight - WinFrameHeigth - TaskBarHeight

Debug "MaxInner: " + Str(MaxInnerWidth) + " x " + Str(MaxInnerHeight)


;..Do desktop related height And width calculations before displaying

WidthFactor = 1.0
HeightFactor = 1.0
Factor = 1.0

If PictureWidth > MaxInnerWidth
  Debug "A"
  WidthFactor = MaxInnerWidth / PictureWidth
EndIf

If PictureHeight > MaxInnerHeight
  Debug "B"
  HeightFactor = MaxInnerHeight / PictureHeight
EndIf

If WidthFactor < HeightFactor
  Factor = WidthFactor
EndIf

If HeightFactor < WidthFactor
  Factor = HeightFactor
EndIf

Debug Factor

;..Some Debug stuff For me

NewWinWidth = PictureWidth * Factor
NewWinHeight = PictureHeight * Factor

Debug "NewWindow (inner size): " + Str(NewWinWidth)  + " x " + Str(NewWinHeight)



;..Now set the resized image To the image gadget

If PictureHandle
  Debug "Located at: " + Str((DesktopWidth - NewWinWidth - WinFrameWidth) / 2) + " / " + Str((DesktopHeight - NewWinHeight - WinFrameHeigth - TaskBarHeight) / 2)
 
  ResizeWindow(#MyWindow, (DesktopWidth - NewWinWidth - WinFrameWidth) / 2, (DesktopHeight - NewWinHeight - WinFrameHeigth - TaskBarHeight) / 2, NewWinWidth, NewWinHeight)
  ResizeImage(PictureHandle.i, NewWinWidth, NewWinHeight, #PB_Image_Smooth)
  SetGadgetState(#MyGadget, ImageID(PictureHandle.i))
EndIf


Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
But still:

If you place a window at 0 not the whole Frame is shown (on Win7) which results in 4 to 6 pixel offset.

Bernd
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4790
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: math for resising images for screen display

Post by Fangbeast »

Hi Bernd. While I doubt I will be able to understand anybody's code, I will do my best to integrate it into the picture database.

And, I found the following titlebar api in the forum and worked it into my code.

Code: Select all

; Windows title bar constants

#CCHILDREN_TITLEBAR = 5

; Title bar structure

Structure TITLEBARINFO
  cbSize.l
  rcTitleBar.RECT
  rgstate.l[#CCHILDREN_TITLEBAR + 1]
EndStructure

; Get the current windows title bar height from a passed window

Procedure.i GetWindowTitleBarDetails(Window.i)
  Protected TitleBarHeight.i
  Protected pti.TITLEBARINFO
  WindowHandle.i = WindowID(Window.i)
  If WindowHandle.i
    pti.TITLEBARINFO\cbSize = SizeOf(TITLEBARINFO)
    GetTitleBarInfo_(WindowHandle.i, pti)
    TitleBarHeight.i = pti\rcTitleBar\bottom  - pti\rcTitleBar\top
  EndIf
  ProcedureReturn TitleBarHeight.i
EndProcedure
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4790
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: math for resising images for screen display

Post by Fangbeast »

Done! Thanks to all people for their valuable input. The below procedure is the fixed module based on Bernd's picture resizing.

Once I have checked the entire program over for any bugs, I will re-upload it to DropBox again.

Code: Select all

;====================================
; Show a bigger version of the stored picture
;============================

Procedure ViewCurrentPicture()
  
  ;------------------------------------------------------------------------------------------------
  ; 
  ;------------------------------------------------------------------------------------------------
  
  Program\CurrentLine = GetGadgetState(#Gadget_PiccyDb_Titles)
  
  ;------------------------------------------------------------------------------------------------
  ; 
  ;------------------------------------------------------------------------------------------------
  
  If Program\CurrentLine  <> #NothingSelected
    
    ;----------------------------------------------------------------------------------------------
    ; 
    ;----------------------------------------------------------------------------------------------
    
    Program\CurrentRecord = GetGadgetItemText(#Gadget_PiccyDb_Titles, Program\CurrentLine,  #RecordColumn)
    
    ;----------------------------------------------------------------------------------------------
    ; 
    ;----------------------------------------------------------------------------------------------
    
    If Program\CurrentRecord  <> #EmptyString
      
      ;--------------------------------------------------------------------------------------------
      ; Check if an existing window is opened
      ;--------------------------------------------------------------------------------------------
      
      If Program\WindowMutex <> #True
        
        ;------------------------------------------------------------------------------------------
        ; Try to open the data form window
        ;------------------------------------------------------------------------------------------
        
        If Window_PiccyViewer()
          
          ;----------------------------------------------------------------------------------------
          ; Window was opened so set mutex to prevent other windows from opening
          ;----------------------------------------------------------------------------------------
          
          Program\WindowMutex = #True
          
          ;----------------------------------------------------------------------------------------
          ; Prevent user input on the main window
          ;----------------------------------------------------------------------------------------
          
          DisableWindow(#Window_PiccyDb, #True)
          
          ;----------------------------------------------------------------------------------------
          ; Setup the common add window message
          ;----------------------------------------------------------------------------------------
          
          Message.s = "View Current Picture"
          
          ;----------------------------------------------------------------------------------------
          ; Set the last window message for the closure routine later
          ;----------------------------------------------------------------------------------------
          
          Program\LastWindow = Message.s
          
          ;----------------------------------------------------------------------------------------
          ; Show new record number and status in the data window
          ;----------------------------------------------------------------------------------------
          
          SetWindowTitle(#Window_PiccyViewer, Message.s)
          
          ;----------------------------------------------------------------------------------------
          ; Add the fast form close keyboard shortcut
          ;----------------------------------------------------------------------------------------
          
          AddKeyboardShortcut(#Window_PiccyViewer, #PB_Shortcut_Escape,               #Shortcut_CloseViewer)
          
          AddKeyboardShortcut(#Window_PiccyViewer, #PB_Shortcut_Alt | #PB_Shortcut_X, #Shortcut_ExitViewer)

          ;----------------------------------------------------------------------------------------
          ;
          ;----------------------------------------------------------------------------------------
          
          QueryString.s = "SELECT m.Title, m.Horizontal, m.Vertical, n.Picture "
          
          QueryString.s + "FROM PictureInfo AS m, PictureData AS n "
          
          QueryString.s + "WHERE n.Record_Id = m.Record_Id "      
          
          QueryString.s + "AND m.Record_Id = '" + Program\CurrentRecord + "'"
          
          ;----------------------------------------------------------------------------------------
          ; 
          ;----------------------------------------------------------------------------------------
          
          If DatabaseQuery(Program\DatabaseHandle, QueryString.s) <> #DatabaseQueryFail
            
            ;--------------------------------------------------------------------------------------
            ; 
            ;--------------------------------------------------------------------------------------
            
            While NextDatabaseRow(Program\DatabaseHandle)
              
              ;------------------------------------------------------------------------------------
              ; 
              ;------------------------------------------------------------------------------------
              
              Picture\Title           = KillQuote(GetDatabaseString(Program\DatabaseHandle,   0))
              
              Picture\Horizontal      =           GetDatabaseString(Program\DatabaseHandle,   1)
              
              Picture\Vertical        =           GetDatabaseString(Program\DatabaseHandle,   2)
              
              ;------------------------------------------------------------------------------------
              ; 
              ;------------------------------------------------------------------------------------
              
              Picture_Length.i        =           DatabaseColumnSize(Program\DatabaseHandle,  3)
              
              ;------------------------------------------------------------------------------------
              ; 
              ;------------------------------------------------------------------------------------
              
              If Picture_Length.i <> #NoDataFound
                
                *PhotoBlobBuffer      =           AllocateMemory(Picture_Length.i)
                
                BlobResult.i          =           GetDatabaseBlob(Program\DatabaseHandle, 3, *PhotoBlobBuffer, Picture_Length.i)
                
              EndIf
              
              ;------------------------------------------------------------------------------------
              ; 
              ;------------------------------------------------------------------------------------
              
            Wend
            
            ;--------------------------------------------------------------------------------------
            ; 
            ;--------------------------------------------------------------------------------------
            
            FinishDatabaseQuery(Program\DatabaseHandle)
            
            ;--------------------------------------------------------------------------------------
            ; 
            ;--------------------------------------------------------------------------------------
            
            SetWindowTitle(#Window_PiccyViewer, GetWindowTitle(#Window_PiccyViewer) + " - Title ("  + Picture\Title + ")")
            
            ;--------------------------------------------------------------------------------------
            ; 
            ;--------------------------------------------------------------------------------------
            
            WindowsFrameWidth.i   = (WindowWidth(#Window_PiccyViewer,   #PB_Window_FrameCoordinate) - WindowWidth(#Window_PiccyViewer,  #PB_Window_InnerCoordinate))
            
            WindowsFrameHeigth.i  = (WindowHeight(#Window_PiccyViewer,  #PB_Window_FrameCoordinate) - WindowHeight(#Window_PiccyViewer, #PB_Window_InnerCoordinate))
            
            TaskBarHeight.i       = GetWindowTitleBarDetails(#Window_PiccyViewer)
            
            ;--------------------------------------------------------------------------------------
            ; 
            ;--------------------------------------------------------------------------------------
            
            PictureWidth.i        = Val(Picture\Horizontal)
            
            PictureHeight.i       = Val(Picture\Vertical)
            
            ;--------------------------------------------------------------------------------------
            ; 
            ;--------------------------------------------------------------------------------------
            
            MaxInnerWidth.i       = Program\DesktopWidth  - WindowsFrameWidth.i
            
            MaxInnerHeight        = Program\DesktopHeight - WindowsFrameHeigth.i - TaskBarHeight.i
            
            ;--------------------------------------------------------------------------------------
            ; 
            ;--------------------------------------------------------------------------------------
            
            WidthFactor.f   = 1.0
            
            HeightFactor.f  = 1.0
            
            Factor.f        = 1.0
            
            ;--------------------------------------------------------------------------------------
            ; 
            ;--------------------------------------------------------------------------------------
            
            If PictureWidth.i > MaxInnerWidth.i
              
              WidthFactor.f   = MaxInnerWidth.i / PictureWidth.i
              
            EndIf
            
            If PictureHeight.i > MaxInnerHeight.i
              
              HeightFactor.f   = MaxInnerHeight.i / PictureHeight.i
              
            EndIf
            
            If WidthFactor.f < HeightFactor.f
              
              Factor.f       = WidthFactor.f
              
            EndIf
            
            If HeightFactor.f < WidthFactor.f
              
              Factor.f        = HeightFactor.f
              
            EndIf
            
            ;--------------------------------------------------------------------------------------
            ;
            ;--------------------------------------------------------------------------------------
            
            NewWindowWidth.i  = PictureWidth.i  * Factor.f
            
            NewWindowHeight.i = PictureHeight.i * Factor.f            
            
            ;--------------------------------------------------------------------------------------
            ;
            ;--------------------------------------------------------------------------------------
            
            If BlobResult.i <> #NoBlobFound
              
              PictureHandle.i = CatchImage(#PB_Any, *PhotoBlobBuffer)
              
              If PictureHandle.i  <> #NoPictureHandle
                
                ResizeWindow(#Window_PiccyViewer, (Program\DesktopWidth - NewWindowWidth.i - WindowsFrameWidth.i) / 2, (Program\DesktopHeight - NewWindowHeight.i - WindowsFrameHeigth.i - TaskBarHeight.i) / 2, NewWindowWidth.i, NewWindowHeight.i)
                
                ResizeImage(PictureHandle.i, NewWindowWidth.i, NewWindowHeight.i, #PB_Image_Smooth)
                
                SetGadgetState(#Gadget_PiccyViewer_picture, ImageID(PictureHandle.i))
                
              EndIf
              
            Else
              
              ResizeImage(#Image_PiccyViewer_picture, #MainPictureWidth, #MainPictureHeight, #PB_Image_Smooth)
              
              SetGadgetState(#Gadget_PiccyViewer_picture,     ImageID(#Image_PiccyViewer_picture))
              
            EndIf
            
            ;--------------------------------------------------------------------------------------
            ;
            ;--------------------------------------------------------------------------------------
            
            SetInfoBarArea("Number",  #EmptyString, Picture\RecordId)
            
            ;--------------------------------------------------------------------------------------
            ; 
            ;--------------------------------------------------------------------------------------
            
          Else
            
            SetInfoBarArea("Headings", "Error", "Database query failed or was empty: " + DatabaseError(), "ViewCurrentPicture")
            
          EndIf
          
          ;----------------------------------------------------------------------------------------
          ; Show new record number and status in the main window
          ;----------------------------------------------------------------------------------------
          
          SetInfoBarArea("Headings", "Info", Message.s  + " to the picture database")
          
          ;----------------------------------------------------------------------------------------
          ; Make sure the data form window is topmost
          ;----------------------------------------------------------------------------------------
          
          SetActiveWindow(#Window_PiccyViewer)
          
          ;----------------------------------------------------------------------------------------
          ; Make sure the version field is selected
          ;----------------------------------------------------------------------------------------
          
          SetActiveGadget(#Gadget_PiccyViewer_Picture)
          
          ;----------------------------------------------------------------------------------------
          ; 
          ;----------------------------------------------------------------------------------------
          
        Else
          
          SetInfoBarArea("Headings", "Error", "The program window could not be opened.", "ViewCurrentPicture")
          
        EndIf
        
        ;------------------------------------------------------------------------------------------
        ; 
        ;------------------------------------------------------------------------------------------
        
      Else
        
        SetInfoBarArea("Headings", "Warn", "Another program window is still open, close that one first.", "ViewCurrentPicture")
        
      EndIf
      
      ;--------------------------------------------------------------------------------------------
      ; 
      ;--------------------------------------------------------------------------------------------
      
    Else
      
      ResizeImage(#Image_PiccyViewer_picture, #MainPictureWidth, #MainPictureHeight, #PB_Image_Smooth)
      
      SetInfoBarArea("Headings", "Error", "No record number found on line: " + Str(Program\CurrentLine), "ViewCurrentPicture")
      
    EndIf
    
    ;----------------------------------------------------------------------------------------------
    ; 
    ;----------------------------------------------------------------------------------------------
    
  Else
    
    SetInfoBarArea("Headings", "Info", "There is no current line selected", "ViewCurrentPicture")
    
  EndIf
  
  ;------------------------------------------------------------------------------------------------
  ; 
  ;------------------------------------------------------------------------------------------------
  
EndProcedure
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
infratec
Always Here
Always Here
Posts: 7623
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: math for resising images for screen display

Post by infratec »

I avoid API were I can to be crossplatform :mrgreen:
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4790
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: math for resising images for screen display

Post by Fangbeast »

infratec wrote:I avoid API were I can to be crossplatform :mrgreen:
That's fair enough but after you said "It was hell", I thought of an easier way:):)

This is my changelog for now. New version uploaded to DropBox, I think I gave the link a few posts ago.

1 I fixed the one bug Jumbuk reported in Piccy
2 Fixed a few other things that I had to do
3 Added a few more right click menus over various objects
4 Added double left click on picture in main screen to view the original size. (Also Alt + V)
5 Bernd (InfraTec) helped me fix up the proportional picture resizer, yay!
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
Post Reply