Search code examples
vb.netwinformsgraphicspicturebox

Split an Image into different PictureBoxes


I have a Image with size 187x16 which contain 10 smaller Images in a row.

I want split those Images into 10 different PictureBoxes.
Original Image:

example image

Dim fr_bm As New Bitmap(Image.FromFile(AppDomain.CurrentDomain.BaseDirectory & "/images/u/image.gif"))
Dim to_bm As New Bitmap(16, 16)
Dim unitsimagearray(9) As Image
Dim gr As Graphics = Graphics.FromImage(to_bm)
For i As Integer = 0 To 9
    Dim fr_rect As New Rectangle(i * 19, 0, 16, 16) '0,19,38,76
    Dim to_rect As New Rectangle(0, 0, 16, 16)
    gr.DrawImage(fr_bm, to_rect, fr_rect, GraphicsUnit.Pixel)
    unitsimagearray(i) = to_bm
Next
u1.Image = unitsimagearray(0)

But the PictureBox shows all the splitted images.


Solution

  • The main problem with your current code is that the destination image (the image containing a slice of the original), is created once but painted many times.
    Since the original image has transparent pixels, the result of the painting will be accumulated.
    You can see the transparent sections overlapping.

    It can be easily corrected, creating a new Bitmap for each slice of the original. You could also re-paint the same image with a transparent color, but this is faster.

    In code, I'm assembling all the PictureBox controls that will receive the slices in one array, so you can assign the Image in the same loop that creates the Bitmaps.
    You called the first PictureBox u1, so I'm following the same naming convention.

    You will dispose of the Bitmap contained in the unitsimagearray when you don't need them anymore or the application closes.


    Original Bitmap (.GIF):

    Bitmap Grid

    Sliced images (2x). Anti-aliasing and transparency are preserved:

    Sliced Image

    Private unitsimagearray(9) As Bitmap
    
    Dim imagePath As String = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "images/u/image.gif")
    Dim picBoxes() As PictureBox = {u1, u2, u3, u4, u5, u6, u7, u8, u9, u10}
    
    Using sourceBitmap As Bitmap = Image.FromStream(New MemoryStream(File.ReadAllBytes(imagePath)))
        For idx As Integer = 0 To picBoxes.Length - 1
            Dim slice As Bitmap = New Bitmap(16, 16, PixelFormat.Format32bppArgb)
            Using g As Graphics = Graphics.FromImage(slice)
                Dim sourceRect As New Rectangle(idx * 19, 0, 16, 16)
                Dim destinationRect As New Rectangle(0, 0, 16, 16)
                g.DrawImage(sourceBitmap, destinationRect, sourceRect, GraphicsUnit.Pixel)
                unitsimagearray(idx) = slice
                picBoxes(idx).Image = unitsimagearray(idx)
            End Using
        Next
    End Using