Technically split out YUV 4:2:0 and 4:2:2 support and tried implementing RGB conversion for 4:2:0

git-svn-id: https://zxing.googlecode.com/svn/trunk@1119 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2009-11-22 12:55:18 +00:00
parent f75a6ec766
commit 87b6b0ec66
5 changed files with 149 additions and 28 deletions

View file

@ -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();
}
}

View file

@ -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);
}
/**

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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();
}
}