Skip to content

Commit

Permalink
Refactored - split functionalities into structs and interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
ajaxray committed Mar 25, 2018
1 parent 60a32eb commit 725ebb5
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 91 deletions.
14 changes: 11 additions & 3 deletions img.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,16 @@ import (

var pageMargin [4]float64
var pageSize creator.PageSize
var sizeHasSet, merginHasSet = false, false
var sizeHasSet, marginHasSet = false, false

type ImgSource struct {
source
}

func (s ImgSource) MergeTo(c *creator.Creator) error {
return addImage(s.path, c, s.mime)
}

// func addImageToPdf(inputPath string, outputPath string, imagePath string, pageNum int, xPos float64, yPos float64, iwidth float64) error {
func addImage(filePath string, c *creator.Creator, fileType string) error {
debugInfo(fmt.Sprintf("Adding image: %s", filePath))

Expand All @@ -39,7 +46,7 @@ func addImage(filePath string, c *creator.Creator, fileType string) error {

func setMargin(img *creator.Image, c *creator.Creator) {

if !merginHasSet {
if !marginHasSet {
for i, m := range strings.Split(margin, ",") {
floatVal, err := strconv.ParseFloat(m, 64)
if err != nil {
Expand All @@ -48,6 +55,7 @@ func setMargin(img *creator.Image, c *creator.Creator) {

pageMargin[i] = floatVal * creator.PPI
}
marginHasSet = true
}

c.SetPageMargins(pageMargin[0], pageMargin[1], pageMargin[2], pageMargin[3])
Expand Down
83 changes: 12 additions & 71 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package main

import (
"errors"
"fmt"
"os"
"strconv"
"strings"

flag "github.com/ogier/pflag"
unicommon "github.com/unidoc/unidoc/common"
Expand All @@ -18,8 +15,8 @@ var JPEGQuality int

const (
DefaultSize = "IMG-SIZE"
DefaultMargin = "1,1,1,1"
VERSION = "1.0.1"
DefaultMargin = "0,0,0,0"
VERSION = "1.0.2"
)

func init() {
Expand All @@ -29,8 +26,8 @@ func init() {
flag.BoolVar(&scaleW, "scale-width", false, "Scale Image to page width. Only if --size specified.")
flag.BoolVar(&scaleH, "scale-height", false, "Scale Image to page height. Only if --size specified.")
flag.IntVar(&JPEGQuality, "jpeg-quality", 100, "Optimize JPEG Quality.")
flag.BoolVarP(&verbose, "verbose", "v", false, "Display debug info.")
flag.BoolVarP(&version, "version", "V", false, "Display debug info.")
flag.BoolVarP(&verbose, "verbose", "v", false, "Display debug information.")
flag.BoolVarP(&version, "version", "V", false, "Display Version information.")

flag.Usage = func() {
fmt.Println("merge2pdf [options...] <output_file> <input_file> [<input_file>...]")
Expand Down Expand Up @@ -58,79 +55,23 @@ func main() {
}

outputPath := args[0]
inputPaths := []string{}
inputPages := [][]int{}
inputPaths := args[1:]

for _, arg := range flag.Args()[1:] {
//inputPaths = append(inputPaths, arg)

fileInputParts := strings.Split(arg, "~")
inputPaths = append(inputPaths, fileInputParts[0])
pages := []int{}

if len(fileInputParts) > 1 {
for _, e := range strings.Split(fileInputParts[1], ",") {
pageNo, err := strconv.Atoi(strings.Trim(e, " \n"))
if err != nil {
fmt.Errorf("Invalid format! Example of a file input with page numbers: path/to/abc.pdf~1,2,3,5,6")
os.Exit(1)
}
pages = append(pages, pageNo)
}
}

inputPages = append(inputPages, pages)
}

// fmt.Println(inputPaths)
// fmt.Println(inputPages)
// os.Exit(1)

err := mergePdf(inputPaths, inputPages, outputPath)
if err != nil {
fmt.Printf("Error: %v\n", err)
os.Exit(1)
}

debugInfo(fmt.Sprintf("Complete, see output file: %s", outputPath))
}

func mergePdf(inputPaths []string, inputPages [][]int, outputPath string) error {
c := creator.New()

for i, inputPath := range inputPaths {

f, err := os.Open(inputPath)
for _, arg := range inputPaths {
err := NewSource(arg).MergeTo(c)
if err != nil {
return err
}
defer f.Close()

fileType, typeError := getFileType(f)
if typeError != nil {
return typeError
}

if fileType == "directory" {
// @TODO : Read all files in directory
return errors.New(inputPath + " is a drectory.")
} else if fileType == "application/pdf" {
err = addPdfPages(f, inputPages[i], c)
} else if fileType[:6] == "image/" {
err = addImage(inputPath, c, fileType)
} else {
err = errors.New("Unsupported type:" + inputPath)
}

if err != nil {
return err
fmt.Printf("Error: %s (%s) \n", err.Error(), arg)
os.Exit(1)
}
}

err := c.WriteToFile(outputPath)
if err != nil {
return err
fmt.Printf("Error: %s \n", err.Error())
}

return nil
debugInfo(fmt.Sprintf("Complete, see output file: %s", outputPath))
os.Exit(0)
}
9 changes: 9 additions & 0 deletions pdf.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ import (
pdf "github.com/unidoc/unidoc/pdf/model"
)

type PDFSource struct {
source
}

func (s PDFSource) MergeTo(c *creator.Creator) error {
f, _ := os.Open(s.path)
return addPdfPages(f, s.pages, c)
}

func getReader(rs io.ReadSeeker) (*pdf.PdfReader, error) {

pdfReader, err := pdf.NewPdfReader(rs)
Expand Down
96 changes: 96 additions & 0 deletions source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package main

import (
"errors"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"

"github.com/labstack/gommon/log"
"github.com/unidoc/unidoc/pdf/creator"
)

type mergable interface {
MergeTo(c *creator.Creator) error
}

type source struct {
path, sourceType, mime, ext string
pages []int
}

// Initiate new source file from input argument
func NewSource(input string) mergable {
fileInputParts := strings.Split(input, "~")

path := fileInputParts[0]
f, err := os.Open(fileInputParts[0])
if err != nil {
log.Fatal("Cannot read source file:", fileInputParts[0])
}

defer f.Close()

ext := filepath.Ext(f.Name())
mime, err := getMimeType(f)
if err != nil {
log.Fatal("Error in getting mime type of file:", fileInputParts[0])
}

sourceType, err := getFileType(mime, ext)
if err != nil {
log.Fatal("Error : %s (%s)", err.Error(), path)
}

pages := []int{}
if len(fileInputParts) > 1 {
pages = parsePageNums(fileInputParts[1])
}

source := source{path, sourceType, mime, ext, pages}

var m mergable
switch sourceType {
case "image":
m = ImgSource{source}
case "pdf":
m = PDFSource{source}
}

return m
}

func getFileType(mime, ext string) (string, error) {
pdfExts := []string{".pdf", ".PDF"}
imgExts := []string{".jpg", ".jpeg", ".gif", ".png", ".tiff", ".tif", ".JPG", ".JPEG", ".GIF", ".PNG", ".TIFF", ".TIF"}

switch {
case mime == "application/pdf":
return "pdf", nil
case mime[:6] == "image/":
return "image", nil
case mime == "application/octet-stream" && in_array(ext, pdfExts):
return "pdf", nil
case mime == "application/octet-stream" && in_array(ext, imgExts):
return "image", nil
}

return "error", errors.New("Could not detect file type.")
}

func parsePageNums(pagesInput string) []int {
pages := []int{}

for _, e := range strings.Split(pagesInput, ",") {
pageNo, err := strconv.Atoi(strings.Trim(e, " \n"))
if err != nil {
fmt.Errorf("Invalid format! Example of a file input with page numbers: path/to/abc.pdf~1,2,3,5,6")
os.Exit(1)
}
pages = append(pages, pageNo)
}

return pages
}
31 changes: 14 additions & 17 deletions util.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ import (
"reflect"
)

func in_array(val interface{}, array interface{}) (exists bool, index int) {
exists = false
func in_array(val interface{}, array interface{}) bool {
return at_array(val, array) != -1
}

func at_array(val interface{}, array interface{}) (index int) {
index = -1

switch reflect.TypeOf(array).Kind() {
Expand All @@ -18,7 +21,6 @@ func in_array(val interface{}, array interface{}) (exists bool, index int) {
for i := 0; i < s.Len(); i++ {
if reflect.DeepEqual(val, s.Index(i).Interface()) == true {
index = i
exists = true
return
}
}
Expand All @@ -27,22 +29,17 @@ func in_array(val interface{}, array interface{}) (exists bool, index int) {
return
}

func getFileType(file *os.File) (string, error) {
func getMimeType(file *os.File) (string, error) {
// Only the first 512 bytes are used to sniff the content type.
if info, stateErr := file.Stat(); stateErr != nil {
return "error", stateErr
} else if info.IsDir() {
return "directory", nil
} else {
buffer := make([]byte, 512)
_, readError := file.Read(buffer)
if readError != nil {
return "error", readError
}

// Always returns a valid content-type and "application/octet-stream" if no others seemed to match.
return http.DetectContentType(buffer), nil
buffer := make([]byte, 512)
_, readError := file.Read(buffer)
if readError != nil {
debugInfo("Read error for file: " + file.Name())
return "error", readError
}

// Always returns a valid content-type and "application/octet-stream" if no others seemed to match.
return http.DetectContentType(buffer), nil
}

func debugInfo(message string) {
Expand Down

0 comments on commit 725ebb5

Please sign in to comment.