mirror of
https://github.com/tesseract-ocr/tesseract.git
synced 2024-12-20 12:50:55 +08:00
367 lines
10 KiB
C++
367 lines
10 KiB
C++
|
/**********************************************************************
|
||
|
* File: scaleimg.cpp (Formerly scaleim.c)
|
||
|
* Description: Smart scaling of images.
|
||
|
* Author: Phil Cheatle
|
||
|
* Created: Wed Nov 18 16:12:03 GMT 1992
|
||
|
*
|
||
|
* (C) Copyright 1992, Hewlett-Packard Ltd.
|
||
|
** 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.
|
||
|
*
|
||
|
**********************************************************************/
|
||
|
|
||
|
/*************************************************************************
|
||
|
* This is really Sheelagh's code that I've hacked into a more usable form.
|
||
|
* You simply call scale_image() passing in source and target images. The target
|
||
|
* image should be empty, but created - in order to define the destination
|
||
|
* size.
|
||
|
*************************************************************************/
|
||
|
|
||
|
#include "mfcpch.h"
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include "fileerr.h"
|
||
|
#include "tprintf.h"
|
||
|
#include "grphics.h"
|
||
|
#include "img.h"
|
||
|
//#include "basefile.h"
|
||
|
#include "imgscale.h"
|
||
|
#include "scaleimg.h"
|
||
|
|
||
|
void scale_image( //scale an image
|
||
|
IMAGE &image, //source image
|
||
|
IMAGE &target_image //target image
|
||
|
) {
|
||
|
INT32 xsize, ysize, new_xsize, new_ysize;
|
||
|
IMAGELINE line, new_line;
|
||
|
int *hires, *lores, *oldhires, *oldlores;
|
||
|
int i, j, n, oldn, row, col;
|
||
|
int offset = 0; //not used here
|
||
|
float factor;
|
||
|
UINT8 curr_colour, new_colour;
|
||
|
int dummy = -1;
|
||
|
IMAGE image2; //horiz scaled image
|
||
|
|
||
|
xsize = image.get_xsize ();
|
||
|
ysize = image.get_ysize ();
|
||
|
new_xsize = target_image.get_xsize ();
|
||
|
new_ysize = target_image.get_ysize ();
|
||
|
if (new_ysize > new_xsize)
|
||
|
new_line.init (new_ysize);
|
||
|
else
|
||
|
new_line.init (new_xsize);
|
||
|
|
||
|
factor = (float) xsize / (float) new_xsize;
|
||
|
|
||
|
hires = (int *) calloc (xsize, sizeof (int));
|
||
|
lores = (int *) calloc (new_xsize, sizeof (int));
|
||
|
oldhires = (int *) calloc (xsize, sizeof (int));
|
||
|
oldlores = (int *) calloc (new_xsize, sizeof (int));
|
||
|
if ((hires == NULL) || (lores == NULL) || (oldhires == NULL)
|
||
|
|| (oldlores == NULL)) {
|
||
|
fprintf (stderr, "Calloc error in scale_image\n");
|
||
|
err_exit();
|
||
|
}
|
||
|
|
||
|
image2.create (new_xsize, ysize, image.get_bpp ());
|
||
|
|
||
|
oldn = 0;
|
||
|
/* do first row separately because hires[col-1] doesn't make sense here */
|
||
|
image.fast_get_line (0, 0, xsize, &line);
|
||
|
/* each line nominally begins with white */
|
||
|
curr_colour = 1;
|
||
|
n = 0;
|
||
|
for (i = 0; i < xsize; i++) {
|
||
|
new_colour = *(line.pixels + i);
|
||
|
if (new_colour != curr_colour) {
|
||
|
hires[n] = i;
|
||
|
n++;
|
||
|
curr_colour = new_colour;
|
||
|
}
|
||
|
}
|
||
|
if (offset != 0)
|
||
|
for (i = 0; i < n; i++)
|
||
|
hires[i] += offset;
|
||
|
|
||
|
if (n > new_xsize) {
|
||
|
tprintf ("Too many transitions (%d) on line 0\n", n);
|
||
|
scale_image_cop_out(image,
|
||
|
target_image,
|
||
|
factor,
|
||
|
hires,
|
||
|
lores,
|
||
|
oldhires,
|
||
|
oldlores);
|
||
|
return;
|
||
|
}
|
||
|
else if (n > 0)
|
||
|
dyn_prog (n, hires, lores, new_xsize, &dummy, &dummy, 0, factor);
|
||
|
else
|
||
|
lores[0] = new_xsize;
|
||
|
|
||
|
curr_colour = 1;
|
||
|
j = 0;
|
||
|
for (i = 0; i < new_xsize; i++) {
|
||
|
if (lores[j] == i) {
|
||
|
curr_colour = 1 - curr_colour;
|
||
|
j++;
|
||
|
}
|
||
|
*(new_line.pixels + i) = curr_colour;
|
||
|
}
|
||
|
image2.put_line (0, 0, new_xsize, &new_line, 0);
|
||
|
|
||
|
for (i = 0; i < n; i++) {
|
||
|
oldhires[i] = hires[i];
|
||
|
oldlores[i] = lores[i];
|
||
|
}
|
||
|
|
||
|
for (i = n; i < oldn; i++) {
|
||
|
oldhires[i] = 0;
|
||
|
oldlores[i] = 0;
|
||
|
}
|
||
|
oldn = n;
|
||
|
|
||
|
for (row = 1; row < ysize; row++) {
|
||
|
image.fast_get_line (0, row, xsize, &line);
|
||
|
/* each line nominally begins with white */
|
||
|
curr_colour = 1;
|
||
|
n = 0;
|
||
|
for (i = 0; i < xsize; i++) {
|
||
|
new_colour = *(line.pixels + i);
|
||
|
if (new_colour != curr_colour) {
|
||
|
hires[n] = i;
|
||
|
n++;
|
||
|
curr_colour = new_colour;
|
||
|
}
|
||
|
}
|
||
|
for (i = n; i < oldn; i++) {
|
||
|
hires[i] = 0;
|
||
|
lores[i] = 0;
|
||
|
}
|
||
|
if (offset != 0)
|
||
|
for (i = 0; i < n; i++)
|
||
|
hires[i] += offset;
|
||
|
|
||
|
if (n > new_xsize) {
|
||
|
tprintf ("Too many transitions (%d) on line %d\n", n, row);
|
||
|
scale_image_cop_out(image,
|
||
|
target_image,
|
||
|
factor,
|
||
|
hires,
|
||
|
lores,
|
||
|
oldhires,
|
||
|
oldlores);
|
||
|
return;
|
||
|
}
|
||
|
else if (n > 0)
|
||
|
dyn_prog(n, hires, lores, new_xsize, oldhires, oldlores, oldn, factor);
|
||
|
else
|
||
|
lores[0] = new_xsize;
|
||
|
|
||
|
curr_colour = 1;
|
||
|
j = 0;
|
||
|
for (i = 0; i < new_xsize; i++) {
|
||
|
if (lores[j] == i) {
|
||
|
curr_colour = 1 - curr_colour;
|
||
|
j++;
|
||
|
}
|
||
|
*(new_line.pixels + i) = curr_colour;
|
||
|
}
|
||
|
image2.put_line (0, row, new_xsize, &new_line, 0);
|
||
|
|
||
|
for (i = 0; i < n; i++) {
|
||
|
oldhires[i] = hires[i];
|
||
|
oldlores[i] = lores[i];
|
||
|
}
|
||
|
for (i = n; i < oldn; i++) {
|
||
|
oldhires[i] = 0;
|
||
|
oldlores[i] = 0;
|
||
|
}
|
||
|
oldn = n;
|
||
|
}
|
||
|
|
||
|
free(hires);
|
||
|
free(lores);
|
||
|
free(oldhires);
|
||
|
free(oldlores);
|
||
|
|
||
|
/* NOW DO THE VERTICAL SCALING from image2 to target_image*/
|
||
|
|
||
|
xsize = new_xsize;
|
||
|
factor = (float) ysize / (float) new_ysize;
|
||
|
offset = 0;
|
||
|
|
||
|
hires = (int *) calloc (ysize, sizeof (int));
|
||
|
lores = (int *) calloc (new_ysize, sizeof (int));
|
||
|
oldhires = (int *) calloc (ysize, sizeof (int));
|
||
|
oldlores = (int *) calloc (new_ysize, sizeof (int));
|
||
|
if ((hires == NULL) || (lores == NULL) || (oldhires == NULL)
|
||
|
|| (oldlores == NULL)) {
|
||
|
fprintf (stderr, "Calloc error in scale_image (vert)\n");
|
||
|
err_exit();
|
||
|
}
|
||
|
|
||
|
oldn = 0;
|
||
|
/* do first col separately because hires[col-1] doesn't make sense here */
|
||
|
image2.get_column (0, 0, ysize, &line, 0);
|
||
|
/* each line nominally begins with white */
|
||
|
curr_colour = 1;
|
||
|
n = 0;
|
||
|
for (i = 0; i < ysize; i++) {
|
||
|
new_colour = *(line.pixels + i);
|
||
|
if (new_colour != curr_colour) {
|
||
|
hires[n] = i;
|
||
|
n++;
|
||
|
curr_colour = new_colour;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (offset != 0)
|
||
|
for (i = 0; i < n; i++)
|
||
|
hires[i] += offset;
|
||
|
|
||
|
if (n > new_ysize) {
|
||
|
tprintf ("Too many transitions (%d) on column 0\n", n);
|
||
|
scale_image_cop_out(image,
|
||
|
target_image,
|
||
|
factor,
|
||
|
hires,
|
||
|
lores,
|
||
|
oldhires,
|
||
|
oldlores);
|
||
|
return;
|
||
|
}
|
||
|
else if (n > 0)
|
||
|
dyn_prog (n, hires, lores, new_ysize, &dummy, &dummy, 0, factor);
|
||
|
else
|
||
|
lores[0] = new_ysize;
|
||
|
|
||
|
curr_colour = 1;
|
||
|
j = 0;
|
||
|
for (i = 0; i < new_ysize; i++) {
|
||
|
if (lores[j] == i) {
|
||
|
curr_colour = 1 - curr_colour;
|
||
|
j++;
|
||
|
}
|
||
|
*(new_line.pixels + i) = curr_colour;
|
||
|
}
|
||
|
target_image.put_column (0, 0, new_ysize, &new_line, 0);
|
||
|
|
||
|
for (i = 0; i < n; i++) {
|
||
|
oldhires[i] = hires[i];
|
||
|
oldlores[i] = lores[i];
|
||
|
}
|
||
|
for (i = n; i < oldn; i++) {
|
||
|
oldhires[i] = 0;
|
||
|
oldlores[i] = 0;
|
||
|
}
|
||
|
oldn = n;
|
||
|
|
||
|
for (col = 1; col < xsize; col++) {
|
||
|
image2.get_column (col, 0, ysize, &line, 0);
|
||
|
/* each line nominally begins with white */
|
||
|
curr_colour = 1;
|
||
|
n = 0;
|
||
|
for (i = 0; i < ysize; i++) {
|
||
|
new_colour = *(line.pixels + i);
|
||
|
if (new_colour != curr_colour) {
|
||
|
hires[n] = i;
|
||
|
n++;
|
||
|
curr_colour = new_colour;
|
||
|
}
|
||
|
}
|
||
|
for (i = n; i < oldn; i++) {
|
||
|
hires[i] = 0;
|
||
|
lores[i] = 0;
|
||
|
}
|
||
|
|
||
|
if (offset != 0)
|
||
|
for (i = 0; i < n; i++)
|
||
|
hires[i] += offset;
|
||
|
|
||
|
if (n > new_ysize) {
|
||
|
tprintf ("Too many transitions (%d) on column %d\n", n, col);
|
||
|
scale_image_cop_out(image,
|
||
|
target_image,
|
||
|
factor,
|
||
|
hires,
|
||
|
lores,
|
||
|
oldhires,
|
||
|
oldlores);
|
||
|
return;
|
||
|
}
|
||
|
else if (n > 0)
|
||
|
dyn_prog(n, hires, lores, new_ysize, oldhires, oldlores, oldn, factor);
|
||
|
else
|
||
|
lores[0] = new_ysize;
|
||
|
|
||
|
curr_colour = 1;
|
||
|
j = 0;
|
||
|
for (i = 0; i < new_ysize; i++) {
|
||
|
if (lores[j] == i) {
|
||
|
curr_colour = 1 - curr_colour;
|
||
|
j++;
|
||
|
}
|
||
|
*(new_line.pixels + i) = curr_colour;
|
||
|
}
|
||
|
target_image.put_column (col, 0, new_ysize, &new_line, 0);
|
||
|
|
||
|
for (i = 0; i < n; i++) {
|
||
|
oldhires[i] = hires[i];
|
||
|
oldlores[i] = lores[i];
|
||
|
}
|
||
|
for (i = n; i < oldn; i++) {
|
||
|
oldhires[i] = 0;
|
||
|
oldlores[i] = 0;
|
||
|
}
|
||
|
oldn = n;
|
||
|
}
|
||
|
free(hires);
|
||
|
free(lores);
|
||
|
free(oldhires);
|
||
|
free(oldlores);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**********************************************************************
|
||
|
* scale_image_cop_out
|
||
|
*
|
||
|
* Cop-out of scale_image by doing it the easy way and free the data.
|
||
|
**********************************************************************/
|
||
|
|
||
|
void scale_image_cop_out( //scale an image
|
||
|
IMAGE &image, //source image
|
||
|
IMAGE &target_image, //target image
|
||
|
float factor, //scale factor
|
||
|
int *hires,
|
||
|
int *lores,
|
||
|
int *oldhires,
|
||
|
int *oldlores) {
|
||
|
INT32 xsize, ysize, new_xsize, new_ysize;
|
||
|
|
||
|
xsize = image.get_xsize ();
|
||
|
ysize = image.get_ysize ();
|
||
|
new_xsize = target_image.get_xsize ();
|
||
|
new_ysize = target_image.get_ysize ();
|
||
|
|
||
|
if (factor <= 0.5)
|
||
|
reduce_sub_image (&image, 0, 0, xsize, ysize,
|
||
|
&target_image, 0, 0, (INT32) (1.0 / factor), FALSE);
|
||
|
else if (factor >= 2)
|
||
|
enlarge_sub_image (&image, 0, 0, &target_image,
|
||
|
0, 0, new_xsize, new_ysize, (INT32) factor, FALSE);
|
||
|
else
|
||
|
copy_sub_image (&image, 0, 0, xsize, ysize, &target_image, 0, 0, FALSE);
|
||
|
free(hires);
|
||
|
free(lores);
|
||
|
free(oldhires);
|
||
|
free(oldlores);
|
||
|
}
|