go-catprinter/image.go
2024-09-10 22:45:30 +02:00

105 lines
2.3 KiB
Go

package catprinter
import (
"github.com/disintegration/imaging"
"github.com/makeworld-the-better-one/dither/v2"
"image"
"image/color"
"image/draw"
"log"
)
const printWidth = 384
func convertImageToBytes(img image.Image) ([]byte, error) {
if img.Bounds().Dx() != printWidth {
return nil, ErrInvalidImageSize
}
var byteArray []byte
for y := 0; y < img.Bounds().Dy(); y++ {
for x := 0; x < img.Bounds().Dx(); x++ {
r, g, b, _ := img.At(x, y).RGBA()
if r != g || g != b || r != b || (r != 0 && r != 65535) {
return nil, ErrNotBlackWhite
}
if r == 0 {
byteArray = append(byteArray, 1) // black
} else {
byteArray = append(byteArray, 0) // white
}
}
}
return byteArray, nil
}
func grayscaleToBlackWhite(img image.Image, blackPoint float32) *image.NRGBA {
bounds := img.Bounds()
nrgbaImg := image.NewNRGBA(bounds)
draw.Draw(nrgbaImg, bounds, img, bounds.Min, draw.Src)
for y := 0; y < img.Bounds().Dy(); y++ {
for x := 0; x < img.Bounds().Dx(); x++ {
r, g, b, _ := img.At(x, y).RGBA()
if r != g || g != b || r != b {
log.Panicln("logic error, image should have been grayscale")
}
if float32(r)/65535 < blackPoint {
nrgbaImg.Set(x, y, color.Black)
} else {
nrgbaImg.Set(x, y, color.White)
}
}
}
return nrgbaImg
}
func ditherImage(img image.Image, algo dither.ErrorDiffusionMatrix) image.Image {
palette := []color.Color{
color.Black,
color.White,
}
d := dither.NewDitherer(palette)
d.Matrix = algo
return d.Dither(img)
}
// FormatImage formats the image for printing by resizing it and dithering or grayscaling it
func (c *Client) FormatImage(img image.Image, opts *PrinterOptions) image.Image {
if img.Bounds().Dx() > img.Bounds().Dy() && opts.autoRotate {
img = imaging.Rotate90(img)
}
var newImg image.Image = imaging.New(img.Bounds().Dx(), img.Bounds().Dy(), color.White)
newImg = imaging.OverlayCenter(newImg, img, 1)
newImg = imaging.Resize(newImg, printWidth, 0, imaging.NearestNeighbor)
if opts.dither {
newImg = ditherImage(newImg, opts.ditherAlgo)
} else {
newImg = imaging.Grayscale(newImg)
newImg = grayscaleToBlackWhite(newImg, opts.blackPoint)
}
if c.Debug.DumpImage {
err := imaging.Save(newImg, "./image.png")
if err != nil {
log.Println("failed to save debugging image dump", err.Error())
}
}
return newImg
}