Changed the order of the BaseMonochromeBitmapSource constructor arguments to be width...
[zxing.git] / android / src / com / google / zxing / client / android / YUVMonochromeBitmapSource.java
1 /*
2  * Copyright (C) 2008 ZXing authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.google.zxing.client.android;
18
19 import android.graphics.Bitmap;
20 import android.graphics.Rect;
21 import com.google.zxing.common.BaseMonochromeBitmapSource;
22
23 /**
24  * This object implements MonochromeBitmapSource around an array of YUV data, giving you the option
25  * to crop to a rectangle within the full data. This can be used to exclude superfluous pixels
26  * around the perimeter and speed up decoding.
27  *
28  * @author Sean Owen
29  * @author Daniel Switkin
30  */
31 public final class YUVMonochromeBitmapSource extends BaseMonochromeBitmapSource {
32
33   private final byte[] mYUVData;
34   private final int mDataWidth;
35   private final int mCropTop;
36   private final int mCropLeft;
37
38   /**
39    * Builds an object around a YUV buffer from the camera. The image is not cropped.
40    *
41    * @param yuvData    A byte array of planar Y data, followed by interleaved U and V
42    * @param dataWidth  The width of the Y data
43    * @param dataHeight The height of the Y data
44    */
45   public YUVMonochromeBitmapSource(byte[] yuvData, int dataWidth, int dataHeight) {
46     this(yuvData, dataWidth, dataHeight, 0, 0, dataHeight, dataWidth);
47   }
48
49   /**
50    * Builds an object around a YUV buffer from the camera. THe image is cropped and only
51    * that part of the image is evaluated.
52    *
53    * @param yuvData    A byte array of planar Y data, followed by interleaved U and V
54    * @param dataWidth  The width of the Y data
55    * @param dataHeight The height of the Y data
56    * @param crop       The rectangle within the yuvData to expose to MonochromeBitmapSource users
57    */
58   public YUVMonochromeBitmapSource(byte[] yuvData, int dataWidth, int dataHeight, Rect crop) {
59     this(yuvData, dataWidth, dataHeight, crop.top, crop.left, crop.bottom, crop.right);
60   }
61
62   /**
63    * Builds an object around a YUV buffer from the camera. The image is cropped and only 
64    * that part of the image is evaluated.
65    *
66    * @param yuvData    A byte array of planar Y data, followed by interleaved U and V
67    * @param dataWidth  The width of the Y data
68    * @param dataHeight The height of the Y data
69    * @param cropTop    Top coordinate of rectangle to crop
70    * @param cropLeft   Left coordinate of rectangle to crop
71    * @param cropBottom Bottom coordinate of rectangle to crop
72    * @param cropRight  Right coordinate of rectangle to crop
73    */
74   public YUVMonochromeBitmapSource(byte[] yuvData,
75                                    int dataWidth,
76                                    int dataHeight,
77                                    int cropTop,
78                                    int cropLeft,
79                                    int cropBottom,
80                                    int cropRight) {
81     super(cropRight - cropLeft, cropBottom - cropTop);
82     if (cropRight - cropLeft > dataWidth || cropBottom - cropTop > dataHeight) {
83       throw new IllegalArgumentException();
84     }
85     mYUVData = yuvData;
86     mDataWidth = dataWidth;
87     this.mCropTop = cropTop;
88     this.mCropLeft = cropLeft;
89   }
90
91   /**
92    * The Y channel is stored as planar data at the head of the array, so we just ignore the
93    * interleavd U and V which follow it.
94    *
95    * @param x The x coordinate to fetch within crop
96    * @param y The y coordinate to fetch within crop
97    * @return The luminance as an int, from 0-255
98    */
99   @Override
100   protected int getLuminance(int x, int y) {
101     return mYUVData[(y + mCropTop) * mDataWidth + x + mCropLeft] & 0xff;
102   }
103
104   @Override
105   protected int[] getLuminanceRow(int y, int[] row) {
106     int width = getWidth();
107     if (row == null || row.length < width) {
108       row = new int[width];
109     }
110     int offset = (y + mCropTop) * mDataWidth + mCropLeft;
111     byte[] yuvData = mYUVData;
112     for (int x = 0; x < width; x++) {
113       row[x] = yuvData[offset + x] & 0xff;
114     }
115     return row;
116   }
117
118   @Override
119   protected int[] getLuminanceColumn(int x, int[] column) {
120     int height = getHeight();
121     if (column == null || column.length < height) {
122       column = new int[height];
123     }
124     int dataWidth = mDataWidth;
125     int offset = mCropTop * dataWidth + mCropLeft + x;
126     byte[] yuvData = mYUVData;
127     for (int y = 0; y < height; y++) {
128       column[y] = yuvData[offset] & 0xff;
129       offset += dataWidth;
130     }
131     return column;
132   }
133
134   /**
135    * Create a greyscale Android Bitmap from the YUV data based on the crop rectangle.
136    *
137    * @return An 8888 bitmap.
138    */
139   public Bitmap renderToBitmap() {
140     int width = getWidth();
141     int height = getHeight();
142     int[] pixels = new int[width * height];
143     byte[] yuvData = mYUVData;
144     for (int y = 0, base = mCropTop * mDataWidth + mCropLeft; y < height; y++, base += mDataWidth) {
145       for (int x = 0; x < width; x++) {
146         int grey = yuvData[base + x] & 0xff;
147         pixels[y * width + x] = (0xff << 24) | (grey << 16) | (grey << 8) | grey;
148       }
149     }
150
151     Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
152     bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
153     return bitmap;
154   }
155
156 }