diff --git a/cbconvert.go b/cbconvert.go index cd47fb2..34fa07c 100644 --- a/cbconvert.go +++ b/cbconvert.go @@ -22,6 +22,7 @@ import ( "github.com/gen2brain/avif" "github.com/gen2brain/jpegxl" "github.com/gen2brain/webp" + "github.com/jsummers/gobmp" "golang.org/x/image/tiff" pngstructure "github.com/dsoprea/go-png-image-structure" @@ -510,6 +511,10 @@ func (c *Converter) imageEncode(img image.Image, w io.Writer) error { err = avif.Encode(w, img, avif.Options{Quality: c.Opts.Quality, Speed: avif.DefaultSpeed}) case "jxl": err = jpegxl.Encode(w, img, jpegxl.Options{Quality: c.Opts.Quality, Effort: jpegxl.DefaultEffort}) + case "bmp": + opts := &gobmp.EncoderOptions{} + opts.SupportTransparency(false) + err = gobmp.EncodeWithOptions(w, imageToPaletted(img), opts) } if err != nil { diff --git a/cbconvert_image.go b/cbconvert_image.go index fb64713..6806ccd 100644 --- a/cbconvert_image.go +++ b/cbconvert_image.go @@ -133,3 +133,31 @@ func isGrayScale(img image.Image) bool { return false } + +var colors16 = []color.Color{ + color.RGBA{0, 0, 0, 255}, + color.RGBA{24, 24, 24, 255}, + color.RGBA{40, 40, 40, 255}, + color.RGBA{56, 56, 56, 255}, + color.RGBA{71, 71, 71, 255}, + color.RGBA{86, 86, 86, 255}, + color.RGBA{100, 100, 100, 255}, + color.RGBA{113, 113, 113, 255}, + color.RGBA{126, 126, 126, 255}, + color.RGBA{140, 140, 140, 255}, + color.RGBA{155, 155, 155, 255}, + color.RGBA{171, 171, 171, 255}, + color.RGBA{189, 189, 189, 255}, + color.RGBA{209, 209, 209, 255}, + color.RGBA{231, 231, 231, 255}, + color.RGBA{255, 255, 255, 255}, +} + +// imageToPaletted converts an image.Image to *image.Paletted using 16-color palette. +func imageToPaletted(src image.Image) *image.Paletted { + b := src.Bounds() + dst := image.NewPaletted(b, colors16) + draw.Draw(dst, dst.Bounds(), src, b.Min, draw.Src) + + return dst +} diff --git a/cbconvert_test.go b/cbconvert_test.go index 6a68152..a69ea35 100644 --- a/cbconvert_test.go +++ b/cbconvert_test.go @@ -18,9 +18,6 @@ func TestConvert(t *testing.T) { conv := New(opts) - conv.Initialize() - defer conv.Terminate() - files, err := conv.Files([]string{"testdata/test", "testdata"}) if err != nil { t.Error(err) @@ -56,9 +53,6 @@ func TestCover(t *testing.T) { conv := New(opts) - conv.Initialize() - defer conv.Terminate() - files, err := conv.Files([]string{"testdata/test.cbt"}) if err != nil { t.Error(err) @@ -88,9 +82,6 @@ func TestThumbnail(t *testing.T) { conv := New(opts) - conv.Initialize() - defer conv.Terminate() - files, err := conv.Files([]string{"testdata/test.pdf"}) if err != nil { t.Error(err) diff --git a/go.mod b/go.mod index a616f4f..4251fd7 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/gen2brain/go-unarr v0.2.3 github.com/gen2brain/jpegxl v0.4.1 github.com/gen2brain/webp v0.5.0 + github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 golang.org/x/image v0.21.0 golang.org/x/sync v0.8.0 ) diff --git a/go.sum b/go.sum index 8e88bd2..a89f562 100644 --- a/go.sum +++ b/go.sum @@ -42,6 +42,8 @@ github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgR github.com/golang/geo v0.0.0-20230421003525-6adc56603217 h1:HKlyj6in2JV6wVkmQ4XmG/EIm+SCYlPZ+V4GWit7Z+I= github.com/golang/geo v0.0.0-20230421003525-6adc56603217/go.mod h1:8wI0hitZ3a1IxZfeH3/5I97CI8i5cLGsYe7xNhQGs9U= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M= +github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw= github.com/jupiterrider/ffi v0.2.1 h1:08GJVDqz4eoQq7cKT1T0kwb9MB58XEAGjgxDvz80yBs= github.com/jupiterrider/ffi v0.2.1/go.mod h1:tJ7Q8p/3blFjdWt5qJU4W5oDE0xloImvrViE+0td0Rk= github.com/tetratelabs/wazero v1.8.1 h1:NrcgVbWfkWvVc4UtT4LRLDf91PsOzDzefMdwhLfA550=