forked from GeertJohan/go.leptonica
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathleptonica.go
145 lines (127 loc) · 3.17 KB
/
leptonica.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package leptonica
/*
#cgo darwin LDFLAGS: -llept
#cgo windows LDFLAGS: /opt/leptonice/src/liblept.dll
#include "/opt/leptonica/src/allheaders.h"
#include <stdlib.h>
l_uint8* uglycast(void* value) { return (l_uint8*)value; }
*/
import "C"
import (
"errors"
"strconv"
"sync"
"unsafe"
)
type ImageType int32
const (
UNKNOWN ImageType = iota
BMP
JFIF_JPEG
PNG
TIFF
TIFF_PACKBITS
TIFF_RLE
TIFF_G3
TIFF_G4
TIFF_LZW
TIFF_ZIP
PNM
PS
GIF
JP2
WEBP
LPDF
DEFAULT
SPIX
)
type Pix struct {
cPix *C.PIX // exported C.PIX so it can be used with other cgo wrap packages
closed bool
lock sync.Mutex
}
func (p *Pix) CPIX() *C.PIX {
return p.cPix
}
// GetDimensions returns the dimensions in Width, Height, Depth, Error format
func (p *Pix) GetDimensions() (int32, int32, int32, error) {
p.lock.Lock()
defer p.lock.Unlock()
var w, h, d int32
cW := C.l_int32(w)
cH := C.l_int32(h)
cD := C.l_int32(d)
if !p.closed {
code := C.pixGetDimensions(p.cPix, &cW, &cH, &cD)
if code != 0 {
return 0, 0, 0, errors.New("could not get dimensions")
}
}
return int32(cW), int32(cH), int32(cD), nil
}
func (p *Pix) Close() {
p.lock.Lock()
defer p.lock.Unlock()
if !p.closed {
// LEPT_DLL extern void pixDestroy ( PIX **ppix );
C.pixDestroy(&p.cPix)
C.free(unsafe.Pointer(p.cPix))
p.closed = true
}
}
// WriteFile saves to disk the current pix in the given format
func (p *Pix) WriteFile(filename string, format ImageType) error {
cFilename := C.CString(filename)
defer C.free(unsafe.Pointer(cFilename))
cFormat := C.l_int32(format)
// create new PIX
code := C.pixWrite(cFilename, p.cPix, cFormat)
if code != 0 {
return errors.New("could not write PIX to given filename: " + filename + " (format: " + strconv.Itoa(int(format)) + ")")
}
return nil
}
// EncodedBytes will return a byte array holding the data from PIX in the given format
func (p *Pix) EncodedBytes(format ImageType) ([]byte, error) {
var memory []byte
memPtr := C.uglycast(unsafe.Pointer(&(memory)))
var i int64
sizePtr := C.size_t(i)
cFormat := C.l_int32(format)
code := C.pixWriteMem(&memPtr, &sizePtr, p.cPix, cFormat)
if code != 0 {
return nil, errors.New("Cannot write type to given memory. WriteMem returned: " + strconv.Itoa(int(code)))
}
data := C.GoBytes(unsafe.Pointer(memPtr), C.int(sizePtr))
C.free(unsafe.Pointer(memPtr))
return data, nil
}
// LEPT_DLL extern PIX * pixRead ( const char *filename );
// NewPixFromFile creates a new Pix from given filename
func NewPixFromFile(filename string) (*Pix, error) {
cFilename := C.CString(filename)
defer C.free(unsafe.Pointer(cFilename))
// create new PIX
CPIX := C.pixRead(cFilename)
if CPIX == nil {
return nil, errors.New("could not create PIX from given filename")
}
// all done
pix := &Pix{
cPix: CPIX,
}
return pix, nil
}
// NewPixReadMem creates a new Pix instance from a byte array
func NewPixReadMem(image *[]byte) (*Pix, error) {
//ptr := (*C.l_uint8)(*C.uchar)(unsafe.Pointer(&(*image)[0]))
ptr := C.uglycast(unsafe.Pointer(&(*image)[0]))
CPIX := C.pixReadMem(ptr, C.size_t(len(*image)))
if CPIX == nil {
return nil, errors.New("Cannot create PIX from given image data")
}
pix := &Pix{
cPix: CPIX,
}
return pix, nil
}