2 * MonochromeBitmapSource.cpp
5 * Created by Christian Brunschen on 12/05/2008.
6 * Copyright 2008 Google UK. All rights reserved.
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
21 #include "MonochromeBitmapSource.h"
22 #include "BlackPointEstimator.h"
23 #include "ReaderException.h"
26 #define LUMINANCE_BITS (5)
27 #define LUMINANCE_SHIFT (8 - LUMINANCE_BITS)
28 #define LUMINANCE_BUCKETS (1 << LUMINANCE_BITS)
32 MonochromeBitmapSource::MonochromeBitmapSource() :
33 blackPoint_(numeric_limits<unsigned char>::max()),
34 lastEstimationMethod_(BlackPointEstimationMethod_None),
35 lastEstimationArgument_(-1) {
39 bool MonochromeBitmapSource::isBlack(size_t x, size_t y) {
40 return getPixel(x, y) < blackPoint_;
43 Ref<BitArray> MonochromeBitmapSource::getBlackRow(size_t y,
47 Ref<BitArray> result(row ? row : new BitArray(getWidth));
51 valarray<unsigned char> pixelRow(getWidth);
52 for (size_t i = 0; i < getWidth; i++) {
53 pixelRow[i] = getPixel(startX + i, y);
56 // If the current decoder calculated the blackPoint based on one row,
57 // assume we're trying to decode a 1D barcode, and apply some sharpening.
58 if (lastEstimationMethod_ == BlackPointEstimationMethod_RowSampling) {
59 unsigned int left = pixelRow[0];
60 unsigned int center = pixelRow[1];
61 for (size_t i = 1; i < getWidth - 1; i++) {
62 unsigned int right = pixelRow[i+1];
63 // Simple -1 4 -1 box filter with a weight of 2
64 unsigned int luminance = ((center << 2) - left - right) >> 1;
65 if (luminance < blackPoint_) {
72 for (size_t i = 0; i < getWidth; i++) {
73 if (pixelRow[i] < blackPoint_) {
82 void MonochromeBitmapSource::
83 estimateBlackPoint(BlackPointEstimationMethod method, int arg) {
84 size_t width = getWidth();
85 size_t height = getHeight();
86 if (method != lastEstimationMethod_ || arg != lastEstimationArgument_) {
87 valarray<int> histogram(LUMINANCE_BUCKETS);
88 if (method == BlackPointEstimationMethod_2D) {
89 size_t minDimension = width < height ? width : height;
90 size_t startX = (width - minDimension) >> 1;
91 size_t startY = (height - minDimension) >> 1;
92 for (size_t n = 0; n < minDimension; n++) {
93 unsigned char pixel = getPixel(startX + n, startY + n);
94 histogram[pixel >> LUMINANCE_SHIFT]++;
96 } else if (method == BlackPointEstimationMethod_RowSampling) {
97 if (arg < 0 || arg >= (int)height) {
98 throw new IllegalArgumentException
99 ("black point estimation argument out of range");
101 size_t y = static_cast<size_t> (arg);
102 for (size_t x = 0; x < width; x++) {
103 histogram[getPixel(x, y) >> LUMINANCE_SHIFT]++;
106 throw new IllegalArgumentException
107 ("unknown black point estimation method");
110 blackPoint_ = BlackPointEstimator::estimate(histogram) << LUMINANCE_SHIFT;
111 lastEstimationMethod_ = method;
112 lastEstimationArgument_ = arg;
116 BlackPointEstimationMethod MonochromeBitmapSource::getLastEstimationMethod() {
117 return lastEstimationMethod_;