Archive for October, 2023
Go: Comic Filter Effect
by admin on Oct.06, 2023, under News
A comic filter is a digital graphical effect applied to photos or videos to make them resemble hand-drawn comic book illustrations. This transformation often involves several steps to achieve a stylized, artistic appearance typical of comic art.
Initially, the filter simplifies the image’s colors, reducing them to a limited palette that mirrors the flat shading seen in many comic books. This process, called color quantization, removes subtle gradients and shadows, turning them into block colors.
Next, the filter accentuates edges and outlines in the image, making them bold and dark, resembling the inked lines in comic book art. This is usually achieved through edge detection algorithms that highlight abrupt changes in color or brightness. The result is thick, dark lines surrounding objects, facial features, and other details, adding depth and making them stand out, much like the work of a comic book inker.
Additionally, some comic filters might introduce halftone patterns, those tiny dots seen in older comic prints, to give a vintage feel. Others might add paper textures, exaggerated shadows, or even speech bubbles for added effect.
Overall, a comic filter transforms ordinary photos, giving them a whimsical, hand-drawn appearance reminiscent of classic comic book pages.
package main import ( "fmt" "image/color" "github.com/disintegration/imaging" ) // Convert hex string to NRGBA color func hexToNRGBA(hex string) color.NRGBA { var c uint32 fmt.Sscanf(hex, "#%06x", &c) return color.NRGBA{ R: uint8(c >> 16), G: uint8(c >> 8), B: uint8(c), A: 255, } } // Function to quantize the pixel to the nearest color in the palette. func quantizeToNearest(c color.NRGBA, palette []color.NRGBA) color.NRGBA { var minDist float64 = 1e9 var bestMatch color.NRGBA for _, col := range palette { dist := colorDistance(c, col) if dist < minDist { minDist = dist bestMatch = col } } return bestMatch } func colorDistance(c1, c2 color.NRGBA) float64 { rDiff := float64(c1.R) - float64(c2.R) gDiff := float64(c1.G) - float64(c2.G) bDiff := float64(c1.B) - float64(c2.B) return rDiff*rDiff + gDiff*gDiff + bDiff*bDiff } func main() { inputPath := "image.jpg" outputPath := "image_comic.jpg" // Open the image from file src, err := imaging.Open(inputPath) if err != nil { panic(err) } // Define the color palette palette := []color.NRGBA{ // generic hexToNRGBA("#c5131e"), hexToNRGBA("#c7242e"), hexToNRGBA("#f08327"), hexToNRGBA("#538adc"), hexToNRGBA("#2859b6"), // skin hexToNRGBA("#F7E6E3"), hexToNRGBA("#EAB486"), hexToNRGBA("#E59F6C"), hexToNRGBA("#DE804E"), hexToNRGBA("#DC7542"), hexToNRGBA("#8E2E21"), hexToNRGBA("#5C1A19"), // black/white hexToNRGBA("#000000"), hexToNRGBA("#FFFFFF"), } // Quantize image quantized := imaging.AdjustFunc(src, func(c color.NRGBA) color.NRGBA { return quantizeToNearest(c, palette) }) // Save the result err = imaging.Save(quantized, outputPath) if err != nil { panic(err) } }