33 #include "config_auto.h"
36 #include "allheaders.h"
45 #define FIXED_COLOURS 32
53 0, 255, 76, 227, 151, 179, 28, 104,
54 149, 72, 215, 67, 53, 44, 156, 137,
55 110, 153, 79, 181, 166, 218, 55, 81,
56 129, 105, 179, 149, 168, 69, 84, 126
92 photo_interp = source.photo_interp;
94 bytespp = (bpp + 7) / 8;
95 lineskip = source.lineskip;
96 captured = source.captured;
100 image = source.image;
102 bufheight = source.bufheight;
104 reader = source.reader;
108 source.captured =
TRUE;
132 if (pixels ==
NULL) {
137 this->
capture (pixels, x, y, bits_per_pixel);
151 if (image !=
NULL && !captured) {
183 bpp = bits_per_pixel;
184 bps = bpp == 24 ? 8 : bpp;
186 bytespp = (bpp + 7) / 8;
219 return image[(ymax - 1 - y) * xdim + x];
221 return bpp4table[image[(ymax - 1 - y) * xdim + x / 2]][x & 1];
223 return bpp2table[image[(ymax - 1 - y) * xdim + x / 4]][x & 3];
225 return bpp1table[image[(ymax - 1 - y) * xdim + x / 8]][x & 7];
227 tprintf (
"Unexpected bits per pixel %d\n", bpp);
245 if (x <= 0 || y <= 0) {
249 if (bits_per_pixel != 1 && bits_per_pixel != 2 &&
250 bits_per_pixel != 4 && bits_per_pixel != 5 &&
251 bits_per_pixel != 6 && bits_per_pixel != 8 &&
252 bits_per_pixel != 16 && bits_per_pixel != 24 &&
253 bits_per_pixel != 32) {
291 if (xstart < 0 || ystart < 0 || xdest < 0 || ydest < 0)
294 xext = source->xsize;
295 if (xext > source->xsize - xstart)
297 xext = source->xsize - xstart;
298 if (xext > dest->xsize - xdest)
299 xext = dest->xsize - xdest;
301 yext = source->ysize;
302 if (yext > source->ysize - ystart)
304 yext = source->ysize - ystart;
305 if (yext > dest->ysize - ydest)
306 yext = dest->ysize - ydest;
307 if (xext <= 0 || yext <= 0)
310 srcppb = 8 / source->bpp;
311 if (source->bpp == dest->bpp || !adjust_grey)
314 shift = source->bps - dest->bps;
318 aligned = source->bpp == dest->bpp;
319 if (aligned && srcppb != 0) {
320 aligned = xstart % srcppb == 0
321 && xdest % srcppb == 0
322 && (xext % srcppb == 0 || xdest + xext == dest->xsize);
324 for (y = 0; y < yext; y++) {
328 yoffset = yext - y - 1;
336 memmove (dest->image + (dest->ymax - 1 - ydest - yoffset) * dest->xdim + xdest * 3, source->image + (source->ymax - 1 - ystart - yoffset) * source->xdim + xstart * 3, (
unsigned) bytesize);
339 memmove (dest->image + (dest->ymax - 1 - ydest - yoffset) * dest->xdim + xdest / srcppb, source->image + (source->ymax - 1 - ystart - yoffset) * source->xdim + xstart / srcppb, (
unsigned) bytesize);
346 else if (source->bpp < dest->bpp) {
347 source->
get_line (xstart, ystart + yoffset, xext, ©line, 0);
348 if (source->bpp <= shift
349 && (source->bpp == 1 || source->bpp == 4)) {
350 if (source->bpp == 1) {
351 for (pixel = 0, copy = copyline.
pixels; pixel < xext;
357 for (pixel = 0, copy = copyline.
pixels; pixel < xext;
360 *copy = (*copy << shift) | *copy;
364 for (pixel = 0, copy = copyline.
pixels; pixel < xext;
370 source->
get_line (xstart, ystart + yoffset, xext, ©line, 0);
371 if (source->bpp == 24) {
372 for (pixel = 0, copy = copyline.
pixels + 1; pixel < xext;
379 for (pixel = 0, copy = copyline.
pixels; pixel < xext;
384 dest->
put_line (xdest, ydest + yoffset, xext, ©line, 0);
415 inT32 xindex, yindex;
423 if (xstart < 0 || ystart < 0 || xdest < 0 || ydest < 0)
428 if (xext > source->xsize * scale - xstart)
430 xext = source->xsize * scale - xstart;
431 if (xext > dest->xsize - xdest)
432 xext = dest->xsize - xdest;
435 if (yext > source->ysize * scale - ystart)
436 yext = source->ysize * scale - ystart;
437 if (yext > dest->ysize - ydest)
438 yext = dest->ysize - ydest;
439 if (xext <= 0 || yext <= 0)
442 xindex = xstart % scale;
443 startxindex = xindex;
444 yindex = ystart % scale;
446 srcext = (xext + xindex + scale - 1) / scale;
450 shift = dest->bps - source->bps;
454 bigline.
init (xext * 3);
455 bigline.
bpp = dest->bpp == 24 ? source->bpp : dest->bpp;
457 for (yoffset = 0; yoffset < yext; ystart++) {
464 if (source->bpp == 24 && dest->bpp == 24) {
465 for (xoffset = 0, xindex = startxindex; xoffset < xext;
466 src += source->bytespp) {
467 xoffset += xscale - xindex;
469 xscale -= xoffset - xext;
470 for (; xindex < xscale; xindex++) {
472 *destpix++ = *(src + 1);
473 *destpix++ = *(src + 2);
479 if (source->bpp == 24)
481 for (xoffset = 0, xindex = startxindex; xoffset < xext;
482 src += source->bytespp) {
483 xoffset += xscale - xindex;
486 xscale -= xoffset - xext;
490 pixel = *src << shift;
492 pixel = *src >> (-shift);
493 for (; xindex < xscale; xindex++)
498 for (; yoffset < yext && yindex < scale; yindex++, yoffset++) {
499 dest->
put_line (xdest, ydest + yoffset, xext, &bigline, 0);
531 inT32 xindex, yindex;
540 if (xstart < 0 || ystart < 0 || xdest < 0 || ydest < 0)
543 xext = source->xsize;
544 if (xext > source->xsize - xstart)
546 xext = source->xsize - xstart;
547 if (xext > (dest->xsize - xdest) * scale)
548 xext = (dest->xsize - xdest) * scale;
550 yext = source->ysize;
551 if (yext > source->ysize - ystart)
553 yext = source->ysize - ystart;
554 if (yext > (dest->ysize - ydest) * scale)
555 yext = (dest->ysize - ydest) * scale;
556 if (xext <= 0 || yext <= 0)
559 xfactor = xext % scale;
563 destext = (xext + scale - 1) / scale;
566 shift = dest->bps - source->bps;
569 linesums =
new inT32[destext * source->bytespp];
571 for (yoffset = 0; yoffset < yext; ydest++) {
574 for (xindex = destext * source->bytespp - 1; xindex >= 0; xindex--)
575 linesums[xindex] = 0;
576 for (yindex = 0; yindex < scale
577 && ystart + yoffset < source->ysize; yindex += 3) {
578 source->
fast_get_line (xstart, ystart + yoffset, xext, ©line);
580 if (source->bpp == 24) {
581 for (xcoord = 1, sums = linesums; xcoord < destext;
582 xcoord++, sums += 3) {
583 for (xindex = 0; xindex < scale; xindex += 2) {
585 *(sums + 1) += *pixel++;
586 *(sums + 2) += *pixel++;
592 for (xindex = 0; xindex < xfactor; xindex += 2) {
594 *(sums + 1) += *pixel++;
595 *(sums + 2) += *pixel++;
600 for (xcoord = 1, sums = linesums; xcoord < destext;
602 for (xindex = 0; xindex < scale; xindex += 2) {
609 for (xindex = 0; xindex < xfactor; xindex += 2) {
617 yoffset -= yindex - scale;
619 copyline.
bpp = source->bpp;
622 divisor = ((yindex + 2) / 3) * ((scale + 1) / 2);
624 divisor <<= (-shift);
625 for (sums = linesums, xindex = (destext - 1) * source->bytespp;
626 xindex > 0; xindex--)
628 *pixel++ = (
uinT8) (*sums++ / divisor);
629 for (xindex = source->bytespp; xindex > 0; xindex--)
631 / (((yindex + 2) / 3) * ((xfactor + 1) / 2) << (-shift));
635 for (sums = linesums, xindex = (destext - 1) * source->bytespp;
636 xindex > 0; xindex--)
637 *pixel++ = (
uinT8) ((*sums++ << shift) / divisor);
639 for (xindex = source->bytespp; xindex > 0; xindex--)
641 *pixel++ = (*(sums++) << shift) / (((yindex + 2) / 3) * ((xfactor + 1) / 2));
644 dest->
put_line (xdest, ydest, destext, ©line, 0);
674 inT32 xindex, yindex;
683 if (xstart < 0 || ystart < 0 || xdest < 0 || ydest < 0)
686 xext = source->xsize;
687 if (xext > source->xsize - xstart)
689 xext = source->xsize - xstart;
690 if (xext > (dest->xsize - xdest) * scale)
691 xext = (dest->xsize - xdest) * scale;
693 yext = source->ysize;
694 if (yext > source->ysize - ystart)
696 yext = source->ysize - ystart;
697 if (yext > (dest->ysize - ydest) * scale)
698 yext = (dest->ysize - ydest) * scale;
699 if (xext <= 0 || yext <= 0)
702 xfactor = xext % scale;
706 destext = (xext + scale - 1) / scale;
709 shift = dest->bps - source->bps;
712 linesums =
new inT32[destext * source->bytespp];
714 for (yoffset = 0; yoffset < yext; ydest++) {
717 for (xindex = 0; xindex < (destext) * source->bytespp; xindex++)
718 linesums[xindex] = 0;
719 for (yindex = 0; yindex < scale && ystart + yoffset < source->ysize;
721 source->
fast_get_line (xstart, ystart + yoffset, xext, ©line);
723 if (source->bpp == 24) {
724 for (xcoord = 1, sums = linesums; xcoord < destext;
725 xcoord++, sums += 3) {
726 for (xindex = 0; xindex < scale; xindex++) {
728 *(sums + 1) += *pixel++;
729 *(sums + 2) += *pixel++;
732 for (xindex = 0; xindex < xfactor; xindex++) {
734 *(sums + 1) += *pixel++;
735 *(sums + 2) += *pixel++;
739 for (xcoord = 1, sums = linesums; xcoord < destext;
741 for (xindex = 0; xindex < scale; xindex++)
744 for (xindex = 0; xindex < xfactor; xindex++)
750 copyline.
set_bpp (source->bpp);
752 divisor = yindex * scale;
755 (
"Impossible:divisor=0!, yindex=%d, scale=%d, yoffset=%d,yext=%d\n",
756 yindex, scale, yoffset, yext);
760 divisor <<= (-shift);
762 for (sums = linesums, xindex = (destext - 1) * source->bytespp;
763 xindex > 0; xindex--)
764 *pixel++ = (
uinT8) ((div2 + *sums++) / divisor);
766 div2 = (yindex * xfactor << (-shift)) / 2;
767 for (xindex = source->bytespp; xindex > 0; xindex--)
769 (
uinT8) ((div2 + *sums++) / (yindex * xfactor << (-shift)));
774 for (sums = linesums, xindex = (destext - 1) * source->bytespp;
775 xindex > 0; xindex--)
776 *pixel++ = (
uinT8) ((div2 + (*sums++ << shift)) / divisor);
778 div2 = (yindex * xfactor) / 2;
779 for (xindex = source->bytespp; xindex > 0; xindex--)
781 (
uinT8) ((div2 + (*sums++ << shift)) / (yindex * xfactor));
785 dest->
put_line (xdest, ydest, destext, ©line, 0);
803 inT32 xindex, yindex;
807 bytespp = image->
get_bpp () == 24 ? 3 : 1;
811 mask = (1 << image->
get_bpp ()) - 1;
813 for (yindex = ysize - 1; yindex >= 0; yindex--) {
815 for (pixel = line.
pixels, xindex = xsize * bytespp; xindex > 0;
817 *pixel = (*pixel) ^ mask;
846 if (xstart < 0 || ystart < 0)
850 if (xext > source->
get_xsize () - xstart)
855 if (yext > source->
get_ysize () - ystart)
858 if (xext <= 0 || yext <= 0)
861 bytespp = source->
get_bpp () == 24 ? 3 : 1;
862 for (y = 0; y < yext; y++) {
865 for (pixel = xext * bytespp, copy = copyline.
pixels; pixel > 0;
904 if (xstart < 0 || ystart < 0 || xdest < 0 || ydest < 0)
908 if (xext > source->
get_xsize () - xstart)
915 if (yext > source->
get_ysize () - ystart)
920 if (xext <= 0 || yext <= 0)
924 srcppb = 8 / source->
get_bpp ();
928 colour_shift = 8 - dest->
get_bpp ();
930 for (y = 0; y < yext; y++) {
934 yoffset = yext - y - 1;
937 source->
get_line (xstart, ystart + yoffset, xext, ©line, 0);
938 for (pixel = 0, copy = copyline.
pixels; pixel < xext; pixel++) {
949 *copy = (*copy -
MIN_4BIT) << (-shift4);
951 *copy = (*copy -
MIN_4BIT) >> shift4;
955 *copy = (*copy -
MIN_6BIT) << (-shift6);
957 *copy = (*copy -
MIN_6BIT) >> shift6;
964 dest->
put_line (xdest, ydest + yoffset, xext, ©line, 0);
984 if (width > 0 && bpp > 4) {
987 linebuf->
pixels = image + xdim * (ymax - 1 - y) + x * bytespp;
991 this->
get_line (x, y, width, linebuf, 0);
1012 const uinT8 *unpacksrc;
1019 if (width > xsize - x)
1022 linebuf->
init (width + margins * bytespp * 2);
1025 src = image + xdim * (ymax - 1 - y);
1026 dest = linebuf->line;
1028 white = (1 << bpp) - 1;
1029 for (pixel = margins * bytespp; pixel > 0; pixel--) {
1036 memmove (dest, src, (
unsigned) width);
1038 else if (bpp == 4) {
1045 while (width >= 2) {
1048 *dest++ = *unpacksrc++;
1049 *dest++ = *unpacksrc++;
1057 else if (bpp == 2) {
1060 bit = (
inT8) (x % 4);
1063 if (width < pixperbyte)
1065 pixperbyte = (
inT8) width;
1068 for (; bit < pixperbyte; bit++)
1069 *dest++ = *unpacksrc++;
1070 width -= pixperbyte;
1077 bit = (
inT8) (x % 8);
1080 if (width < pixperbyte)
1082 pixperbyte = (
inT8) width;
1085 for (; bit < pixperbyte; bit++)
1086 *dest++ = *unpacksrc++;
1087 width -= pixperbyte;
1092 for (pixel = margins * bytespp; pixel > 0; pixel--) {
1123 if (height > ysize - y)
1125 linebuf->
init (height * bytespp + margins * bytespp * 2);
1127 src = image + xdim * (ymax - 1 - y);
1128 dest = linebuf->line;
1130 white = (1 << bpp) - 1;
1131 for (pixel = margins * bytespp; pixel > 0; pixel--) {
1137 for (; height > 0; --height) {
1139 *dest++ = *(src + 1);
1140 *dest++ = *(src + 2);
1146 for (; height > 0; --height) {
1151 else if (bpp == 4) {
1154 for (; height > 0; --height) {
1161 for (; height > 0; --height) {
1168 else if (bpp == 2) {
1171 bit = (
inT8) (x % 4);
1172 for (; height > 0; --height) {
1181 bit = (
inT8) (x % 8);
1182 for (; height > 0; --height) {
1189 for (pixel = margins * bytespp; pixel > 0; pixel--) {
1209 if (width > 0 && (bpp <= 4 || linebuf->pixels == linebuf->line))
1211 put_line (x, y, width, linebuf, 0);
1237 if (width > xsize - x)
1242 src = linebuf->
pixels + margins;
1244 dest = image + xdim * (ymax - 1 - y);
1246 if (linebuf->
bpp == 24) {
1252 if (bpp == 24 && linebuf->
bpp == 24) {
1253 dest += x * bytespp;
1255 memmove (dest, src - 1, (
unsigned) width);
1257 else if (bpp == 24) {
1259 dest += x * bytespp;
1270 if (linebuf->
bpp == 24) {
1279 memmove (dest, src, (
unsigned) width);
1281 else if (bpp == 4) {
1285 *dest++ |= *src & 0x0f;
1289 while (width >= 2) {
1292 pixel |= *src & 0x0f;
1302 else if (bpp == 2) {
1305 bit = (
inT8) (x % 4);
1307 pixel = *dest >> (8 - bit - bit);
1308 while (width >= 4) {
1309 for (; bit < 4; bit++) {
1319 for (bit = 0; bit < width; bit++) {
1324 pixel <<= (8 - bit - bit);
1326 pixel |= *dest & ((1 << (8 - bit - bit)) - 1);
1333 bit = (
inT8) (x % 8);
1335 pixel = *dest >> (8 - bit);
1336 while (width >= 8) {
1337 for (; bit < 8; bit++) {
1355 pixel <<= (8 - bit);
1357 pixel |= *dest & ((1 << (8 - bit)) - 1);
1386 if (height > ysize - y)
1391 src = linebuf->
pixels + margins;
1393 dest = image + xdim * (ymax - 1 - y);
1395 if (linebuf->
bpp == 24) {
1402 if (bpp == 24 && linebuf->
bpp == 24) {
1403 dest += x * bytesperpix;
1405 for (; height > 0; --height) {
1407 *(dest + 1) = *src++;
1408 *(dest + 2) = *src++;
1412 else if (bpp == 24) {
1414 dest += x * bytesperpix;
1415 for (; height > 0; --height) {
1418 *(dest + 1) = pixel;
1419 *(dest + 2) = pixel;
1425 for (; height > 0; --height) {
1431 else if (bpp == 4) {
1434 for (; height > 0; --height) {
1436 *dest |= *src & 0x0f;
1442 for (; height > 0; --height) {
1450 else if (bpp == 2) {
1452 bit = (
inT8) (x % 4);
1453 bit = 6 - bit - bit;
1454 pixel = ~(3 << bit);
1455 for (; height > 0; --height) {
1457 *dest = (*dest &
pixel) | ((*src & 3) << bit);
1464 bit = (
inT8) (x % 8);
1466 pixel = ~(1 << bit);
1467 for (; height > 0; --height) {
1469 *dest = (*dest &
pixel) | ((*src & 1) << bit);
1489 if (x < 0 || x >= xsize || y < 0 || y >= ysize || x + xext > xsize)
1491 ABORT,
"(%d+%d,%d)", x, xext, y);
1492 if (y < ymin || y >= ymax)
1505 Pix* pix = pixCreate(width, height, bpp == 24 ? 32 : bpp);
1506 l_uint32* data = pixGetData(pix);
1509 line.
init(width * 3);
1516 for (
int y = height - 1 ; y >= 0; --y) {
1517 this->
get_line(0, y, width, &line, 0);
1518 for (
int x = 0; x < width; ++x) {
1520 CLEAR_DATA_BIT(data, x);
1522 SET_DATA_BIT(data, x);
1524 data += pixGetWpl(pix);
1530 for (
int y = height - 1 ; y >= 0; --y) {
1531 this->
get_line(0, y, width, &line, 0);
1532 for (
int x = 0; x < width; ++x)
1533 SET_DATA_BYTE(data, x, line.
pixels[x]);
1534 data += pixGetWpl(pix);
1540 for (
int y = height - 1 ; y >= 0; --y) {
1541 this->
get_line(0, y, width, &line, 0);
1542 for (
int x = 0; x < width; ++x, ++data) {
1543 SET_DATA_BYTE(data, COLOR_RED, line[x][
RED_PIX]);
1544 SET_DATA_BYTE(data, COLOR_GREEN, line[x][
GREEN_PIX]);
1545 SET_DATA_BYTE(data, COLOR_BLUE, line[x][
BLUE_PIX]);
1551 tprintf(
"Cannot convert image to Pix with bpp = %d\n", bpp);
1563 Pix* pix =
const_cast<Pix*
>(src_pix);
1564 Pix* destroy_this_pix =
NULL;
1566 int depth = pixGetDepth(pix);
1567 if (depth > 1 && depth < 8) {
1569 destroy_this_pix = pixConvertTo8(pix,
false);
1570 pix = destroy_this_pix;
1571 depth = pixGetDepth(pix);
1573 int width = pixGetWidth(pix);
1574 int height = pixGetHeight(pix);
1575 const l_uint32* data = pixGetData(pix);
1576 this->
create(width, height, depth == 32 ? 24 : depth);
1582 line.
init(width * 3);
1590 for (
int y = height - 1 ; y >= 0; --y) {
1591 for (
int x = 0; x < width; ++x)
1592 line.
pixels[x] = GET_DATA_BIT((
void *)data, x) ^ 1;
1593 this->
put_line(0, y, width, &line, 0);
1594 data += pixGetWpl(pix);
1600 for (
int y = height - 1 ; y >= 0; --y) {
1601 for (
int x = 0; x < width; ++x)
1602 line.
pixels[x] = GET_DATA_BYTE((
void *)data, x);
1603 this->
put_line(0, y, width, &line, 0);
1604 data += pixGetWpl(pix);
1610 for (
int y = height - 1 ; y >= 0; --y) {
1611 for (
int x = 0; x < width; ++x, ++data) {
1612 line[x][
RED_PIX] = GET_DATA_BYTE((
void *)data, COLOR_RED);
1613 line[x][
GREEN_PIX] = GET_DATA_BYTE((
void *)data, COLOR_GREEN);
1614 line[x][
BLUE_PIX] = GET_DATA_BYTE((
void *)data, COLOR_BLUE);
1616 this->
put_line(0, y, width, &line, 0);
1621 tprintf(
"Cannot convert Pix to image with bpp = %d\n", depth);
1623 if (destroy_this_pix !=
NULL)
1624 pixDestroy(&destroy_this_pix);
1646 uinT8 ret_white_value,
1651 inT32 oldest_imline;
1662 inT32 xmargin = win_width / 2;
1663 inT32 ymargin = win_height / 2;
1665 const uinT8 max_white = 255;
1668 if (((win_width % 2) == 0) ||
1669 ((win_height % 2) == 0) ||
1671 (win_width < 3) || (win_height > ysize / 2) || (win_width > xsize / 2))
1673 ABORT,
"(%d x %d)", win_width, win_height);
1675 new_row.
init (xsize * bytespp);
1678 for (i = 0; i < win_height; i++) {
1679 old_rows[i].
init ((xsize + 2 * xmargin) * bytespp);
1684 winmax = window + win_height;
1687 for (oldest_imline = 0; oldest_imline < ymargin; oldest_imline++) {
1688 pix = old_rows[oldest_imline].
pixels;
1689 max = pix + (xsize + 2 * xmargin) * bytespp;
1694 for (; oldest_imline < win_height - 1; oldest_imline++) {
1695 get_line (0, row++, xsize, &old_rows[oldest_imline], xmargin);
1696 if (max_white != white) {
1697 pix = old_rows[oldest_imline].
pixels;
1698 max = pix + (xsize + 2 * xmargin) * bytespp;
1700 *pix = (
uinT8) (*pix * white_scale);
1708 for (current_row = 0; current_row < ysize;) {
1711 get_line (0, row++, xsize, &old_rows[oldest_imline], xmargin);
1712 if (max_white != white) {
1713 pix = old_rows[oldest_imline].
pixels;
1714 max = pix + (xsize + 2 * xmargin) * bytespp;
1716 *pix = (
uinT8) (*pix * white_scale);
1722 pix = old_rows[oldest_imline].
pixels;
1723 max = pix + (xsize + 2 * xmargin) * bytespp;
1728 if (oldest_imline >= win_height)
1733 for (current_col = 0; current_col < xsize;) {
1735 if (current_col == 0) {
1737 for (i = 0; i < win_height; i++) {
1738 window[i] = old_rows[j++].
pixels;
1739 if (j >= win_height)
1744 for (win = window; win < winmax; (*win++) += bytespp);
1748 convolve(window, bytespp, win_width, win_height, white, pix);
1753 put_line (0, current_row, xsize, &new_row, 0);