Splitting a huge image on a grid of Picture entities

Sometimes you may have the need to create a Picture entity from an image that is too big for your graphics card memory.

The Picture entity automatically resizes the image to fit into the graphics card memory but this process causes a loss of precision and your image may become blurry.

This method shows how to split a huge image in smaller Picture entity tiles (of size 256x256) that will fit in your graphics card memory, while preserving the image precision:

private void SplitImageInTiles(Design design1, Image image) 
{ 
    // Split the image in tiles of size 256x256 
    int tileWidth = 256; 
    int tileHeight = 256; 

    Point3D basePoint = Point3D.Origin; 
    Rectangle imageRect = new Rectangle(0, 0, image.Width, image.Height); 

    int pictureWidth = 10; 
    int pictureHeight = 10; 

    int posX = 0; 

    for (int x = posX; x < image.Size.Width; x += tileWidth - 1) // increment by the tile width minus the border pixel 
    { 
        int posY = 0; 

        for (int y = posY; y < image.Size.Height; y += tileHeight - 1) // increment by the tile height minus the border pixel 
        { 
            // Split the image in tiles of 256x256 size 
            Bitmap tile = new Bitmap(tileWidth, tileHeight, PixelFormat.Format32bppArgb); 
            Graphics g = Graphics.FromImage(tile); 

            Rectangle rect = Rectangle.Intersect(imageRect, new Rectangle(x, y, tile.Width, tile.Height)); 

            // Set a transparent background color, so the area of the tile outside the image becomes transparent 
            g.Clear(Color.Transparent); 

            // Draw the sub-image in the tile 
            g.DrawImage(image, new Rectangle(new System.Drawing.Point(0, 0), rect.Size), rect, GraphicsUnit.Pixel); 

            // Create a Picture entity from the tile 
            Picture picture = new Picture( 
                new Plane(new Point3D(0, 0, -1), new Vector3D(0, 0, 1)),  
                pictureWidth,  
                pictureHeight,  
                tile.ToByteArray()) 
            { 
                Selectable = false, 
                Lighted = false, 
                DrawEdge = false, 
                Tiling = true // Set tiling to true so that border pixels are correctly interpolated 
            }; 

            picture.Translate((basePoint + new Point3D(posX, Height - posY, 0)).AsVector);
            design1.Entities.Add(picture); 
                         
            posY += pictureHeight; 
     
            g.Dispose(); 
        } 

        posX += pictureWidth; 
    } 
}

 

The following picture shows how the image is splitted in a 3x3 grid of smaller pictures (the red dots are the corners of the Picture entities).

Since the image size was of 512x512 and the tile size is 254, we need 3 tiles in each dimension to accomodate the whole picture (the third tile has only 4 units of the picture).

tiles.PNG

Was this article helpful?
4 out of 4 found this helpful

Comments

0 comments

Please sign in to leave a comment.

Articles in this section