Tricky Math: Auto-Scale Thumbnails to Fit in Grid

Blitz3D Forums/Blitz3D Programming/Tricky Math: Auto-Scale Thumbnails to Fit in Grid

Roland(Posted 2007) [#1]
Hi,
This one has me stumped, and I hope that my fellow b3ders can help me figure it out.

for an image gallery, I want to be able to load an arbitrary number of thumbnails up and have them fit nicely into a predefined space (the screen). Based on the number of the thumbnails to be loaded, they should scale so that they all organize nicely and fit into the screen at once. So if you load 100, they will organize into as many rows / columns as necessary and scale down to fit -- if you load only 10, they will change their arrangement as necessary.

I know that this isn't very 3d, but the math is something I was hoping some of the geniuses here could help me out with... I think it's pretty tricky!

Here are some other assumptions we can make:

1. The screensize should be constant

2. the thumbnail proportions should be constant and the same for all thumbnails (so that they scale up / down proportionally and look similar).

any ideas? for now, i'm not even loading images, just working with boxes that I generate myself... but I can't even really get started I'm so stumped.

thanks,
roland


_33(Posted 2007) [#2]
Well, as easy as can be, all you have to do is get familiar with the userlib FastImage, and it will do all this for you, and in an interestingly fast manner! I highly suggest you take the necessary time and study that userlib, it will save you tons of time/sweat/headaches in exchange. Good luck!


Stevie G(Posted 2007) [#3]
Simply use resizeimage on all loaded images to create correct thumbnails then something like this to position them ...

GW = Graphicswidth()
GH = Graphicsheight()
TW = Thumbnail width
TH = Thumbnail height
SW = Width of space between thumbnails
SH = Height of space between thumbnails

;Max Images on width of screen
MAX = floor( GW / ( TW + SW ) )

for l = 0 to NumberofImages - 1

  X =  ( l mod MAX ) * ( TW + SW )
  Y = floor( l / MAX ) * ( TH + SH )
  drawimage image(l) , X, Y

Next



Roland(Posted 2007) [#4]
Hey Stevie -- thanks for the reply... I'll see if I can use this, but I don't think it will do quite what i'm looking for...

I want the size of the thumbnails to change dynamically in order to make them fit as best as possible... so if you have only a few images, they will be bigger, and conversely if you have many they will be small so that they can all fit on screen...

So how do i determine the size of the thumbs? Especially tricky because they should scale proportionally.

Thanks for your help on this one -- I'm sorry if I'm not explaining it very well. It would be so much easier if I could find an example somewhere of where it's been done!


big10p(Posted 2007) [#5]
Hmm. You could probably do this by evaluating the width/height of each image as you load them, in order to calculate the aspect ratio of the 'frame' every image can fit into, so as to keep their proportions. Then, try a brute force method of scaling the frame up until the largest size that fits all images on the screen is found.

Not very elegant, I guess. There's proabably a better way. My programming brain has been on holiday for so long, I'm a bit rusty, TBH. :)


Jasu(Posted 2007) [#6]
I think the algorithm would go as follows:
-Create a array having the sizes of all pictures (X,Y)
-Create a grid with only one row (ie with 26 pictures a 26x1 grid)
-Go through the pictures and search for the picture that needs most downscaling in order to fit in the grid box size. Create a scaling factor (float variable) from that.
-Store the scaling factor and grid properties in an array.
-Add one row to the grid (reduce columns when possible).
-Go back to phase 3.

After this loop has reached the situation where 26 picture collection has created a 1x26 grid, go through the scaling factor array and choose the one with the highest scaling factor.

I think by this way you should be able to find the optimum grid for your pictures. This is just an idea. Hope it gives you some thoughts.

EDIT: A way to refine this could be reducing one column and adding a row when needed. This would make the algorithm a bit more heavier but more precise. I still think that this would be fast enough if you don't actually resize the pictures when scaling, instead do it mathematically.


Roland(Posted 2007) [#7]
Hey Jasu,

I think that you're going along the same lines that I was thinking... unfortunately I have so far been unable to code it correctly. One simplification is that all of the pictures are the same size, step 3 can be removed and you can use sort of a global size for all the thumbs.

Any chance of some example code to make this happen? I am completely turned around on it and my head is spinning.

cheers!
roland


Jasu(Posted 2007) [#8]
Constant picture size makes this a bit more mathematical.

Global PicWidth ; you need some code to get this
Global PicHeight ; this too
Global PicAmount ; also this

Factor# = (PicWidth / GraphicsWidth()) / (PicHeight / GraphicsHeight())

OptW% = 1
Test# = PicAmount
For A%=1 To PicAmount
  If ABS(Ceil(PicAmount/A)/A - Factor) < Test Then OptW = A
  Test = ABS(Ceil(PicAmount/A)/A - Factor)
Next

GridColumns% = OptW
GridRows% = Ceil(PicAmount/OptW)


I'm not sure if that loop works, but basics of this is that you need to find the grid option where Rows/Columns is as near as possible to Factor#. That grid option will waste the least space.


Roland(Posted 2007) [#9]
Wow, this is awesome, Jasu. I have no idea how you came up with the math to make this work. It's almost perfect as is... the only thing that I can't quite figure out now, is how to constrain the size of the thumbnails to their proportion.

So if my picwidth is 50 and my picheight is 75, I want to maintain that proportion as they scale up and down... This of course, increases the complexity quite a bit.

Any ideas on how I would adjust the equation to make that happen?

thanks again -- you have already been a huge help!

roland


Jasu(Posted 2007) [#10]
Now that I got home and had a change to actually run this...
I added a few Float() commands and put some demo stuff there.

Just play around with different amounts of pictures. I'm not sure if this algorithm always finds the most optimum grid, but most of the time it works.

Graphics 800,600,16,2

PicWidth% = 50 ; you need some code to get this
PicHeight% = 75  ; this too
PicAmount% = 34 ; also this

Factor# = (Float(PicWidth) / GraphicsWidth()) / (Float(PicHeight) / GraphicsHeight())

OptW% = 1
Test# = PicAmount
For A%=1 To PicAmount
  If Abs(Ceil(PicAmount/A)/A - Factor) < Test Then OptW = A
  Test = Abs(Ceil(PicAmount/A)/A - Factor)
Next

GridColumns% = OptW
GridRows% = Ceil(Float(PicAmount)/OptW)




GridWidth# = Float(GraphicsWidth()) / GridColumns
GridHeight# = Float(GraphicsHeight()) / GridRows


If GridWidth/PicWidth < GridHeight/PicHeight Then
  Scale# = GridWidth/PicWidth
Else
  Scale# = GridHeight/PicHeight
EndIf


For Y=1 To GridRows
  For X=1 To GridColumns
    If (Y-1)*GridColumns+X<=PicAmount Then		
      Color 100,100,100
      Rect (X-1)*GridWidth+(GridWidth-Float(PicWidth) * Scale)/2,(Y-1)*GridHeight+(GridHeight-Float(PicHeight) * Scale)/2,Float(PicWidth) * Scale,Float(PicHeight) * Scale,1
      Color 200,200,200
      Text (X-1+0.5)*GridWidth,(Y-1+0.5)*GridHeight,(Y-1)*GridColumns+X
    EndIf
    Rect (X-1)*GridWidth,(Y-1)*GridHeight,GridWidth,GridHeight,0
  Next
Next

Color 255,255,255
Print "Grid is " + GridColumns + "x" + GridRows
Print "Grid box is " + Gridwidth + "x" + GridHeight + " pixels.
Print "Scale is " + scale
Print "And with that, picture scales to " + Float(PicWidth) * Scale + "x" + Float(PicHeight) * Scale


Just simply scale your pictures with ScaleImage image,scale,scale and place them with a loop similar with the one on the example and bobs your uncle.


Roland(Posted 2007) [#11]
Hey Jasu, you are the best-- this works perfectly! I was actually able to get the proportions working ok a slightly different way after I posted, but this is way more elegant.

I can't thank you enough for puzzling through this one with me -- your math /logic skills are amazing...

thanks again for your help!!! This should end up being a really flexible tool for me with the interface I'm working on!

best,
roland


Jasu(Posted 2007) [#12]
Thanks for the words, Roland. Glad to be of help.