Created
June 13, 2012 21:50
-
-
Save slodge/2926704 to your computer and use it in GitHub Desktop.
PlanarYUVLuminanceSource - for use with Mono4Android in-app scanning
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class PlanarYUVLuminanceSource : LuminanceSource | |
{ | |
private readonly sbyte[] yuvData; | |
private readonly int dataWidth; | |
private readonly int dataHeight; | |
private readonly int left; | |
private readonly int top; | |
public PlanarYUVLuminanceSource(sbyte[] yuvData, | |
int dataWidth, | |
int dataHeight, | |
int left, | |
int top, | |
int width, | |
int height, | |
bool reverseHorizontal) | |
: base(width, height) | |
{ | |
if (left + width > dataWidth || top + height > dataHeight) | |
{ | |
throw new IllegalArgumentException("Crop rectangle does not fit within image data."); | |
} | |
this.yuvData = yuvData; | |
this.dataWidth = dataWidth; | |
this.dataHeight = dataHeight; | |
this.left = left; | |
this.top = top; | |
if (reverseHorizontal) | |
{ | |
this.reverseHorizontal(width, height); | |
} | |
} | |
public override sbyte[] getRow(int y, sbyte[] row) | |
{ | |
if (y < 0 || y >= Height) | |
{ | |
throw new IllegalArgumentException("Requested row is outside the image: " + y); | |
} | |
int width = Width; | |
if (row == null || row.Length < width) | |
{ | |
row = new sbyte[width]; | |
} | |
int offset = (y + top) * dataWidth + left; | |
Array.Copy(yuvData, offset, row, 0, width); | |
return row; | |
} | |
public override sbyte[] Matrix | |
{ | |
get | |
{ | |
int width = Width; | |
int height = Height; | |
// 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 == dataWidth && height == dataHeight) | |
{ | |
return yuvData; | |
} | |
int area = width*height; | |
sbyte[] matrix = new sbyte[area]; | |
int inputOffset = top*dataWidth + left; | |
// If the width matches the full width of the underlying data, perform a single copy. | |
if (width == dataWidth) | |
{ | |
Array.Copy(yuvData, inputOffset, matrix, 0, area); | |
return matrix; | |
} | |
// Otherwise copy one cropped row at a time. | |
sbyte[] yuv = yuvData; | |
for (int y = 0; y < height; y++) | |
{ | |
int outputOffset = y*width; | |
Array.Copy(yuv, inputOffset, matrix, outputOffset, width); | |
inputOffset += dataWidth; | |
} | |
return matrix; | |
} | |
} | |
public override bool CropSupported | |
{ | |
get | |
{ | |
return true; | |
} | |
} | |
public override LuminanceSource crop(int left, int top, int width, int height) | |
{ | |
return new PlanarYUVLuminanceSource(yuvData, | |
dataWidth, | |
dataHeight, | |
this.left + left, | |
this.top + top, | |
width, | |
height, | |
false); | |
} | |
public Bitmap renderCroppedGreyscaleBitmap() | |
{ | |
int width = Width; | |
int height = Height; | |
int[] pixels = new int[width * height]; | |
sbyte[] yuv = yuvData; | |
int inputOffset = top * dataWidth + left; | |
for (int y = 0; y < height; y++) | |
{ | |
int outputOffset = y * width; | |
for (int x = 0; x < width; x++) | |
{ | |
int grey = yuv[inputOffset + x] & 0xff; | |
pixels[outputOffset + x] = (int)(0xFF000000 | (grey * 0x00010101)); | |
} | |
inputOffset += dataWidth; | |
} | |
Bitmap bitmap = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888); | |
bitmap.SetPixels(pixels, 0, width, 0, 0, width, height); | |
return bitmap; | |
} | |
private void reverseHorizontal(int width, int height) | |
{ | |
sbyte[] yuvData = this.yuvData; | |
for (int y = 0, rowStart = top * dataWidth + left; y < height; y++, rowStart += dataWidth) | |
{ | |
int middle = rowStart + width / 2; | |
for (int x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) | |
{ | |
sbyte temp = yuvData[x1]; | |
yuvData[x1] = yuvData[x2]; | |
yuvData[x2] = temp; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment