move to internal

This commit is contained in:
Celogeek 2022-12-25 19:26:02 +01:00
parent 892c0ca320
commit 7a9796000e
Signed by: celogeek
GPG Key ID: E6B7BDCFC446233A
2 changed files with 175 additions and 103 deletions

View File

@ -0,0 +1,165 @@
package comicconverter
import (
"fmt"
"image"
"image/color"
"image/jpeg"
"os"
"golang.org/x/image/draw"
)
type ComicConverter struct {
Options ComicConverterOptions
img image.Image
grayImg *image.Gray16
}
type ComicConverterOptions struct {
Quality int
}
func New(opt ComicConverterOptions) *ComicConverter {
return &ComicConverter{Options: opt}
}
func (c *ComicConverter) Load(file string) *ComicConverter {
f, err := os.Open(file)
if err != nil {
panic(err)
}
defer f.Close()
img, _, err := image.Decode(f)
if err != nil {
panic(err)
}
c.img = img
return c
}
func (c *ComicConverter) GrayScale() *ComicConverter {
if c.img == nil {
panic("load image first")
}
c.grayImg = image.NewGray16(c.img.Bounds())
draw.Draw(c.grayImg, c.grayImg.Bounds(), c.img, image.Point{}, draw.Src)
return c
}
func (c *ComicConverter) CropMarging() *ComicConverter {
if c.grayImg == nil {
panic("grayscale first")
}
imgArea := c.grayImg.Bounds()
colorLimit := color.Gray16{60000}
LEFT:
for x := imgArea.Min.X; x < imgArea.Max.X; x++ {
for y := imgArea.Min.Y; y < imgArea.Max.Y; y++ {
if c.grayImg.Gray16At(x, y).Y < colorLimit.Y {
break LEFT
}
}
imgArea.Min.X++
}
UP:
for y := imgArea.Min.Y; y < imgArea.Max.Y; y++ {
for x := imgArea.Min.X; x < imgArea.Max.X; x++ {
if c.grayImg.Gray16At(x, y).Y < colorLimit.Y {
break UP
}
}
imgArea.Min.Y++
}
RIGHT:
for x := imgArea.Max.X - 1; x >= imgArea.Min.X; x-- {
for y := imgArea.Min.Y; y < imgArea.Max.Y; y++ {
if c.grayImg.Gray16At(x, y).Y < colorLimit.Y {
break RIGHT
}
}
imgArea.Max.X--
}
BOTTOM:
for y := imgArea.Max.Y - 1; y >= imgArea.Min.Y; y-- {
for x := imgArea.Min.X; x < imgArea.Max.X; x++ {
if c.grayImg.Gray16At(x, y).Y < colorLimit.Y {
break BOTTOM
}
}
imgArea.Max.Y--
}
fmt.Println("CROP", imgArea)
c.grayImg = c.grayImg.SubImage(imgArea).(*image.Gray16)
return c
}
func (c *ComicConverter) Resize(w, h int) *ComicConverter {
if c.grayImg == nil {
panic("grayscale first")
}
dim := c.grayImg.Bounds()
origWidth := dim.Dx()
origHeight := dim.Dy()
width, heigth := origWidth*h/origHeight, origHeight*w/origWidth
fmt.Println("W:", origWidth, width, h)
fmt.Println("H:", origHeight, heigth, w)
if width > origWidth {
width = origWidth
} else if heigth > origHeight {
heigth = origHeight
}
imgGray := image.NewGray16(image.Rectangle{
Min: image.Point{0, 0},
Max: image.Point{width, heigth},
})
fmt.Println("RESIZE", imgGray.Bounds())
draw.BiLinear.Scale(imgGray, imgGray.Bounds(), c.grayImg, c.grayImg.Bounds(), draw.Src, nil)
c.grayImg = imgGray
return c
}
func (c *ComicConverter) Save(output string) *ComicConverter {
if c.grayImg == nil {
panic("grayscale first")
}
o, err := os.Create(output)
if err != nil {
panic(err)
}
defer o.Close()
quality := 75
if c.Options.Quality > 0 {
quality = c.Options.Quality
}
err = jpeg.Encode(o, c.grayImg, &jpeg.Options{Quality: quality})
if err != nil {
panic(err)
}
return c
}

113
main.go
View File

@ -1,111 +1,18 @@
package main package main
import ( import (
"fmt" comicconverter "go-comic-converter/internal/comic-converter"
"image"
"image/jpeg"
"os"
"golang.org/x/image/draw"
) )
type KindleSpec struct {
Width int
Height int
}
func (k *KindleSpec) Bounds() image.Rectangle {
return image.Rectangle{
Min: image.Point{0, 0},
Max: image.Point{k.Width, k.Height},
}
}
func (k *KindleSpec) ConvertGray16(img image.Image) image.Image {
r := detectMarging(img)
width, heigth := r.Dx()*k.Height/r.Dy(), r.Dy()*k.Width/r.Dx()
if width > k.Width {
width = k.Width
} else {
heigth = k.Height
}
imgGray := image.NewGray16(image.Rectangle{
Min: image.Point{0, 0},
Max: image.Point{width, heigth},
})
draw.BiLinear.Scale(imgGray, imgGray.Bounds(), img, r, draw.Src, nil)
return imgGray
}
var KindleScribe = &KindleSpec{1860, 2480}
func lineIsBlank(img image.Image, y int) bool {
for x := 0; x < img.Bounds().Max.X; x++ {
r, _, _, _ := img.At(x, y).RGBA()
if r < 0xfff {
return false
}
}
return true
}
func colIsBlank(img image.Image, x int) bool {
for y := 0; y < img.Bounds().Max.Y; y++ {
r, _, _, _ := img.At(x, y).RGBA()
if r < 0xfff { // allow a light gray, white = 0xffff
return false
}
}
return true
}
func detectMarging(img image.Image) image.Rectangle {
rect := img.Bounds()
var xmin, xmax = rect.Min.X, rect.Max.X - 1
var ymin, ymax = rect.Min.Y, rect.Max.Y - 1
for ; ymin < ymax && lineIsBlank(img, ymin); ymin++ {
rect.Min.Y++
}
for ; ymin < ymax && lineIsBlank(img, ymax); ymax-- {
rect.Max.Y--
}
for ; xmin < xmax && colIsBlank(img, xmin); xmin++ {
rect.Min.X++
}
for ; xmin < xmax && colIsBlank(img, xmax); xmax-- {
rect.Max.X--
}
fmt.Println(rect)
return rect
}
func main() { func main() {
f, err := os.Open("/Users/vincent/Downloads/00001.jpg") comicconverter.
if err != nil { New(comicconverter.ComicConverterOptions{
panic(err) Quality: 90,
} }).
defer f.Close() Load("/Users/vincent/Downloads/00001.jpg").
img, _, err := image.Decode(f) GrayScale().
if err != nil { CropMarging().
panic(err) Resize(1860, 2480).
} Save("/Users/vincent/Downloads/00001_gray.jpg")
imgGray := KindleScribe.ConvertGray16(img)
o, err := os.Create("/Users/vincent/Downloads/00001_gray.jpg")
if err != nil {
panic(err)
}
defer o.Close()
err = jpeg.Encode(o, imgGray, &jpeg.Options{Quality: 90})
if err != nil {
panic(err)
}
} }