Skip to content

Instantly share code, notes, and snippets.

@viettranx
Created September 7, 2018 06:14
Show Gist options
  • Save viettranx/59a21f855ccff9505d803b5f1e65e565 to your computer and use it in GitHub Desktop.
Save viettranx/59a21f855ccff9505d803b5f1e65e565 to your computer and use it in GitHub Desktop.
This program merges all images in "./input" folder to "/output" folder horizontally
/**
* This program merges all images in "./input" folder to "/output" folder horizontally
* Ex: ./input/1.jpg + ./input/2.jpg => ./output/12.jpg
**/
package main
import (
"fmt"
"image"
"image/draw"
jpeg "image/jpeg"
_ "image/png"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
)
const INPUT_DIR_PATH = "input/"
const OUTPUT_DIR_PATH = "output/"
type Img struct {
ID int
Name string
}
type ByImg []Img
func (s ByImg) Len() int {
return len(s)
}
func (s ByImg) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s ByImg) Less(i, j int) bool {
return s[i].ID < s[j].ID
}
func NewImg(fileName string) Img {
comps := strings.Split(fileName, ".")
numb, err := strconv.Atoi(comps[0])
if err != nil {
numb = 0
}
return Img{ID: numb, Name: fileName}
}
var imgs []Img
func main() {
println("Scanning ...")
err := filepath.Walk(INPUT_DIR_PATH, func(path string, info os.FileInfo, err error) error {
if !info.IsDir() {
filePath := INPUT_DIR_PATH + info.Name()
file, _ := os.Open(filePath)
defer file.Close()
// Check is image
_, _, err = image.Decode(file)
if err == nil {
imgs = append(imgs, NewImg(info.Name()))
}
}
return nil
})
if err != nil {
println(err.Error())
return
}
sort.Sort(ByImg(imgs))
println("Number of images: ", len(imgs))
if len(imgs) == 0 || len(imgs)%2 == 1 {
println("Folder empty or number of images not even.")
return
}
for j := 0; j < len(imgs); j += 2 {
if err := mergeImg(imgs[j], imgs[j+1]); err != nil {
println(err.Error())
println("You have to create './output' folder")
return
}
}
println("Finished. Goodbye !!!")
// log.Println(imgs)
}
func max(n1, n2 int) int {
if n1 > n2 {
return n1
}
return n2
}
func mergeImg(img1, img2 Img) error {
fmt.Printf("Merging %v and %v\n", img1.Name, img2.Name)
imgPath1 := INPUT_DIR_PATH + img1.Name
imgPath2 := INPUT_DIR_PATH + img2.Name
imgFile1, _ := os.Open(imgPath1)
imgFile2, _ := os.Open(imgPath2)
image1, _, err := image.Decode(imgFile1)
image2, _, err := image.Decode(imgFile2)
if err != nil {
fmt.Println("Parse image err: ", err)
}
//rectangle for the big image
bigSize := image.Point{
X: image1.Bounds().Dx() + image2.Bounds().Dx(),
Y: max(image1.Bounds().Dy(), image2.Bounds().Dy()),
}
rect := image.Rectangle{image.Point{0, 0}, bigSize}
rgba := image.NewRGBA(rect)
rectDraw2 := image.Rectangle{image.Point{image1.Bounds().Dx(), 0}, rect.Max}
draw.Draw(rgba, image1.Bounds(), image1, image.Point{0, 0}, draw.Src)
draw.Draw(rgba, rectDraw2, image2, image.Point{0, 0}, draw.Src)
os.MkdirAll(OUTPUT_DIR_PATH, os.ModePerm)
outFilePath := OUTPUT_DIR_PATH + strconv.Itoa(img1.ID) + strconv.Itoa(img2.ID) + ".jpg"
out, err := os.Create(outFilePath)
if err != nil {
return err
}
defer out.Close()
var opt jpeg.Options
opt.Quality = 100
jpeg.Encode(out, rgba, &opt)
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment