Skip to content

Smallsan/OctQuant

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Octree Color Quantizer

This project implements an octree-based color quantization algorithm in Go to reduce the number of colors in an image while preserving visual quality. The octree color quantizer helps create a palette of colors from an input image and then maps the colors in the image to this palette, which can be useful for tasks like image compression and color reduction.

Features

  • Color Quantization: Reduces the number of colors in an image using an octree-based quantization algorithm.
  • Palette Generation: Generates a color palette with a specified number of colors.
  • Image Conversion: Converts an input image to use the generated palette.
  • Palette Visualization: Creates and saves an image showing the generated color palette.

Code Overview

Usage

for running the code,

go run main.go                       # Uses defaults: input.png, depth=8, colors=256
go run main.go path/to/image.png     # Process specific image with default settings
go run main.go path/to/image.gif     # Process specific GIF with default settings
go run main.go path/to/image.png 4   # Process image with depth=4, colors=16
go run main.go path/to/image.png 6 50 # Process image with depth=6, colors=50
go run main.go 4 32                  # Process default image with depth=4, colors=32
func forImages() {
    // Load the image
    file, err := os.Open("input.png")
    if err != nil {
        fmt.Println("Error opening image:", err)
        return
    }
    defer file.Close()

    img, err := png.Decode(file)
    if err != nil {
        fmt.Println("Error decoding image:", err)
        return
    }

    // Create an OctreeQuantizer
    quantizer := NewOctreeQuantizer()

    // Add colors from the image to the quantizer
    bounds := img.Bounds()
    for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
        for x := bounds.Min.X; x < bounds.Max.X; x++ {
            r, g, b, a := img.At(x, y).RGBA()
            color := Color{
                Red:   int(r >> 8),
                Green: int(g >> 8),
                Blue:  int(b >> 8),
                Alpha: int(a >> 8),

            }
            quantizer.AddColor(color)
        }
    }

    // Generate the color palette
    colorCount := 256 // Number of colors in the palette
    palette := quantizer.MakePalette(colorCount)

    // Create a new image with the quantized colors
    quantizedImg := image.NewRGBA(bounds)
    for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
        for x := bounds.Min.X; x < bounds.Max.X; x++ {
            r, g, b, a := img.At(x, y).RGBA()
            color_palette := Color{
                Red:   int(r >> 8),
                Green: int(g >> 8),
                Blue:  int(b >> 8),
                Alpha: int(a >> 8),
            }
            paletteIndex := quantizer.GetPaletteIndex(color_palette)
            quantizedColor := palette[paletteIndex]
            quantizedImg.Set(x, y, color.RGBA{
                R: uint8(quantizedColor.Red),
                G: uint8(quantizedColor.Green),
                B: uint8(quantizedColor.Blue),
                A: uint8(quantizedColor.Alpha),
            })
        }
    }

    // Save the quantized image
    outputFile, err := os.Create("output.png")
    if err != nil {
        fmt.Println("Error creating output image:", err)
        return
    }
    defer outputFile.Close()

    err = png.Encode(outputFile, quantizedImg)
    if err != nil {
        fmt.Println("Error encoding output image:", err)
        return
    }

    fmt.Println("Quantized image saved as output.png")

// Create a palette image with larger pixels
pixelSize := 10
paletteImg := image.NewRGBA(image.Rect(0, 0, 8*pixelSize, ((colorCount+7)/8)*pixelSize))
for i, c := range palette {
    x := (i % 8) * pixelSize
    y := (i / 8) * pixelSize
    for dx := 0; dx < pixelSize; dx++ {
        for dy := 0; dy < pixelSize; dy++ {
            paletteImg.Set(x+dx, y+dy, color.RGBA{
                R: uint8(c.Red),
                G: uint8(c.Green),
                B: uint8(c.Blue),
                A: uint8(c.Alpha),
            })
        }
    }
}
    // Save the palette image
    paletteFile, err := os.Create("palette.png")
    if err != nil {
        fmt.Println("Error creating palette image:", err)
        return
    }
    defer paletteFile.Close()

    err = png.Encode(paletteFile, paletteImg)
    if err != nil {
        fmt.Println("Error encoding palette image:", err)
        return
    }

    fmt.Println("Palette image saved as palette.png")
}

Key Components

  • Color: Represents a color with Red, Green, and Blue components.
  • OctreeNode: Represents a node in the octree. Each node can have up to 8 children.
  • OctreeQuantizer: Manages the octree and provides methods to add colors, generate palettes, and get color indices.

Functions

  • NewColor(red, green, blue int) Color: Creates a new Color instance.
  • NewOctreeNode(level int, parent *OctreeQuantizer) *OctreeNode: Creates a new OctreeNode.
  • AddColor(color Color): Adds a color to the quantizer.
  • MakePalette(colorCount int) []Color: Generates a color palette with the specified number of colors.
  • GetPaletteIndex(color Color) int: Gets the index of the color in the palette.

Example

Original Image

The original image is located at examples/alice. It is 2.27MB in size.

Original Image

Quantized Image

The quantized image is located at examples/quantized_alice. It is 0.51MB in size and contains 64 colors.

Quantized Image

Quantized Palette

The palette used for the quantized image is located at examples/quantized_palette.

Quantized Palette

Contributing

Feel free to submit issues, pull requests, and suggestions to improve the project.

About

Oct tree color quantization algorithm.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages