下面列出了怎么用com.google.zxing.LuminanceSource的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* 条形码解码
*
* @param imgPath
* @return String
*/
public static String decode(String imgPath) {
BufferedImage image = null;
Result result = null;
try {
image = ImageIO.read(new File(imgPath));
if (image == null) {
System.out.println("the decode image may be not exit.");
}
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
result = new MultiFormatReader().decode(bitmap, null);
return result.getText();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public LuminanceSource rotateCounterClockwise() {
int sourceWidth = image.getWidth();
int sourceHeight = image.getHeight();
// Rotate 90 degrees counterclockwise.
AffineTransform transform = new AffineTransform(0.0, -1.0, 1.0, 0.0, 0.0, sourceWidth);
// Note width/height are flipped since we are rotating 90 degrees.
BufferedImage rotatedImage = new BufferedImage(sourceHeight, sourceWidth, BufferedImage.TYPE_BYTE_GRAY);
// Draw the original image into rotated, via transformation
Graphics2D g = rotatedImage.createGraphics();
g.drawImage(image, transform, null);
g.dispose();
// Maintain the cropped region, but rotate it too.
int width = getWidth();
return new BufferedImageLuminanceSource(rotatedImage, top, sourceWidth - (left + width), getHeight(), width);
}
/**
* 读二维码并输出携带的信息
*/
public static void readQrCode(InputStream inputStream) throws IOException {
//从输入流中获取字符串信息
BufferedImage image = ImageIO.read(inputStream);
//将图像转换为二进制位图源
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
Result result = null;
try {
result = reader.decode(bitmap);
} catch (ReaderException e) {
e.printStackTrace();
}
System.out.println(result.getText());
}
/**
* 条形码解码
*
* @param imgPath
* @return String
*/
public static String decode(String imgPath) {
BufferedImage image = null;
Result result = null;
try {
image = ImageIO.read(new File(imgPath));
if (image == null) {
System.out.println("the decode image may be not exit.");
}
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
result = new MultiFormatReader().decode(bitmap, null);
return result.getText();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 二维码解码
*
* @param imgPath
* @return String
*/
public static String decode2(String imgPath) {
BufferedImage image = null;
Result result = null;
try {
image = ImageIO.read(new File(imgPath));
if (image == null) {
System.out.println("the decode image may be not exit.");
}
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
hints.put(DecodeHintType.CHARACTER_SET, "GBK");
result = new MultiFormatReader().decode(bitmap, hints);
return result.getText();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
// TODO Auto-generated method stub
if (mDialog.isShowing())
return;
LuminanceSource source = new PlanarYUVLuminanceSource(data, mWidth, mHeight, mLeft, mTop, mAreaWidth, mAreaHeight, false);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(
source));
Result result;
try {
result = mMultiFormatReader.decode(bitmap, null);
if (result != null) {
mDialog.setTitle("Result");
mDialog.setMessage(result.getText());
mDialog.show();
}
} catch (NotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public BitMatrix getBlackMatrix()
{
if (e != null)
{
return e;
}
LuminanceSource luminancesource = getLuminanceSource();
if (luminancesource.getWidth() >= 40 && luminancesource.getHeight() >= 40)
{
byte abyte0[] = luminancesource.getMatrix();
int i = luminancesource.getWidth();
int j = luminancesource.getHeight();
int k = i >> 3;
if ((i & 7) != 0)
{
k++;
}
int l = j >> 3;
if ((j & 7) != 0)
{
l++;
}
int ai[][] = a(abyte0, k, l, i, j);
BitMatrix bitmatrix = new BitMatrix(i, j);
a(abyte0, k, l, i, j, ai, bitmatrix);
e = bitmatrix;
} else
{
e = super.getBlackMatrix();
}
return e;
}
@Override
public LuminanceSource rotateCounterClockwise45() {
int width = getWidth();
int height = getHeight();
int oldCenterX = left + width / 2;
int oldCenterY = top + height / 2;
// Rotate 45 degrees counterclockwise.
AffineTransform transform = AffineTransform.getRotateInstance(MINUS_45_IN_RADIANS, oldCenterX, oldCenterY);
int sourceDimension = Math.max(image.getWidth(), image.getHeight());
BufferedImage rotatedImage = new BufferedImage(sourceDimension, sourceDimension, BufferedImage.TYPE_BYTE_GRAY);
// Draw the original image into rotated, via transformation
Graphics2D g = rotatedImage.createGraphics();
g.drawImage(image, transform, null);
g.dispose();
int halfDimension = Math.max(width, height) / 2;
int newLeft = Math.max(0, oldCenterX - halfDimension);
int newTop = Math.max(0, oldCenterY - halfDimension);
int newRight = Math.min(sourceDimension - 1, oldCenterX + halfDimension);
int newBottom = Math.min(sourceDimension - 1, oldCenterY + halfDimension);
return new BufferedImageLuminanceSource(rotatedImage, newLeft, newTop, newRight - newLeft, newBottom - newTop);
}
/**
* 读取二维码
* @param file 二维码源
* @throws Exception
*/
private static void readCode(File file) throws Exception{
BufferedImage encodedBufferedImage = ImageIO.read(file) ;
LuminanceSource source = new BufferedImageLuminanceSource(encodedBufferedImage);
Result result = new QRCodeReader().decode(new BinaryBitmap(new HybridBinarizer(source)));
System.out.println(result.getText());
}
@Override
public BitArray getBlackRow(int y, BitArray row) throws NotFoundException {
LuminanceSource source = getLuminanceSource();
int width = source.getWidth();
if (row == null || row.getSize() < width) {
row = new BitArray(width);
} else {
row.clear();
}
initArrays(width);
byte[] localLuminances = source.getRow(y, luminances);
int[] localBuckets = buckets;
for (int x = 0; x < width; x++) {
localBuckets[(localLuminances[x] & 0xff) >> LUMINANCE_SHIFT]++;
}
int blackPoint = estimateBlackPoint(localBuckets);
if (width < 3) {
// Special case for very small images
for (int x = 0; x < width; x++) {
if ((localLuminances[x] & 0xff) < blackPoint) {
row.set(x);
}
}
} else {
int left = localLuminances[0] & 0xff;
int center = localLuminances[1] & 0xff;
for (int x = 1; x < width - 1; x++) {
int right = localLuminances[x + 1] & 0xff;
// A simple -1 4 -1 box filter with a weight of 2.
if (((center * 4) - left - right) / 2 < blackPoint) {
row.set(x);
}
left = center;
center = right;
}
}
return row;
}
/**
* Calculates the final BitMatrix once for all requests. This could be called once from the
* constructor instead, but there are some advantages to doing it lazily, such as making
* profiling easier, and not doing heavy lifting when callers don't expect it.
*/
@Override
public BitMatrix getBlackMatrix() throws NotFoundException {
if (matrix != null) {
return matrix;
}
LuminanceSource source = getLuminanceSource();
int width = source.getWidth();
int height = source.getHeight();
if (width >= MINIMUM_DIMENSION && height >= MINIMUM_DIMENSION) {
byte[] luminances = source.getMatrix();
int subWidth = width >> BLOCK_SIZE_POWER;
if ((width & BLOCK_SIZE_MASK) != 0) {
subWidth++;
}
int subHeight = height >> BLOCK_SIZE_POWER;
if ((height & BLOCK_SIZE_MASK) != 0) {
subHeight++;
}
int[][] blackPoints = calculateBlackPoints(luminances, subWidth, subHeight, width, height);
BitMatrix newMatrix = new BitMatrix(width, height, 1);
calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, newMatrix);
matrix = newMatrix;
} else {
// If the image is too small, fall back to the global histogram approach.
matrix = super.getBlackMatrix();
}
return matrix;
}
@Nullable
public static Result decodeLuminanceSource(@NonNull final MultiFormatReader reader,
@NonNull final LuminanceSource luminanceSource) throws ReaderException {
try {
return reader.decodeWithState(new BinaryBitmap(new HybridBinarizer(luminanceSource)));
} catch (final NotFoundException e) {
return reader.decodeWithState(
new BinaryBitmap(new HybridBinarizer(luminanceSource.invert())));
} finally {
reader.reset();
}
}
@Override
public LuminanceSource rotateCounterClockwise45() {
int width = getWidth();
int height = getHeight();
int oldCenterX = left + width / 2;
int oldCenterY = top + height / 2;
// Rotate 45 degrees counterclockwise.
AffineTransform transform = AffineTransform.getRotateInstance(MINUS_45_IN_RADIANS, oldCenterX, oldCenterY);
int sourceDimension = Math.max(image.getWidth(), image.getHeight());
BufferedImage rotatedImage = new BufferedImage(sourceDimension, sourceDimension, BufferedImage.TYPE_BYTE_GRAY);
// Draw the original image into rotated, via transformation
Graphics2D g = rotatedImage.createGraphics();
g.drawImage(image, transform, null);
g.dispose();
int halfDimension = Math.max(width, height) / 2;
int newLeft = Math.max(0, oldCenterX - halfDimension);
int newTop = Math.max(0, oldCenterY - halfDimension);
int newRight = Math.min(sourceDimension - 1, oldCenterX + halfDimension);
int newBottom = Math.min(sourceDimension - 1, oldCenterY + halfDimension);
return new BufferedImageLuminanceSource(rotatedImage, newLeft, newTop, newRight - newLeft, newBottom - newTop);
}
@Override
public BitArray getBlackRow(int y, BitArray row) throws NotFoundException {
LuminanceSource source = getLuminanceSource();
int width = source.getWidth();
if (row == null || row.getSize() < width) {
row = new BitArray(width);
} else {
row.clear();
}
initArrays(width);
byte[] localLuminances = source.getRow(y, luminances);
int[] localBuckets = buckets;
for (int x = 0; x < width; x++) {
localBuckets[(localLuminances[x] & 0xff) >> LUMINANCE_SHIFT]++;
}
int blackPoint = estimateBlackPoint(localBuckets);
if (width < 3) {
// Special case for very small images
for (int x = 0; x < width; x++) {
if ((localLuminances[x] & 0xff) < blackPoint) {
row.set(x);
}
}
} else {
int left = localLuminances[0] & 0xff;
int center = localLuminances[1] & 0xff;
for (int x = 1; x < width - 1; x++) {
int right = localLuminances[x + 1] & 0xff;
// A simple -1 4 -1 box filter with a weight of 2.
if (((center * 4) - left - right) / 2 < blackPoint) {
row.set(x);
}
left = center;
center = right;
}
}
return row;
}
@Override
public BitArray getBlackRow(int y, BitArray row) throws NotFoundException {
LuminanceSource source = getLuminanceSource();
int width = source.getWidth();
if (row == null || row.getSize() < width) {
row = new BitArray(width);
} else {
row.clear();
}
initArrays(width);
byte[] localLuminances = source.getRow(y, luminances);
int[] localBuckets = buckets;
for (int x = 0; x < width; x++) {
int pixel = localLuminances[x] & 0xff;
localBuckets[pixel >> LUMINANCE_SHIFT]++;
}
int blackPoint = estimateBlackPoint(localBuckets);
int left = localLuminances[0] & 0xff;
int center = localLuminances[1] & 0xff;
for (int x = 1; x < width - 1; x++) {
int right = localLuminances[x + 1] & 0xff;
// A simple -1 4 -1 box filter with a weight of 2.
int luminance = ((center * 4) - left - right) / 2;
if (luminance < blackPoint) {
row.set(x);
}
left = center;
center = right;
}
return row;
}
@Override
public BitArray getBlackRow(int y, BitArray row) throws NotFoundException {
LuminanceSource source = getLuminanceSource();
int width = source.getWidth();
if (row == null || row.getSize() < width) {
row = new BitArray(width);
} else {
row.clear();
}
initArrays(width);
byte[] localLuminances = source.getRow(y, luminances);
int[] localBuckets = buckets;
for (int x = 0; x < width; x++) {
localBuckets[(localLuminances[x] & 0xff) >> LUMINANCE_SHIFT]++;
}
int blackPoint = estimateBlackPoint(localBuckets);
if (width < 3) {
// Special case for very small images
for (int x = 0; x < width; x++) {
if ((localLuminances[x] & 0xff) < blackPoint) {
row.set(x);
}
}
} else {
int left = localLuminances[0] & 0xff;
int center = localLuminances[1] & 0xff;
for (int x = 1; x < width - 1; x++) {
int right = localLuminances[x + 1] & 0xff;
// A simple -1 4 -1 box filter with a weight of 2.
if (((center * 4) - left - right) / 2 < blackPoint) {
row.set(x);
}
left = center;
center = right;
}
}
return row;
}
/**
* Calculates the final BitMatrix once for all requests. This could be called once from the
* constructor instead, but there are some advantages to doing it lazily, such as making
* profiling easier, and not doing heavy lifting when callers don't expect it.
*/
@Override
public BitMatrix getBlackMatrix() throws NotFoundException {
if (matrix != null) {
return matrix;
}
LuminanceSource source = getLuminanceSource();
int width = source.getWidth();
int height = source.getHeight();
if (width >= MINIMUM_DIMENSION && height >= MINIMUM_DIMENSION) {
byte[] luminances = source.getMatrix();
int subWidth = width >> BLOCK_SIZE_POWER;
if ((width & BLOCK_SIZE_MASK) != 0) {
subWidth++;
}
int subHeight = height >> BLOCK_SIZE_POWER;
if ((height & BLOCK_SIZE_MASK) != 0) {
subHeight++;
}
int[][] blackPoints = calculateBlackPoints(luminances, subWidth, subHeight, width, height);
BitMatrix newMatrix = new BitMatrix(width, height);
calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, newMatrix);
matrix = newMatrix;
} else {
// If the image is too small, fall back to the global histogram approach.
matrix = super.getBlackMatrix();
}
return matrix;
}
private void onScanImageResult(Intent intent) {
Uri inputFile = (intent.getData());
Bitmap bitmap;
try {
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
try (InputStream inputStream = getContentResolver().openInputStream(inputFile)) {
bitmap = BitmapFactory.decodeStream(inputStream, null, bmOptions);
}
int[] intArray = new int[bitmap.getWidth() * bitmap.getHeight()];
bitmap.getPixels(intArray, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
LuminanceSource source = new RGBLuminanceSource(bitmap.getWidth(), bitmap.getHeight(), intArray);
BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source));
Reader reader = new MultiFormatReader();
Result result = reader.decode(binaryBitmap);
GoogleAuthInfo info = GoogleAuthInfo.parseUri(result.getText());
VaultEntry entry = new VaultEntry(info);
startEditEntryActivity(CODE_ADD_ENTRY, entry, true);
} catch (NotFoundException | IOException | ChecksumException | FormatException | GoogleAuthInfoException e) {
e.printStackTrace();
Dialogs.showErrorDialog(this, R.string.unable_to_read_qrcode, e);
}
}
/**
* Calculates the final BitMatrix once for all requests. This could be
* called once from the constructor instead, but there are some advantages
* to doing it lazily, such as making profiling easier, and not doing heavy
* lifting when callers don't expect it.
*/
@Override
public BitMatrix getBlackMatrix() throws NotFoundException {
if (matrix != null) {
return matrix;
}
LuminanceSource source = getLuminanceSource();
int width = source.getWidth();
int height = source.getHeight();
if (width >= MINIMUM_DIMENSION && height >= MINIMUM_DIMENSION) {
byte[] luminances = source.getMatrix();
int subWidth = width >> BLOCK_SIZE_POWER;
if ((width & BLOCK_SIZE_MASK) != 0) {
subWidth++;
}
int subHeight = height >> BLOCK_SIZE_POWER;
if ((height & BLOCK_SIZE_MASK) != 0) {
subHeight++;
}
int[][] blackPoints = calculateBlackPoints(luminances, subWidth, subHeight, width, height);
BitMatrix newMatrix = new BitMatrix(width, height);
calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, newMatrix);
matrix = newMatrix;
} else {
// If the image is too small, fall back to the global histogram
// approach.
matrix = super.getBlackMatrix();
}
return matrix;
}
private static Observable<Result> resolve(LuminanceSource source, boolean failWhenNotFound) {
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
try {
return Observable.just(reader.decode(bitmap, TRY_HARDER));
} catch (NotFoundException | ChecksumException | FormatException e) {
if (failWhenNotFound) {
return Observable.error(e);
}
} finally {
reader.reset();
}
return Observable.empty();
}
@Override
public BitArray getBlackRow(int y, BitArray row) throws NotFoundException {
LuminanceSource source = getLuminanceSource();
int width = source.getWidth();
if (row == null || row.getSize() < width) {
row = new BitArray(width);
} else {
row.clear();
}
initArrays(width);
byte[] localLuminances = source.getRow(y, luminances);
int[] localBuckets = buckets;
for (int x = 0; x < width; x++) {
localBuckets[(localLuminances[x] & 0xff) >> LUMINANCE_SHIFT]++;
}
int blackPoint = estimateBlackPoint(localBuckets);
if (width < 3) {
// Special case for very small images
for (int x = 0; x < width; x++) {
if ((localLuminances[x] & 0xff) < blackPoint) {
row.set(x);
}
}
} else {
int left = localLuminances[0] & 0xff;
int center = localLuminances[1] & 0xff;
for (int x = 1; x < width - 1; x++) {
int right = localLuminances[x + 1] & 0xff;
// A simple -1 4 -1 box filter with a weight of 2.
if (((center * 4) - left - right) / 2 < blackPoint) {
row.set(x);
}
left = center;
center = right;
}
}
return row;
}
public BitMatrix getBlackMatrix()
{
LuminanceSource luminancesource = getLuminanceSource();
int i = luminancesource.getWidth();
int j = luminancesource.getHeight();
BitMatrix bitmatrix = new BitMatrix(i, j);
a(i);
int ai[] = e;
for (int k = 1; k < 5; k++)
{
byte abyte1[] = luminancesource.getRow((j * k) / 5, d);
int l1 = (i << 2) / 5;
for (int i2 = i / 5; i2 < l1; i2++)
{
int j2 = (0xff & abyte1[i2]) >> 3;
ai[j2] = 1 + ai[j2];
}
}
int l = a(ai);
byte abyte0[] = luminancesource.getMatrix();
for (int i1 = 0; i1 < j; i1++)
{
int j1 = i1 * i;
for (int k1 = 0; k1 < i; k1++)
{
if ((0xff & abyte0[j1 + k1]) < l)
{
bitmatrix.set(k1, i1);
}
}
}
return bitmatrix;
}
protected LuminanceSource createSource(SourceData sourceData) {
if (this.cropRect == null) {
return null;
} else {
return sourceData.createSource();
}
}
@Override
public BitArray getBlackRow(int y, BitArray row) throws NotFoundException {
LuminanceSource source = getLuminanceSource();
int width = source.getWidth();
if (row == null || row.getSize() < width) {
row = new BitArray(width);
} else {
row.clear();
}
initArrays(width);
byte[] localLuminances = source.getRow(y, luminances);
int[] localBuckets = buckets;
for (int x = 0; x < width; x++) {
int pixel = localLuminances[x] & 0xff;
localBuckets[pixel >> LUMINANCE_SHIFT]++;
}
int blackPoint = estimateBlackPoint(localBuckets);
int left = localLuminances[0] & 0xff;
int center = localLuminances[1] & 0xff;
for (int x = 1; x < width - 1; x++) {
int right = localLuminances[x + 1] & 0xff;
// A simple -1 4 -1 box filter with a weight of 2.
int luminance = ((center * 4) - left - right) / 2;
if (luminance < blackPoint) {
row.set(x);
}
left = center;
center = right;
}
return row;
}
/**
* Calculates the final BitMatrix once for all requests. This could be called once from the
* constructor instead, but there are some advantages to doing it lazily, such as making
* profiling easier, and not doing heavy lifting when callers don't expect it.
*/
@Override
public BitMatrix getBlackMatrix() throws NotFoundException {
if (matrix != null) {
return matrix;
}
LuminanceSource source = getLuminanceSource();
int width = source.getWidth();
int height = source.getHeight();
if (width >= MINIMUM_DIMENSION && height >= MINIMUM_DIMENSION) {
byte[] luminances = source.getMatrix();
int subWidth = width >> BLOCK_SIZE_POWER;
if ((width & BLOCK_SIZE_MASK) != 0) {
subWidth++;
}
int subHeight = height >> BLOCK_SIZE_POWER;
if ((height & BLOCK_SIZE_MASK) != 0) {
subHeight++;
}
int[][] blackPoints = calculateBlackPoints(luminances, subWidth, subHeight, width, height);
BitMatrix newMatrix = new BitMatrix(width, height);
calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, newMatrix);
matrix = newMatrix;
} else {
// If the image is too small, fall back to the global histogram approach.
matrix = super.getBlackMatrix();
}
return matrix;
}
public Result[] zxing( Mat inputImage ) throws ChecksumException, FormatException {
int w = inputImage.width();
int h = inputImage.height();
Mat southEast;
if (mBugRotate) {
southEast = inputImage.submat(h-h/4 , h , 0 , w/2 - h/4 );
} else {
southEast = inputImage.submat(0, h / 4, w / 2 + h / 4, w);
}
Bitmap bMap = Bitmap.createBitmap(southEast.width(), southEast.height(), Bitmap.Config.ARGB_8888);
org.opencv.android.Utils.matToBitmap(southEast, bMap);
southEast.release();
int[] intArray = new int[bMap.getWidth()*bMap.getHeight()];
//copy pixel data from the Bitmap into the 'intArray' array
bMap.getPixels(intArray, 0, bMap.getWidth(), 0, 0, bMap.getWidth(), bMap.getHeight());
LuminanceSource source = new RGBLuminanceSource(bMap.getWidth(), bMap.getHeight(),intArray);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result[] results = {};
try {
results = qrCodeMultiReader.decodeMultiple(bitmap);
}
catch (NotFoundException ignored) {
}
return results;
}
public LuminanceSource rotateCounterClockwise() {
int sourceWidth = image.getWidth();
int sourceHeight = image.getHeight();
AffineTransform transform = new AffineTransform(0.0, -1.0, 1.0, 0.0, 0.0, sourceWidth);
BufferedImage rotatedImage = new BufferedImage(sourceHeight, sourceWidth, BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g = rotatedImage.createGraphics();
g.drawImage(image, transform, null);
g.dispose();
int width = getWidth();
return new BufferedImageLuminanceSource(rotatedImage, top, sourceWidth - (left + width), getHeight(), width);
}
public BitArray getBlackRow(int i, BitArray bitarray)
{
int j = 1;
LuminanceSource luminancesource = getLuminanceSource();
int k = luminancesource.getWidth();
byte abyte0[];
int ai[];
if (bitarray == null || bitarray.getSize() < k)
{
bitarray = new BitArray(k);
} else
{
bitarray.clear();
}
a(k);
abyte0 = luminancesource.getRow(i, d);
ai = e;
for (int l = 0; l < k; l++)
{
int j2 = (0xff & abyte0[l]) >> 3;
ai[j2] = 1 + ai[j2];
}
int i1 = a(ai);
int j1 = 0xff & abyte0[0];
int k1 = 0xff & abyte0[j];
int l1 = j1;
while (j < k - 1)
{
int i2 = 0xff & abyte0[j + 1];
if ((k1 << 2) - l1 - i2 >> 1 < i1)
{
bitarray.set(j);
}
j++;
l1 = k1;
k1 = i2;
}
return bitarray;
}
/**
* Calculates the final BitMatrix once for all requests. This could be called once from the
* constructor instead, but there are some advantages to doing it lazily, such as making
* profiling easier, and not doing heavy lifting when callers don't expect it.
*/
@Override
public BitMatrix getBlackMatrix() throws NotFoundException {
if (matrix != null) {
return matrix;
}
LuminanceSource source = getLuminanceSource();
int width = source.getWidth();
int height = source.getHeight();
if (width >= MINIMUM_DIMENSION && height >= MINIMUM_DIMENSION) {
byte[] luminances = source.getMatrix();
int subWidth = width >> BLOCK_SIZE_POWER;
if ((width & BLOCK_SIZE_MASK) != 0) {
subWidth++;
}
int subHeight = height >> BLOCK_SIZE_POWER;
if ((height & BLOCK_SIZE_MASK) != 0) {
subHeight++;
}
int[][] blackPoints = calculateBlackPoints(luminances, subWidth, subHeight, width, height);
BitMatrix newMatrix = new BitMatrix(width, height);
calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, newMatrix);
matrix = newMatrix;
} else {
// If the image is too small, fall back to the global histogram approach.
matrix = super.getBlackMatrix();
}
return matrix;
}
@Override
public BitArray getBlackRow(int y, BitArray row) throws NotFoundException {
LuminanceSource source = getLuminanceSource();
int width = source.getWidth();
if (row == null || row.getSize() < width) {
row = new BitArray(width);
} else {
row.clear();
}
initArrays(width);
byte[] localLuminances = source.getRow(y, luminances);
int[] localBuckets = buckets;
for (int x = 0; x < width; x++) {
localBuckets[(localLuminances[x] & 0xff) >> LUMINANCE_SHIFT]++;
}
int blackPoint = estimateBlackPoint(localBuckets);
if (width < 3) {
// Special case for very small images
for (int x = 0; x < width; x++) {
if ((localLuminances[x] & 0xff) < blackPoint) {
row.set(x);
}
}
} else {
int left = localLuminances[0] & 0xff;
int center = localLuminances[1] & 0xff;
for (int x = 1; x < width - 1; x++) {
int right = localLuminances[x + 1] & 0xff;
// A simple -1 4 -1 box filter with a weight of 2.
if (((center * 4) - left - right) / 2 < blackPoint) {
row.set(x);
}
left = center;
center = right;
}
}
return row;
}