Standardize and update all copyright statements to name "ZXing authors" as suggested...
[zxing.git] / android / src / com / google / zxing / client / android / RGBMonochromeBitmapSource.java
1 /*
2  * Copyright 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 com.google.zxing.common.BaseMonochromeBitmapSource;
21
22 /**
23  * This object implements MonochromeBitmapSource around an Android Bitmap.
24  *
25  * @author dswitkin@google.com (Daniel Switkin)
26  * @author srowen@google.com (Sean Owen)
27  */
28 final class RGBMonochromeBitmapSource extends BaseMonochromeBitmapSource {
29
30   private final Bitmap image;
31   private final int[] rgbRow;
32   private int cachedRow;
33
34   RGBMonochromeBitmapSource(Bitmap image) {
35     this.image = image;
36     rgbRow = new int[image.getWidth()];
37     cachedRow = -1;
38   }
39
40   public int getHeight() {
41     return image.height();
42   }
43
44   public int getWidth() {
45     return image.width();
46   }
47
48   /**
49    * An optimized approximation of a more proper conversion from RGB to luminance which
50    * only uses shifts.
51    */
52   public int getLuminance(int x, int y) {
53     int pixel;
54     if (cachedRow == y) {
55       pixel = rgbRow[x];
56     } else {
57       pixel = image.getPixel(x, y);
58     }
59
60     // Instead of multiplying by 306, 601, 117, we multiply by 256, 512, 256, so that
61     // the multiplies can be implemented as shifts.
62     //
63     // Really, it's:
64     //
65     // return ((((pixel >> 16) & 0xFF) << 8) +
66     //         (((pixel >>  8) & 0xFF) << 9) +
67     //         (( pixel        & 0xFF) << 8)) >> 10;
68     //
69     // That is, we're replacing the coefficients in the original with powers of two,
70     // which can be implemented as shifts, even though changing the coefficients slightly
71     // corrupts the conversion. Not significant for our purposes.
72     return (((pixel & 0x00FF0000) >> 16) +
73             ((pixel & 0x0000FF00) >>  7) +
74              (pixel & 0x000000FF       )) >> 2;
75   }
76
77   public void cacheRowForLuminance(int y) {
78     if (y != cachedRow) {
79       int width = image.width();
80       image.getPixels(rgbRow, 0, width, 0, y, width, 1);
81       cachedRow = y;
82     }
83   }
84
85 }