fckeuspy-go/vendor/github.com/makiuchi-d/gozxing/planar_yuv_luminance_source.go
2025-09-28 21:03:39 +02:00

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]
}
}
}