Last active
December 28, 2021 15:19
-
-
Save JokerCatz/2af8ed7c232251d9b861b02c57d378c8 to your computer and use it in GitHub Desktop.
golang image append , support jpg / png / webp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"fmt" | |
"image" | |
"image/draw" | |
"image/jpeg" | |
"image/png" | |
"io/ioutil" | |
"os" | |
"golang.org/x/image/webp" | |
) | |
// only support jpg , png , webp | |
// webp only support read | |
type ImageType int | |
const ( | |
ImageTypeJPG ImageType = iota + 1 | |
ImageTypePNG | |
ImageTypeWEBP | |
) | |
// ImageTypeFileHead fast filetype check | |
var ImageTypeFileHead = map[ImageType][]byte{ | |
ImageTypeJPG: {0xFF, 0xD8, 0xFF}, | |
ImageTypePNG: {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}, | |
ImageTypeWEBP: {0x52, 0x49, 0x46, 0x46}, | |
} | |
func getImage(filePath string) (img *image.Image, err error) { | |
var data []byte | |
data, err = ioutil.ReadFile(filePath) | |
if err != nil { | |
return | |
} | |
var imageType *ImageType | |
for tempImageType, tempImageFileHead := range ImageTypeFileHead { | |
if len(data) < len(tempImageFileHead) { | |
continue | |
} | |
if bytes.Equal(data[:len(tempImageFileHead)], tempImageFileHead) { | |
imageType = &tempImageType | |
break | |
} | |
} | |
if imageType == nil { | |
err = fmt.Errorf("image file not support , file head not match") | |
return | |
} | |
var tempImg image.Image | |
switch *imageType { | |
case ImageTypeJPG: | |
tempImg, err = jpeg.Decode(bytes.NewReader(data)) | |
case ImageTypePNG: | |
tempImg, err = png.Decode(bytes.NewReader(data)) | |
case ImageTypeWEBP: | |
tempImg, err = webp.Decode(bytes.NewReader(data)) | |
default: | |
err = fmt.Errorf("image file not support , file head not match") | |
} | |
if err == nil { | |
img = &tempImg | |
} | |
return | |
} | |
func saveImage(img image.Image, filePath string, imageType ImageType, jpgQuality *int) (err error) { | |
f, err := os.Create(filePath) | |
if err != nil { | |
return | |
} | |
defer f.Close() | |
switch imageType { | |
case ImageTypeJPG: | |
if jpgQuality == nil { | |
temp := 80 // default 80 | |
jpgQuality = &temp | |
} | |
err = jpeg.Encode(f, img, &jpeg.Options{Quality: *jpgQuality}) | |
case ImageTypePNG: | |
err = png.Encode(f, img) | |
default: | |
err = fmt.Errorf("unknow image type to save file") | |
} | |
return | |
} | |
func mergeImage(fileList []string) (rgbaConvas *image.RGBA64, err error) { | |
var imageSize image.Point | |
for index, fileName := range fileList { | |
var imgP *image.Image | |
imgP, err = getImage(fileName) | |
if err != nil { | |
return | |
} | |
img := *imgP | |
if index == 0 { | |
imageSize = img.Bounds().Max | |
rgbaConvas = image.NewRGBA64(image.Rectangle{image.Point{0, 0}, img.Bounds().Max}) // create empty canvas | |
} | |
if !img.Bounds().Max.Eq(imageSize) { | |
tImageSize := img.Bounds().Max | |
err = fmt.Errorf("image not all match , image(%d:%d) , [%d:%s](%d:%d)", imageSize.X, imageSize.Y, index, fileName, tImageSize.X, tImageSize.Y) | |
return | |
} | |
draw.Draw(rgbaConvas, img.Bounds(), img, image.Point{0, 0}, draw.Over) // draw image to canvas | |
} | |
if rgbaConvas == nil { | |
err = fmt.Errorf("empty canvas") | |
return | |
} | |
return | |
} | |
func main() { | |
img, err := mergeImage([]string{ | |
"layer1.webp", "layer2.png", "layer3.webp", "layer4.png", | |
}) | |
if err != nil { | |
fmt.Println("ERR", err) | |
return | |
} | |
err = saveImage(img, "final.png", ImageTypePNG, nil) | |
if err != nil { | |
fmt.Println("ERR", err) | |
return | |
} | |
fmt.Println("finished!") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment