What's New
Q & A
Tip Jar
C# Helper...
Follow VBHelper on Twitter
MSDN Visual Basic Community
TitlePixellate an image
Keywordspixellate, image, DIB, GetDIBits, SetDIBits
Pixellation replaces an image with large pseudo-pixels that each represent the average color of the area they represent.

This program loops over the image in pseudo-pixel blocks of a specified size. For each block, it takes the average of the colors in the block and sets all pixels in the block to that average color.

If you examine the code carefully, you'll see how the program uses Do loops to ensure that every pixel is considered even if it is near the edge of the image. For example, suppose the image has 20x16 pixels and the block size is 8. The image will contain 4 blocks plus two 4x8 partial blocks on the right. The xmax and ymax values allow the program to average over these partial blocks.

Note that averaging over the partial blocks makes them less "averaged" than the other blocks (their data is less disguised). An alternative might be to cut any partial blocks out of the image completely.

Private Sub cmdGo_Click()
Dim block_size As Integer
Dim bitmap_info As BITMAPINFO
Dim pixels() As Byte
Dim bytes_per_scanLine As Integer
Dim pad_per_scanLine As Integer
Dim X As Integer
Dim Y As Integer
Dim i As Integer
Dim j As Integer
Dim total_r As Long
Dim total_g As Long
Dim total_b As Long
Dim xmax As Integer
Dim ymax As Integer
Dim num_pixels As Integer

    block_size = CInt(txtBlockSize.Text)

    ' Prepare the bitmap description.
    With bitmap_info.bmiHeader
        .biSize = 40
        .biWidth = picFrom.ScaleWidth
        ' Use negative height to scan top-down.
        .biHeight = -picFrom.ScaleHeight
        .biPlanes = 1
        .biBitCount = 32
        .biCompression = BI_RGB
        bytes_per_scanLine = ((((.biWidth * .biBitCount) + _
            31) \ 32) * 4)
        pad_per_scanLine = bytes_per_scanLine - (((.biWidth _
            * .biBitCount) + 7) \ 8)
        .biSizeImage = bytes_per_scanLine * Abs(.biHeight)
    End With

    ' Load the bitmap's data.
    ReDim pixels(1 To 4, 1 To picFrom.ScaleWidth, 1 To _
    GetDIBits picFrom.hdc, picFrom.Image, _
        0, picFrom.ScaleHeight, pixels(1, 1, 1), _
        bitmap_info, DIB_RGB_COLORS

    ' Modify the pixels.
    Y = 1
    Do While Y < picFrom.ScaleHeight
        ymax = Y + block_size
        If ymax >= picFrom.ScaleHeight _
            Then ymax = picFrom.ScaleHeight

        X = 1
        Do While X < picFrom.ScaleWidth
            xmax = X + block_size
            If xmax >= picFrom.ScaleWidth _
                Then xmax = picFrom.ScaleWidth

            ' Get the total color for this block.
            total_r = 0
            total_g = 0
            total_b = 0
            For i = X To xmax
                For j = Y To ymax
                    total_r = total_r + pixels(pixR, i, j)
                    total_g = total_g + pixels(pixG, i, j)
                    total_b = total_b + pixels(pixB, i, j)
                Next j
            Next i

            ' Set the color of this block.
            ' Set the blue component to 255.
            num_pixels = (xmax - X + 1) * (ymax - Y + 1)
            total_r = total_r / num_pixels
            total_g = total_g / num_pixels
            total_b = total_b / num_pixels
            For i = X To xmax
                For j = Y To ymax
                    pixels(pixR, i, j) = total_r
                    pixels(pixG, i, j) = total_g
                    pixels(pixB, i, j) = total_b
                Next j
            Next i
            X = X + block_size
        Y = Y + block_size

    ' Display the result.
    SetDIBits picTo.hdc, picTo.Image, _
        0, picFrom.ScaleHeight, pixels(1, 1, 1), _
        bitmap_info, DIB_RGB_COLORS
    picTo.Picture = picTo.Image
End Sub
Copyright © 1997-2010 Rocky Mountain Computer Consulting, Inc.   All rights reserved.