forked from makiuchi-d/gozxing
-
Notifications
You must be signed in to change notification settings - Fork 0
/
planar_yuv_luminance_source.go
143 lines (122 loc) · 3.85 KB
/
planar_yuv_luminance_source.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
package gozxing
import (
"errors"
"fmt"
)
const thumbnailScaleFactor = 2
type PlanarYUVLuminanceSource struct {
LuminanceSourceBase
yuvData []byte
dataWidth int
dataHeight int
left int
top int
}
func NewPlanarYUVLuminanceSource(yuvData []byte,
dataWidth, dataHeight, left, top, width, height int,
reverseHorizontal bool) (LuminanceSource, error) {
if left+width > dataWidth || top+height > dataHeight {
return nil, errors.New("IllegalArgumentException: Crop rectangle does not fit within image data")
}
yuvsrc := &PlanarYUVLuminanceSource{
LuminanceSourceBase{width, height},
yuvData,
dataWidth,
dataHeight,
left,
top,
}
if reverseHorizontal {
yuvsrc.reverseHorizontal(width, height)
}
return yuvsrc, nil
}
func (this *PlanarYUVLuminanceSource) Invert() LuminanceSource {
return LuminanceSourceInvert(this)
}
func (this *PlanarYUVLuminanceSource) String() string {
return LuminanceSourceString(this)
}
func (this *PlanarYUVLuminanceSource) GetRow(y int, row []byte) ([]byte, error) {
if y < 0 || y >= this.GetHeight() {
return nil, fmt.Errorf("IllegalArgumentException: Requested row is outside the image: %v", y)
}
width := this.GetWidth()
if row == nil || len(row) < width {
row = make([]byte, width)
}
offset := (y+this.top)*this.dataWidth + this.left
copy(row, this.yuvData[offset:offset+width])
return row, nil
}
func (this *PlanarYUVLuminanceSource) GetMatrix() []byte {
width := this.GetWidth()
height := this.GetHeight()
// If the caller asks for the entire underlying image, save the copy and give them the
// original data. The docs specifically warn that result.length must be ignored.
if width == this.dataWidth && height == this.dataHeight {
return this.yuvData
}
area := width * height
matrix := make([]byte, area)
inputOffset := this.top*this.dataWidth + this.left
// If the width matches the full width of the underlying data, perform a single copy.
if width == this.dataWidth {
copy(matrix, this.yuvData[inputOffset:inputOffset+area])
return matrix
}
// Otherwise copy one cropped row at a time.
for y := 0; y < height; y++ {
outputOffset := y * width
copy(matrix[outputOffset:], this.yuvData[inputOffset:inputOffset+width])
inputOffset += this.dataWidth
}
return matrix
}
func (this *PlanarYUVLuminanceSource) IsCropSupported() bool {
return true
}
func (this *PlanarYUVLuminanceSource) Crop(left, top, width, height int) (LuminanceSource, error) {
return NewPlanarYUVLuminanceSource(
this.yuvData,
this.dataWidth,
this.dataHeight,
this.left+left,
this.top+top,
width,
height,
false)
}
func (this *PlanarYUVLuminanceSource) RenderThumbnail() []int {
width := this.GetThumbnailWidth()
height := this.GetThumbnailHeight()
pixels := make([]int, width*height)
yuv := this.yuvData
inputOffset := this.top*this.dataWidth + this.left
for y := 0; y < height; y++ {
outputOffset := y * width
for x := 0; x < width; x++ {
grey := int(yuv[inputOffset+x*thumbnailScaleFactor]) & 0xff
pixels[outputOffset+x] = 0xFF000000 | (grey * 0x00010101)
}
inputOffset += this.dataWidth * thumbnailScaleFactor
}
return pixels
}
// GetThumbnailWidth return width of image from {@link #renderThumbnail()}
func (this *PlanarYUVLuminanceSource) GetThumbnailWidth() int {
return this.GetWidth() / thumbnailScaleFactor
}
// GetThumbnailHeight return height of image from {@link #renderThumbnail()}
func (this *PlanarYUVLuminanceSource) GetThumbnailHeight() int {
return this.GetHeight() / thumbnailScaleFactor
}
func (this *PlanarYUVLuminanceSource) reverseHorizontal(width, height int) {
yuvData := this.yuvData
for y, rowStart := 0, this.top*this.dataWidth+this.left; y < height; y, rowStart = y+1, rowStart+this.dataWidth {
middle := rowStart + width/2
for x1, x2 := rowStart, rowStart+width-1; x1 < middle; x1, x2 = x1+1, x2-1 {
yuvData[x1], yuvData[x2] = yuvData[x2], yuvData[x1]
}
}
}