143 lines
3.9 KiB
Go
143 lines
3.9 KiB
Go
package gozxing
|
|
|
|
import (
|
|
errors "golang.org/x/xerrors"
|
|
)
|
|
|
|
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, errors.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() []uint {
|
|
width := this.GetThumbnailWidth()
|
|
height := this.GetThumbnailHeight()
|
|
pixels := make([]uint, 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 := uint(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]
|
|
}
|
|
}
|
|
}
|