diff --git a/android/src/com/google/zxing/client/android/PlanarYUVLuminanceSource.java b/android/src/com/google/zxing/client/android/AbstractPlanarYUVLuminanceSource.java similarity index 79% rename from android/src/com/google/zxing/client/android/PlanarYUVLuminanceSource.java rename to android/src/com/google/zxing/client/android/AbstractPlanarYUVLuminanceSource.java index 994809110..2d0122478 100644 --- a/android/src/com/google/zxing/client/android/PlanarYUVLuminanceSource.java +++ b/android/src/com/google/zxing/client/android/AbstractPlanarYUVLuminanceSource.java @@ -16,8 +16,6 @@ package com.google.zxing.client.android; -import com.google.zxing.LuminanceSource; - import android.graphics.Bitmap; /** @@ -26,18 +24,21 @@ import android.graphics.Bitmap; * superfluous pixels around the perimeter and speed up decoding. * * It works for any pixel format where the Y channel is planar and appears first, including - * YCbCr_420_SP and YCbCr_422_SP. Any subsequent color data will be ignored. + * YCbCr_420_SP and YCbCr_422_SP. * * @author dswitkin@google.com (Daniel Switkin) */ -public final class PlanarYUVLuminanceSource extends BaseLuminanceSource { +public abstract class AbstractPlanarYUVLuminanceSource extends BaseLuminanceSource { + + protected static final int OPAQUE_ALPHA = 0xFF000000; + private final byte[] yuvData; private final int dataWidth; private final int dataHeight; private final int left; private final int top; - public PlanarYUVLuminanceSource(byte[] yuvData, int dataWidth, int dataHeight, int left, int top, + AbstractPlanarYUVLuminanceSource(byte[] yuvData, int dataWidth, int dataHeight, int left, int top, int width, int height) { super(width, height); @@ -53,7 +54,7 @@ public final class PlanarYUVLuminanceSource extends BaseLuminanceSource { } @Override - public byte[] getRow(int y, byte[] row) { + public final byte[] getRow(int y, byte[] row) { if (y < 0 || y >= getHeight()) { throw new IllegalArgumentException("Requested row is outside the image: " + y); } @@ -67,7 +68,7 @@ public final class PlanarYUVLuminanceSource extends BaseLuminanceSource { } @Override - public byte[] getMatrix() { + public final byte[] getMatrix() { int width = getWidth(); int height = getHeight(); @@ -98,27 +99,34 @@ public final class PlanarYUVLuminanceSource extends BaseLuminanceSource { } @Override - public boolean isCropSupported() { + public final boolean isCropSupported() { return true; } @Override - public LuminanceSource crop(int left, int top, int width, int height) { - return new PlanarYUVLuminanceSource(yuvData, dataWidth, dataHeight, left, top, width, height); - } - - @Override - public int getDataWidth() { + public final int getDataWidth() { return dataWidth; } @Override - public int getDataHeight() { + public final int getDataHeight() { return dataHeight; } + protected final byte[] getYUVData() { + return yuvData; + } + + protected final int getLeft() { + return left; + } + + protected final int getTop() { + return top; + } + @Override - public Bitmap renderCroppedGreyscaleBitmap() { + public final Bitmap renderCroppedGreyscaleBitmap() { int width = getWidth(); int height = getHeight(); int[] pixels = new int[width * height]; @@ -129,7 +137,7 @@ public final class PlanarYUVLuminanceSource extends BaseLuminanceSource { int outputOffset = y * width; for (int x = 0; x < width; x++) { int grey = yuv[inputOffset + x] & 0xff; - pixels[outputOffset + x] = (0xff000000) | (grey * 0x00010101); + pixels[outputOffset + x] = OPAQUE_ALPHA | (grey * 0x00010101); } inputOffset += dataWidth; } @@ -139,9 +147,4 @@ public final class PlanarYUVLuminanceSource extends BaseLuminanceSource { return bitmap; } - // Can't be implemented here, as the color representations vary. - @Override - public Bitmap renderFullColorBitmap(boolean halfSize) { - throw new UnsupportedOperationException(); - } } diff --git a/android/src/com/google/zxing/client/android/CameraManager.java b/android/src/com/google/zxing/client/android/CameraManager.java index 74f5a5709..dafa06642 100755 --- a/android/src/com/google/zxing/client/android/CameraManager.java +++ b/android/src/com/google/zxing/client/android/CameraManager.java @@ -285,8 +285,10 @@ final class CameraManager { Rect rect = getFramingRect(); switch (previewFormat) { case PixelFormat.YCbCr_420_SP: + return new PlanarYUV420LuminanceSource(data, width, height, rect.left, rect.top, + rect.width(), rect.height()); case PixelFormat.YCbCr_422_SP: - return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top, + return new PlanarYUV422LuminanceSource(data, width, height, rect.left, rect.top, rect.width(), rect.height()); default: // Handle some non-standard values: @@ -296,12 +298,12 @@ final class CameraManager { rect.width(), rect.height()); } else if (previewFormatString.equals("yuv420p")) { // Assume this is a synonym for YUV420SP -- note the lack of 's' - return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top, + return new PlanarYUV420LuminanceSource(data, width, height, rect.left, rect.top, rect.width(), rect.height()); - } - throw new IllegalArgumentException("Unsupported picture format: " + - previewFormat + '/' + previewFormatString); + } } + throw new IllegalArgumentException("Unsupported picture format: " + + previewFormat + '/' + previewFormatString); } /** diff --git a/android/src/com/google/zxing/client/android/InterleavedYUV422LuminanceSource.java b/android/src/com/google/zxing/client/android/InterleavedYUV422LuminanceSource.java index 0105b90e6..30dc9e1b8 100644 --- a/android/src/com/google/zxing/client/android/InterleavedYUV422LuminanceSource.java +++ b/android/src/com/google/zxing/client/android/InterleavedYUV422LuminanceSource.java @@ -171,7 +171,7 @@ public final class InterleavedYUV422LuminanceSource extends BaseLuminanceSource /** * @link http://en.wikipedia.org/wiki/YUV#Y.27UV444 */ - private static int yuvToRGB(int y, int u, int v) { + static int yuvToRGB(int y, int u, int v) { int c = y - 16; int d = u - 128; int e = v - 128; diff --git a/android/src/com/google/zxing/client/android/PlanarYUV420LuminanceSource.java b/android/src/com/google/zxing/client/android/PlanarYUV420LuminanceSource.java new file mode 100644 index 000000000..1ee3e8304 --- /dev/null +++ b/android/src/com/google/zxing/client/android/PlanarYUV420LuminanceSource.java @@ -0,0 +1,76 @@ +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.client.android; + +import android.graphics.Bitmap; +import com.google.zxing.LuminanceSource; + +public final class PlanarYUV420LuminanceSource extends AbstractPlanarYUVLuminanceSource { + + public PlanarYUV420LuminanceSource(byte[] yuvData, int dataWidth, int dataHeight, + int left, int top, int width, int height) { + super(yuvData, dataWidth, dataHeight, left, top, width, height); + } + + @Override + public LuminanceSource crop(int left, int top, int width, int height) { + return new PlanarYUV420LuminanceSource( + getYUVData(), getDataWidth(), getDataHeight(), left, top, width, height); + } + + @Override + public Bitmap renderFullColorBitmap(boolean halfSize) { + // TODO implement halfSize + int width = getWidth(); + int height = getHeight(); + int dataWidth = getDataWidth(); + byte[] yuv = getYUVData(); + int expectedYBytes = width * height; + int expectedUBytes = expectedYBytes >> 2; + int expectedVBytes = expectedYBytes >> 2; + int expectedBytes = expectedYBytes + expectedUBytes + expectedVBytes; + if (yuv.length != expectedBytes) { + throw new IllegalStateException("Expected " + expectedBytes + " bytes"); + } + + int[] pixels = new int[width * height]; + int inputYOffset = getTop() * getDataWidth() + getLeft(); + int uOffset = expectedYBytes; + int vOffset = expectedYBytes + expectedUBytes; + + for (int y = 0; y < height; y++) { + int outputOffset = y * width; + for (int x = 0; x < width; x++) { + int yOffset = inputYOffset + x; + int yDataRow = yOffset / dataWidth; + int yDataOffset = yOffset % dataWidth; + int uvOffset = ((yDataRow >> 1) * dataWidth + yDataOffset) >> 1; + int y1 = yuv[yOffset] & 0xFF; + int u = yuv[uOffset + uvOffset] & 0xFF; + int v = yuv[vOffset + uvOffset] & 0XFF; + pixels[outputOffset + x] = + OPAQUE_ALPHA | InterleavedYUV422LuminanceSource.yuvToRGB(y1, u, v); + } + inputYOffset += dataWidth; + } + + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + bitmap.setPixels(pixels, 0, width, 0, 0, width, height); + return bitmap; + } + +} diff --git a/android/src/com/google/zxing/client/android/PlanarYUV422LuminanceSource.java b/android/src/com/google/zxing/client/android/PlanarYUV422LuminanceSource.java new file mode 100644 index 000000000..c4007f918 --- /dev/null +++ b/android/src/com/google/zxing/client/android/PlanarYUV422LuminanceSource.java @@ -0,0 +1,40 @@ +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.client.android; + +import android.graphics.Bitmap; +import com.google.zxing.LuminanceSource; + +public final class PlanarYUV422LuminanceSource extends AbstractPlanarYUVLuminanceSource { + + public PlanarYUV422LuminanceSource(byte[] yuvData, int dataWidth, int dataHeight, + int left, int top, int width, int height) { + super(yuvData, dataWidth, dataHeight, left, top, width, height); + } + + @Override + public LuminanceSource crop(int left, int top, int width, int height) { + return new PlanarYUV422LuminanceSource( + getYUVData(), getDataWidth(), getDataHeight(), left, top, width, height); + } + + @Override + public Bitmap renderFullColorBitmap(boolean halfSize) { + throw new UnsupportedOperationException(); + } + +} \ No newline at end of file