Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
develar committed Jan 4, 2018
0 parents commit 4ec4da1
Show file tree
Hide file tree
Showing 10 changed files with 387 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
builds:
- goos:
- windows
- darwin
- linux
archive:
format: binary

snapshot:
name_template: SNAPSHOT
6 changes: 6 additions & 0 deletions .idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions app-builder.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
214 changes: 214 additions & 0 deletions commands/icon.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
package commands

import (
"image"
"os"

"github.com/disintegration/imaging"
"image/png"
"bufio"
"text/template"
"bytes"
"sync"
"runtime"
"os/exec"
"io/ioutil"
"path"
"encoding/json"
"fmt"
"github.com/develar/app-builder/util"
"strings"
)

type IconInfo struct {
File string `json:"file"`
Size int `json:"size"`
}

type Icns2PngMapping struct {
Id string
Size int
}

var icns2PngMappingList = []Icns2PngMapping{
{"is32", 16},
{"il32", 32},
{"ih32", 48},
{"icp6", 64},
{"it32", 128},
{"ic08", 256},
{"ic09", 512},
}

type ConvertIcnsToPngResult struct {
MaxIconPath string `json:"maxIconPath"`
Icons []IconInfo `json:"icons"`
}

func ConvertIcnsToPng(inFile string) error {
tempDir, err := util.TempDir(os.Getenv("ELECTRON_BUILDER_TMP_DIR"), ".iconset")
if err != nil {
return err
}

var maxIconPath string
var result []IconInfo

sizeList := []int{24, 96}
outFileTemplate := path.Join(tempDir, "icon_{{.Width}}x{{.Height}}.png")
if runtime.GOOS == "darwin" && os.Getenv("FORCE_ICNS2PNG") == "" {
output, err := exec.Command("iconutil", "--convert", "iconset", "--output", tempDir, inFile).CombinedOutput()
if err != nil {
fmt.Println(string(output))
return err
}

iconFiles, err := ioutil.ReadDir(tempDir)
if err != nil {
return err
}

for _, item := range icns2PngMappingList {
fileName := fmt.Sprintf("icon_%dx%d.png", item.Size, item.Size)
if contains(iconFiles, fileName) {
// list sorted by size, so, last assignment is a max size
maxIconPath = path.Join(tempDir, fileName)
result = append(result, IconInfo{maxIconPath, item.Size})
} else {
sizeList = append(sizeList, item.Size)
}
}
} else {
outputBytes, err := exec.Command("icns2png", "--extract", "--output", tempDir, inFile).CombinedOutput()
output := string(outputBytes)
if err != nil {
fmt.Println(output)
return err
}

namePrefix := strings.TrimSuffix(path.Base(inFile), path.Ext(inFile))

for _, item := range icns2PngMappingList {
if strings.Contains(output, item.Id) {
// list sorted by size, so, last assignment is a max size
maxIconPath = path.Join(tempDir, fmt.Sprintf("%s_%dx%dx32.png", namePrefix, item.Size, item.Size))
result = append(result, IconInfo{maxIconPath, item.Size})
} else {
sizeList = append(sizeList, item.Size)
}
}
}

err = multiResizeImage(maxIconPath, outFileTemplate, &result, sizeList, nil)
if err != nil {
return err
}

serializedResult, err := json.Marshal(ConvertIcnsToPngResult{
MaxIconPath: maxIconPath,
Icons: result,
})
if err != nil {
return err
}

_, err = os.Stdout.Write(serializedResult)
if err != nil {
return err
}

return nil
}

func contains(files []os.FileInfo, name string) bool {
for _, fileInfo := range files {
if fileInfo.Name() == name {
return true
}
}
return false
}

func multiResizeImage(inFile string, outFileNameTemplateString string, result *[]IconInfo, wList []int, hList []int) (error) {
reader, err := os.Open(inFile)
if err != nil {
return err
}

originalImage, _, err := image.Decode(reader)
if err != nil {
return err
}

if hList == nil || len(hList) == 0 {
hList = wList
}

outFileNameTemplate := template.Must(template.New("name").Parse(outFileNameTemplateString))

var waitGroup sync.WaitGroup

imageCount := len(wList)
waitGroup.Add(imageCount)

for i := 0; i < imageCount; i++ {
w := wList[i]
h := hList[i]

outFilePath, err := computeName(outFileNameTemplate, map[string]interface{}{
"Width": w,
"Height": h,
})
if err != nil {
return err
}

*result = append(*result, IconInfo{
File: outFilePath,
Size: w,
})
go resizeImage(originalImage, w, h, outFilePath, &waitGroup)
}

waitGroup.Wait()
return nil
}

func computeName(template *template.Template, data interface{}) (string, error) {
outFileNameBuffer := &bytes.Buffer{}
err := template.Execute(outFileNameBuffer, data)
if err != nil {
return "", err
}
return outFileNameBuffer.String(), nil
}

func resizeImage(originalImage image.Image, w int, h int, outFileName string, waitGroup *sync.WaitGroup) error {
defer waitGroup.Done()
newImage := imaging.Resize(originalImage, w, h, imaging.Lanczos)
return saveImage(newImage, outFileName)
}

func saveImage(image *image.NRGBA, outFileName string) error {
outFile, err := os.Create(outFileName)
if err != nil {
return err
}

writer := bufio.NewWriter(outFile)
err = png.Encode(writer, image)
if err != nil {
return err
}

flushError := writer.Flush()
closeError := outFile.Close()
if flushError != nil {
return flushError
}
if closeError != nil {
return closeError
}

return nil
}
25 changes: 25 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package main

import (
"gopkg.in/alecthomas/kingpin.v2"
"os"
"github.com/develar/app-builder/commands"
"log"
)

var (
app = kingpin.New("app-builder", "app-builder").Version("0.1.0")

icnsToPng = app.Command("icns-to-png", "convert ICNS to PNG")
icnsToPngInFile = icnsToPng.Flag("input", "input ICNS file").Short('i').Required().String()
)

func main() {
switch kingpin.MustParse(app.Parse(os.Args[1:])) {
case icnsToPng.FullCommand():
err := commands.ConvertIcnsToPng(*icnsToPngInFile)
if err != nil {
log.Fatal(err)
}
}
}
33 changes: 33 additions & 0 deletions publish.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env bash
set -e

BASEDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

if [ -z "$GITHUB_TOKEN" ] ; then
SEC=`security find-generic-password -l GH_TOKEN -g 2>&1`
export GITHUB_TOKEN=`echo "$SEC" | grep "password" | cut -d \" -f 2`
fi

NAME=app-builder
VERSION=0.1.0

OUT_DIR="$BASEDIR/dist/out"
rm -rf "$OUT_DIR"

publish()
{
outDir=$1
archiveName="$NAME-v$VERSION-$2"
archiveFile="$OUT_DIR/$archiveName.7z"

cd "$BASEDIR/dist/$outDir"
7za a -mx=9 -mfb=64 "$archiveFile" .
}

publish "darwinamd64" mac
publish "linux386" linux-ia32
publish "linuxamd64" linux-x64
publish "windows386" win-ia32
publish "windowsamd64" win-x64

tool-releaser develar/app-builder "v$VERSION" master "" "$OUT_DIR/*.7z"
3 changes: 3 additions & 0 deletions release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash

goreleaser --rm-dist "$@"
Loading

0 comments on commit 4ec4da1

Please sign in to comment.