JordyRitzen
JordyRitzen

Reputation: 702

Determine best size for images in an given space

What I want: image = a square bitmap with Width = Height all images are EXACTLY the same size

I've got a program which draws images on a container. In this case the images are generated bitmaps. The dimensions of the container are generic (the same size as the clientsize of the form).

I want the images laid out in rows and columns. But the drawing part should calculate how many rows and how many columns fit the best for the given amount of images and resize the images to make them fit.

What I've got: code for resizing the object where the images are in

    public void ResizeScreen(Size newSize)
    {
        this.size = newSize;
        InitializeObjectSize();
    }

code for resizing the images

public void InitializeObjectSize()
        {
            int objectSize;
            int spacing = 10;
            if ((this.size.Height - 2 * spacing) <= (this.size.Width - ((objects.Count + 1) * spacing)) / objects.Count)
            {
                objectSize = this.size.Height - (2 * spacing);

            }
            else
            {
                objectSize = (this.size.Width - ((objects.Count + 1) * spacing)) / objects.Count;
            }
        foreach (Object object in objects)
        {
            object.Size = objectSize;
        }
    }

Code for drawing the images/ This one centers the images horizontally and vertically and draws them.

public void DrawObjects()
    {

        if (objects[0].Image != null)
        {
            drawImage = new Bitmap(size.Width, size.Height);
            System.Drawing.Graphics tempGraphics = Graphics.FromImage(drawImage);
            int spacing = 10;
            int totalwidth = this.size.Width; //- ((objects.Count * spacing) + spacing);
            int totalUsedWidth = objects.Count * objects[0].Size + ((objects.Count * spacing) + spacing);
            int realign = (totalwidth - totalUsedWidth) / 2;
            for (int i = 0; i < objects.Count; i++)
            {

                int startxposition = (objects[i].Size * i + 10 * i + 10) + realign;
                int startyposition = (size.Height - objects[i].Size) / 2;
                tempGraphics.DrawImage(objects[i].ObjectImage, startxposition, startyposition);
            }
            tempGraphics.Dispose();
        }
    }

Upvotes: 0

Views: 168

Answers (2)

JordyRitzen
JordyRitzen

Reputation: 702

This is how I solved it. It's a brute force method.(it will try all combinations and pick the best

        public void SetObjectSize()
        {
            int objectSize = 0;
            for (int objectsPerRow = 1; objectsPerRow <= objects.Count ; objectsPerRow++)
            {
                int rows =(int)Math.Ceiling(((double)objects.Count) / objectsPerRow);
                int horizontalSize = (this.size.Height - (rows * spacing + spacing)) / rows;
                int verticalSize = (this.size.Width - (objectsPerRow * spacing + spacing)) / objectsPerRow;
                int newSize = horizontalSize < verticalSize ? horizontalSize : verticalSize ;
                if (newSize > objectSize)
                {
                    this.rows = rows;
                    this.objectsPerRow = objectsPerRow ;
                    objectSize = newSize;
                }
            }
         }

Upvotes: 0

James
James

Reputation: 9985

First you need the aspect ratio

Double aspectRatio = height/width;

Using the aspect ratio you need a calculation which will turn a number of columns into a number of squares.

Double squares = columns * columns * aspectRatio;

You need the smallest number of squares which is greater than the number of squares you have, so invert the formula.

    Double columns = Math.Ceiling(Math.Sqrt(squares / aspectRatio));
    Double rows = Math.Ceiling(columns * aspectRatio);
    Double actualSquares = rows * columns;
    Double squareWidth = width / columns;
    Double squareHeight = height / rows;

Note that due to the Math.Ceiling your squares won't quite be square. You'll need to take the smaller number and calculate the remaining to form a margin, you can then pad each square or form a border

Upvotes: 1

Related Questions