21# include "config_auto.h"
28#if defined(USE_OPENCL)
32#include <allheaders.h>
50 , estimated_res_(300) {
65 return pix_ ==
nullptr;
77 int bytes_per_pixel,
int bytes_per_line) {
78 int bpp = bytes_per_pixel * 8;
82 Image pix = pixCreate(width, height, bpp == 24 ? 32 : bpp);
83 l_uint32 *data = pixGetData(pix);
84 int wpl = pixGetWpl(pix);
87 for (
int y = 0;
y < height; ++
y, data += wpl, imagedata += bytes_per_line) {
88 for (
int x = 0;
x < width; ++
x) {
89 if (imagedata[
x / 8] & (0x80 >> (
x % 8))) {
90 CLEAR_DATA_BIT(data,
x);
92 SET_DATA_BIT(data,
x);
100 for (
int y = 0;
y < height; ++
y, data += wpl, imagedata += bytes_per_line) {
101 for (
int x = 0;
x < width; ++
x) {
102 SET_DATA_BYTE(data,
x, imagedata[
x]);
109 for (
int y = 0;
y < height; ++
y, imagedata += bytes_per_line) {
110 for (
int x = 0;
x < width; ++
x, ++data) {
111 SET_DATA_BYTE(data, COLOR_RED, imagedata[3 *
x]);
112 SET_DATA_BYTE(data, COLOR_GREEN, imagedata[3 *
x + 1]);
113 SET_DATA_BYTE(data, COLOR_BLUE, imagedata[3 *
x + 2]);
120 for (
int y = 0;
y < height; ++
y, imagedata += bytes_per_line, data += wpl) {
121 for (
int x = 0;
x < width; ++
x) {
122 data[
x] = (imagedata[
x * 4] << 24) | (imagedata[
x * 4 + 1] << 16) |
123 (imagedata[
x * 4 + 2] << 8) | imagedata[
x * 4 + 3];
129 tprintf(
"Cannot convert RAW image to Pix with bpp = %d\n", bpp);
164 if (
pix_ !=
nullptr) {
173 if (depth > 1 && depth < 8) {
174 pix_ = pixConvertTo8(src,
false);
178 depth = pixGetDepth(
pix_);
189 Image pix_binary =
nullptr;
190 Image pix_thresholds =
nullptr;
196 pix_binary = original.
copy();
198 return std::make_tuple(
true,
nullptr, pix_binary,
nullptr);
205 l_int32 pix_w, pix_h;
206 pixGetDimensions(pix_grey, &pix_w, &pix_h,
nullptr);
208 bool thresholding_debug;
210 if (thresholding_debug) {
211 tprintf(
"\nimage width: %d height: %d ppi: %d\n", pix_w, pix_h,
yres_);
216 double window_size_factor;
218 window_size = window_size_factor *
yres_;
219 window_size = std::max(7, window_size);
220 window_size = std::min(pix_w < pix_h ? pix_w - 3 : pix_h - 3, window_size);
221 int half_window_size = window_size / 2;
226 nx = std::max(1, (pix_w + 125) / 250);
227 ny = std::max(1, (pix_h + 125) / 250);
228 auto xrat = pix_w / nx;
229 auto yrat = pix_h / ny;
230 if (xrat < half_window_size + 2) {
231 nx = pix_w / (half_window_size + 2);
233 if (yrat < half_window_size + 2) {
234 ny = pix_h / (half_window_size + 2);
239 kfactor = std::max(0.0, kfactor);
241 if (thresholding_debug) {
242 tprintf(
"window size: %d kfactor: %.3f nx:%d ny: %d\n", window_size, kfactor, nx, ny);
245 r = pixSauvolaBinarizeTiled(pix_grey, half_window_size, kfactor, nx, ny,
246 (PIX**)pix_thresholds,
250 double tile_size_factor;
252 tile_size = tile_size_factor *
yres_;
253 tile_size = std::max(16, tile_size);
256 double smooth_size_factor;
258 &smooth_size_factor);
259 smooth_size_factor = std::max(0.0, smooth_size_factor);
260 smooth_size = smooth_size_factor *
yres_;
261 int half_smooth_size = smooth_size / 2;
263 double score_fraction;
266 if (thresholding_debug) {
267 tprintf(
"tile size: %d smooth_size: %d score_fraction: %.2f\n", tile_size, smooth_size, score_fraction);
270 r = pixOtsuAdaptiveThreshold(pix_grey, tile_size, tile_size,
271 half_smooth_size, half_smooth_size,
273 (PIX**)pix_thresholds,
278 return std::make_tuple(ok, pix_grey, pix_binary, pix_thresholds);
294 *pix = original.
copy();
296 if (pixGetColormap(original)) {
299 pixRemoveColormap(original, REMOVE_CMAP_BASED_ON_SRC);
300 int depth = pixGetDepth(without_cmap);
301 if (depth > 1 && depth < 8) {
302 tmp = pixConvertTo8(without_cmap,
false);
304 tmp = without_cmap.
copy();
329 int width = pixGetWidth(pix_grey);
330 int height = pixGetHeight(pix_grey);
331 std::vector<int> thresholds;
332 std::vector<int> hi_values;
333 OtsuThreshold(pix_grey, 0, 0, width, height, thresholds, hi_values);
335 Image pix_thresholds = pixCreate(width, height, 8);
336 int threshold = thresholds[0] > 0 ? thresholds[0] : 128;
337 pixSetAllArbitrary(pix_thresholds, threshold);
338 return pix_thresholds;
358 Image cropped = pixClipRectangle(
pix_, box,
nullptr);
370 int depth = pixGetDepth(pix);
371 if (depth != 8 || pixGetColormap(pix)) {
373 auto tmp = pixConvert24To32(pix);
377 auto result = pixConvertTo8(pix,
false);
386 std::vector<int> thresholds;
387 std::vector<int> hi_values;
390 thresholds, hi_values);
394 if (num_channels == 4 && od.selectedDeviceIsOpenCL() &&
rect_top_ == 0 &&
rect_left_ == 0) {
395 od.ThresholdRectToPixOCL((
unsigned char *)pixGetData(src_pix), num_channels,
396 pixGetWpl(src_pix) * 4, &thresholds[0], &hi_values[0], out_pix ,
411 const std::vector<int> &hi_values,
Image *pix)
const {
413 uint32_t *pixdata = pixGetData(*pix);
414 int wpl = pixGetWpl(*pix);
415 int src_wpl = pixGetWpl(src_pix);
416 uint32_t *srcdata = pixGetData(src_pix);
417 pixSetXRes(*pix, pixGetXRes(src_pix));
418 pixSetYRes(*pix, pixGetYRes(src_pix));
420 const uint32_t *linedata = srcdata + (
y +
rect_top_) * src_wpl;
421 uint32_t *pixline = pixdata +
y * wpl;
423 bool white_result =
true;
424 for (
int ch = 0;
ch < num_channels; ++
ch) {
425 int pixel = GET_DATA_BYTE(linedata, (
x +
rect_left_) * num_channels +
ch);
426 if (hi_values[
ch] >= 0 && (pixel > thresholds[
ch]) == (hi_values[
ch] == 0)) {
427 white_result =
false;
432 CLEAR_DATA_BIT(pixline,
x);
434 SET_DATA_BIT(pixline,
x);
void tprintf(const char *format,...)
int OtsuThreshold(Image src_pix, int left, int top, int width, int height, std::vector< int > &thresholds, std::vector< int > &hi_values)
bool GetBoolVariable(const char *name, bool *value) const
bool GetDoubleVariable(const char *name, double *value) const
virtual Image GetPixRectThresholds()
int pix_wpl_
Words per line of pix_.
virtual void GetImageSizes(int *left, int *top, int *width, int *height, int *imagewidth, int *imageheight)
bool IsFullImage() const
Return true if we are processing the full image.
bool IsEmpty() const
Return true if no image has been set.
void SetImage(const unsigned char *imagedata, int width, int height, int bytes_per_pixel, int bytes_per_line)
int estimated_res_
Resolution estimate from text size.
virtual std::tuple< bool, Image, Image, Image > Threshold(TessBaseAPI *api, ThresholdMethod method)
virtual ~ImageThresholder()
void SetRectangle(int left, int top, int width, int height)
virtual void Init()
Common initialization shared between SetImage methods.
void OtsuThresholdRectToPix(Image src_pix, Image *out_pix) const
int scale_
Scale factor from original image.
int pix_channels_
Number of 8-bit channels in pix_.
int yres_
y pixels/inch in source image.
int image_width_
Width of source pix_.
virtual Image GetPixRectGrey()
void ThresholdRectToPix(Image src_pix, int num_channels, const std::vector< int > &thresholds, const std::vector< int > &hi_values, Image *pix) const
virtual bool ThresholdToPix(Image *pix)
Returns false on error.
bool IsBinary() const
Returns true if the source image is binary.
int image_height_
Height of source pix_.
virtual void Clear()
Destroy the Pix if there is one, freeing memory.