first commit
commit
d1a64da3e9
@ -0,0 +1,5 @@
|
|||||||
|
module git.cheetah.cat/cheetah/go-snake-label
|
||||||
|
|
||||||
|
go 1.22.5
|
||||||
|
|
||||||
|
require gopkg.in/gographics/imagick.v2 v2.7.0
|
@ -0,0 +1,2 @@
|
|||||||
|
gopkg.in/gographics/imagick.v2 v2.7.0 h1:Acluvnk5MhtETFX4EVnt9NbjC32ROaaC3bx6nJueHJk=
|
||||||
|
gopkg.in/gographics/imagick.v2 v2.7.0/go.mod h1:/QVPLV/iKdNttRKthmDkeeGg+vdHurVEPc8zkU0XgBk=
|
@ -0,0 +1,52 @@
|
|||||||
|
package lib
|
||||||
|
|
||||||
|
import "gopkg.in/gographics/imagick.v2/imagick"
|
||||||
|
|
||||||
|
func ConvertPDF2PNG(pdfFile, pngFile string, dpi int, rot int) (err error) {
|
||||||
|
mw := imagick.NewMagickWand()
|
||||||
|
defer mw.Destroy()
|
||||||
|
|
||||||
|
err = mw.SetResolution(float64(dpi), float64(dpi))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = mw.ReadImage(pdfFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if mw.GetNumberImages() > 1 {
|
||||||
|
mw = mw.MergeImageLayers(imagick.IMAGE_LAYER_FLATTEN)
|
||||||
|
}
|
||||||
|
|
||||||
|
drawingWand := imagick.NewDrawingWand()
|
||||||
|
defer drawingWand.Destroy()
|
||||||
|
pixelWand := imagick.NewPixelWand()
|
||||||
|
defer pixelWand.Destroy()
|
||||||
|
pixelWand.SetColor("white")
|
||||||
|
drawingWand.SetFillColor(pixelWand)
|
||||||
|
|
||||||
|
err = mw.RotateImage(pixelWand, float64(rot))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//mw.SetIteratorIndex(0)
|
||||||
|
err = mw.SetImageAlphaChannel(imagick.ALPHA_CHANNEL_DEACTIVATE)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = mw.SetImageFormat("png")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = mw.WriteImage(pngFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
//
|
||||||
|
return nil
|
||||||
|
}
|
@ -0,0 +1,301 @@
|
|||||||
|
package lib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"gopkg.in/gographics/imagick.v2/imagick"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DHLPrivat(inputFile, outputFile string) (err error) {
|
||||||
|
canvasWidth := uint(1642)
|
||||||
|
canvasHeight := uint(696)
|
||||||
|
//
|
||||||
|
srcWand := imagick.NewMagickWand()
|
||||||
|
defer srcWand.Destroy()
|
||||||
|
|
||||||
|
if err = srcWand.ReadImage(inputFile); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
barcodeSizeX int = 710
|
||||||
|
barcodeSizeY int = 320
|
||||||
|
scSize int = 296
|
||||||
|
)
|
||||||
|
sections := []struct {
|
||||||
|
srcX, srcY, srcW, srcH,
|
||||||
|
tgtX, tgtY, tgtW, tgtH,
|
||||||
|
rot int
|
||||||
|
}{
|
||||||
|
|
||||||
|
{ // Kopf
|
||||||
|
1964, 106, 1124, 94,
|
||||||
|
0, 0, 890, 74,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // Adresse
|
||||||
|
1964, 210, 785, 625,
|
||||||
|
0, 95, 580, 465,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // Sicherheitscode
|
||||||
|
2763, 215, scSize, scSize,
|
||||||
|
594, 90, scSize, scSize,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // Sicherheitscode Text
|
||||||
|
3075, 244, 20, 194,
|
||||||
|
645, 395, 200, 20,
|
||||||
|
270,
|
||||||
|
},
|
||||||
|
{ // Bahntransport
|
||||||
|
2802, 679, 234, 154,
|
||||||
|
666, 465, 152, 100,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ //Sendungsdaten
|
||||||
|
1964, 933, 1124, 152,
|
||||||
|
0, 576, 890, 120,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // Leitcode/Routingcode
|
||||||
|
2181, 1526, barcodeSizeX, barcodeSizeY,
|
||||||
|
930, 20, barcodeSizeX, barcodeSizeY,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // Identcode/Sendungsnummer
|
||||||
|
2181, 1940, barcodeSizeX, barcodeSizeY,
|
||||||
|
930, 376, barcodeSizeX, barcodeSizeY,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
outputWand := imagick.NewMagickWand()
|
||||||
|
defer outputWand.Destroy()
|
||||||
|
drawingWand := imagick.NewDrawingWand()
|
||||||
|
defer drawingWand.Destroy()
|
||||||
|
pixelWand := imagick.NewPixelWand()
|
||||||
|
defer pixelWand.Destroy()
|
||||||
|
|
||||||
|
// Set canvas size for the output image
|
||||||
|
pixelWand.SetColor("white")
|
||||||
|
drawingWand.SetFillColor(pixelWand)
|
||||||
|
err = outputWand.NewImage(canvasWidth, canvasHeight, pixelWand)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, section := range sections {
|
||||||
|
cropped := srcWand.Clone()
|
||||||
|
defer cropped.Destroy()
|
||||||
|
|
||||||
|
if err := cropped.CropImage(uint(section.srcW), uint(section.srcH), int(section.srcX), int(section.srcY)); err != nil {
|
||||||
|
return fmt.Errorf("failed to crop section %d: %v", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if section.rot != 0 {
|
||||||
|
err = cropped.RotateImage(pixelWand, float64(section.rot))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to rotate section %d: %v", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Resize cropped section (if needed)
|
||||||
|
if err := cropped.ResizeImage(uint(section.tgtW), uint(section.tgtH), imagick.FILTER_LANCZOS, 1); err != nil {
|
||||||
|
return fmt.Errorf("failed to resize section %d: %v", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//cropped.WriteImage(fmt.Sprintf("section%d.png", i))
|
||||||
|
// Composite the cropped section onto the output canvas
|
||||||
|
if err := outputWand.CompositeImage(cropped, imagick.COMPOSITE_OP_COPY, int(section.tgtX), int(section.tgtY)); err != nil {
|
||||||
|
return fmt.Errorf("failed to composite section %d: %v", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ // Line
|
||||||
|
strokeWand := imagick.NewPixelWand()
|
||||||
|
defer strokeWand.Destroy()
|
||||||
|
strokeWand.SetColor("black")
|
||||||
|
lineWand := imagick.NewDrawingWand()
|
||||||
|
defer lineWand.Destroy()
|
||||||
|
|
||||||
|
lineWand.SetStrokeColor(strokeWand)
|
||||||
|
lineWand.Line(910, 0, 910, float64(canvasHeight))
|
||||||
|
|
||||||
|
err = outputWand.DrawImage(lineWand)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = outputWand.SetImageFormat("png")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = outputWand.WriteImage(outputFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
//
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func DHLPrivatInternational(inputFile, outputFile string) (err error) {
|
||||||
|
canvasWidth := uint(2232)
|
||||||
|
canvasHeight := uint(696)
|
||||||
|
//
|
||||||
|
srcWand := imagick.NewMagickWand()
|
||||||
|
defer srcWand.Destroy()
|
||||||
|
|
||||||
|
if err = srcWand.ReadImage(inputFile); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
barcodeSizeX int = 1124
|
||||||
|
barcodeSizeY int = 280
|
||||||
|
scSize int = 296
|
||||||
|
)
|
||||||
|
sections := []struct {
|
||||||
|
srcX, srcY, srcW, srcH,
|
||||||
|
tgtX, tgtY, tgtW, tgtH,
|
||||||
|
rot int
|
||||||
|
}{
|
||||||
|
{ // Kopf
|
||||||
|
1964, 106, 1124, 94,
|
||||||
|
0, 0, 890, 74,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // Adresse
|
||||||
|
1964, 210, 785, 625,
|
||||||
|
0, 95, 580, 465,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // Sicherheitscode
|
||||||
|
2763, 215, scSize, scSize,
|
||||||
|
594, 90, scSize, scSize,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // Sicherheitscode Text
|
||||||
|
3075, 244, 20, 194,
|
||||||
|
645, 395, 200, 20,
|
||||||
|
270,
|
||||||
|
},
|
||||||
|
{ // Telefonnummer & E-Mail
|
||||||
|
2768, 743, 300, 60,
|
||||||
|
590, 495, 300, 60,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ //Sendungsdaten
|
||||||
|
1964, 933, 1124, 152,
|
||||||
|
0, 576, 890, 120,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // Icons / Go Green
|
||||||
|
1964, 854, 1124, 70,
|
||||||
|
920, 696, 696, 43,
|
||||||
|
270,
|
||||||
|
},
|
||||||
|
{ // Tracked
|
||||||
|
1964, 1197, 1124, 122,
|
||||||
|
986, 696, 696, 76,
|
||||||
|
270,
|
||||||
|
},
|
||||||
|
{ // Tracked Icon
|
||||||
|
2846, 530, 130, 202,
|
||||||
|
930, 10, 130, 202,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // Unzustellbarkeit
|
||||||
|
1964, 1422, barcodeSizeX, 70,
|
||||||
|
1100, 4, barcodeSizeX, 70,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // Leitcode/Routingcode
|
||||||
|
1964, 1634, barcodeSizeX, barcodeSizeY,
|
||||||
|
1100, 100, barcodeSizeX, barcodeSizeY,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // Category Letter
|
||||||
|
1964, 2000, 160, barcodeSizeY - 20,
|
||||||
|
1100, 416, 160, barcodeSizeY - 20,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // Identcode/Sendungsnummer
|
||||||
|
1964, 2048 + 260, 160, 20,
|
||||||
|
1100, 416 + 260, 160, 20,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // Identcode/Sendungsnummer (2)
|
||||||
|
1964 + 160, 2048, barcodeSizeX - 160, barcodeSizeY,
|
||||||
|
1100 + 160, 416, barcodeSizeX - 160, barcodeSizeY,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
outputWand := imagick.NewMagickWand()
|
||||||
|
defer outputWand.Destroy()
|
||||||
|
drawingWand := imagick.NewDrawingWand()
|
||||||
|
defer drawingWand.Destroy()
|
||||||
|
pixelWand := imagick.NewPixelWand()
|
||||||
|
defer pixelWand.Destroy()
|
||||||
|
|
||||||
|
// Set canvas size for the output image
|
||||||
|
pixelWand.SetColor("white")
|
||||||
|
drawingWand.SetFillColor(pixelWand)
|
||||||
|
err = outputWand.NewImage(canvasWidth, canvasHeight, pixelWand)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, section := range sections {
|
||||||
|
cropped := srcWand.Clone()
|
||||||
|
defer cropped.Destroy()
|
||||||
|
|
||||||
|
if err := cropped.CropImage(uint(section.srcW), uint(section.srcH), int(section.srcX), int(section.srcY)); err != nil {
|
||||||
|
return fmt.Errorf("failed to crop section %d: %v", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if section.rot != 0 {
|
||||||
|
err = cropped.RotateImage(pixelWand, float64(section.rot))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to rotate section %d: %v", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Resize cropped section (if needed)
|
||||||
|
if err := cropped.ResizeImage(uint(section.tgtW), uint(section.tgtH), imagick.FILTER_LANCZOS, 1); err != nil {
|
||||||
|
return fmt.Errorf("failed to resize section %d: %v", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Composite the cropped section onto the output canvas
|
||||||
|
if err := outputWand.CompositeImage(cropped, imagick.COMPOSITE_OP_COPY, int(section.tgtX), int(section.tgtY)); err != nil {
|
||||||
|
return fmt.Errorf("failed to composite section %d: %v", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ // Line 1
|
||||||
|
strokeWand := imagick.NewPixelWand()
|
||||||
|
defer strokeWand.Destroy()
|
||||||
|
strokeWand.SetColor("black")
|
||||||
|
lineWand := imagick.NewDrawingWand()
|
||||||
|
defer lineWand.Destroy()
|
||||||
|
|
||||||
|
lineWand.SetStrokeColor(strokeWand)
|
||||||
|
lineWand.Line(910, 0, 910, float64(canvasHeight))
|
||||||
|
lineWand.Line(920, 230, 1070, 230)
|
||||||
|
lineWand.Line(970, 240, 970, float64(canvasHeight))
|
||||||
|
lineWand.Line(1080, 0, 1080, float64(canvasHeight))
|
||||||
|
|
||||||
|
err = outputWand.DrawImage(lineWand)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = outputWand.SetImageFormat("png")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = outputWand.WriteImage(outputFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
//
|
||||||
|
return nil
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/hex"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.cheetah.cat/cheetah/go-snake-label/lib"
|
||||||
|
"gopkg.in/gographics/imagick.v2/imagick"
|
||||||
|
)
|
||||||
|
|
||||||
|
var src = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
|
||||||
|
func RandStringBytesMaskImprSrc(n int) string {
|
||||||
|
b := make([]byte, (n+1)/2)
|
||||||
|
if _, err := src.Read(b); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return hex.EncodeToString(b)[:n]
|
||||||
|
}
|
||||||
|
|
||||||
|
func tempPNGPath() string {
|
||||||
|
return path.Join(os.TempDir(), fmt.Sprintf(RandStringBytesMaskImprSrc(16), ".png"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// sudo apt-get install libmagickwand-dev
|
||||||
|
func main() {
|
||||||
|
imagick.Initialize()
|
||||||
|
defer imagick.Terminate()
|
||||||
|
|
||||||
|
inputFile := flag.String("input", "", "input filename")
|
||||||
|
outputFile := flag.String("output", "", "output filename")
|
||||||
|
modeSelect := flag.String("mode", "dhlprivat", "mode select (dhlprivat, dhlprivatint)")
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if len(*inputFile) < 3 {
|
||||||
|
panic("invalid input file")
|
||||||
|
}
|
||||||
|
if len(*outputFile) == 0 {
|
||||||
|
panic("invalid output file")
|
||||||
|
}
|
||||||
|
|
||||||
|
tempFileName := tempPNGPath()
|
||||||
|
defer os.Remove(tempFileName)
|
||||||
|
|
||||||
|
outputFileName := *outputFile
|
||||||
|
outputSTDOUT := false
|
||||||
|
if outputFileName == "-" || outputFileName == "/dev/stdout" {
|
||||||
|
outputSTDOUT = true
|
||||||
|
outputFileName = tempPNGPath()
|
||||||
|
defer os.Remove(outputFileName)
|
||||||
|
}
|
||||||
|
switch *modeSelect {
|
||||||
|
case "dhlprivat":
|
||||||
|
// scale: 4, // optional, defaults to 4 (288dpi) -- 4.1666 for 300dpi
|
||||||
|
lib.ConvertPDF2PNG(*inputFile, tempFileName, 288, 90)
|
||||||
|
lib.DHLPrivat(tempFileName, outputFileName)
|
||||||
|
case "dhlprivatint":
|
||||||
|
lib.ConvertPDF2PNG(*inputFile, tempFileName, 288, 90)
|
||||||
|
lib.DHLPrivatInternational(tempFileName, outputFileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if outputSTDOUT {
|
||||||
|
outputBytes, _ := os.ReadFile(outputFileName)
|
||||||
|
binary.Write(os.Stdout, binary.LittleEndian, outputBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue