00001
00020 #include "mfcpch.h"
00021 #ifdef __MSW32__
00022 #include <io.h>
00023 #else
00024 #include <unistd.h>
00025 #endif
00026 #include <string.h>
00027 #ifdef __UNIX__
00028 #include <assert.h>
00029 #endif
00030 #include "stderr.h"
00031 #include "tprintf.h"
00032 #include "imgerrs.h"
00033 #include "memry.h"
00034 #include "imgs.h"
00035 #include "imgio.h"
00036 #include "imgunpk.h"
00037
00038 #define FIXED_COLOURS 32
00039 #define MIN_4BIT 48
00040 #define MAX_4BIT 64
00041 #define MIN_6BIT 64
00042 #define MAX_6BIT 128
00043 #define BLACK_PIX 0
00044
00047 static UINT8 grey_scales[FIXED_COLOURS] = {
00048 0, 255, 76, 227, 151, 179, 28, 104,
00049 149, 72, 215, 67, 53, 44, 156, 137,
00050 110, 153, 79, 181, 166, 218, 55, 81,
00051 129, 105, 179, 149, 168, 69, 84, 126
00052 };
00053
00054 #define EXTERN
00055
00058 EXTERN INT_VAR (image_default_resolution, 300, "Image resolution dpi");
00066 IMAGE::IMAGE() {
00067 bpp = 0;
00068 fd = -1;
00069 image = NULL;
00070 photo_interp = 1;
00071 res = image_default_resolution;
00072 }
00073
00074
00080 IMAGE & IMAGE::operator= (
00081 IMAGE & source
00082 ) {
00083 destroy();
00084 bpp = source.bpp;
00085 photo_interp = source.photo_interp;
00086 bps = source.bps;
00087 bytespp = (bpp + 7) / 8;
00088 lineskip = source.lineskip;
00089 captured = source.captured;
00090 xsize = source.xsize;
00091 ysize = source.ysize;
00092 res = source.res;
00093 image = source.image;
00094 xdim = source.xdim;
00095 bufheight = source.bufheight;
00096 fd = source.fd;
00097 reader = source.reader;
00098 ymin = source.ymin;
00099 ymax = source.ymax;
00100
00101 source.captured = TRUE;
00102 source.fd = -1;
00103
00104 return *this;
00105 }
00106
00107
00111 INT8 IMAGE::create(
00112 INT32 x,
00113 INT32 y,
00114 INT8 bits_per_pixel
00115 ) {
00116 UINT8 *pixels;
00117
00118 xdim = check_legal_image_size (x, y, bits_per_pixel);
00119 if (xdim < 0)
00120 return -1;
00121 pixels = (UINT8 *) alloc_big_zeros ((size_t) (xdim * y * sizeof (UINT8)));
00122 if (pixels == NULL) {
00123 MEMORY_OUT.error ("IMAGE::create", ABORT, "Size=(%d,%d)", xdim, y);
00124 return -1;
00125 }
00126
00127 this->capture (pixels, x, y, bits_per_pixel);
00128 captured = FALSE;
00129 res = image_default_resolution;
00130 return 0;
00131 }
00132
00133
00137 void IMAGE::destroy() {
00138 if (image != NULL && !captured) {
00139 free_big_mem(image);
00140 }
00141 image = NULL;
00142 if (fd >= 0) {
00143 close(fd);
00144 fd = -1;
00145 }
00146 bpp = 0;
00147 }
00148
00149
00154 INT8 IMAGE::capture(
00155 UINT8 *pixels,
00156 INT32 x,
00157 INT32 y,
00158 INT8 bits_per_pixel
00159 ) {
00160 destroy();
00161 xdim = check_legal_image_size (x, y, bits_per_pixel);
00162 if (xdim < 0)
00163 return -1;
00164 xsize = x;
00165 ysize = y;
00166 bufheight = y;
00167 bpp = bits_per_pixel;
00168 bps = bpp == 24 ? 8 : bpp;
00169 photo_interp = 1;
00170 bytespp = (bpp + 7) / 8;
00171 image = pixels;
00172 ymin = 0;
00173 ymax = bufheight;
00174 captured = TRUE;
00175 res = image_default_resolution;
00176 return 0;
00177 }
00178
00179
00183 UINT8 IMAGE::pixel(
00184 INT32 x,
00185 INT32 y
00186 ) {
00187 if (x < 0)
00188 x = 0;
00189 else if (x >= xsize)
00190 x = xsize - 1;
00191 if (y < 0)
00192 y = 0;
00193 else if (y >= ysize)
00194 y = ysize - 1;
00195 check_legal_access (x, y, 1);
00196 switch (bpp) {
00197 case 5:
00198 case 6:
00199 case 8:
00200 return image[(ymax - 1 - y) * xdim + x];
00201 case 4:
00202 return bpp4table[image[(ymax - 1 - y) * xdim + x / 2]][x & 1];
00203 case 2:
00204 return bpp2table[image[(ymax - 1 - y) * xdim + x / 4]][x & 3];
00205 case 1:
00206 return bpp1table[image[(ymax - 1 - y) * xdim + x / 8]][x & 7];
00207 default:
00208 tprintf ("Unexpected bits per pixel %d\n", bpp);
00209 return 0;
00210 }
00211 }
00212
00213
00219 INT32 check_legal_image_size(
00220 INT32 x,
00221 INT32 y,
00222 INT8 bits_per_pixel
00223 ) {
00224 if (x <= 0 || y <= 0) {
00225 BADIMAGESIZE.error ("check_legal_image_size", LOG, "(%d,%d)", x, y);
00226 return -1;
00227 }
00228 if (bits_per_pixel != 1 && bits_per_pixel != 2
00229 && bits_per_pixel != 4 && bits_per_pixel != 5
00230 && bits_per_pixel != 6 && bits_per_pixel != 8 && bits_per_pixel != 24) {
00231 BADBPP.error ("check_legal_image_size", LOG, "%d", bits_per_pixel);
00232 return -1;
00233 }
00234
00235 return COMPUTE_IMAGE_XDIM (x, bits_per_pixel);
00236 }
00237
00238
00245 DLLSYM void copy_sub_image(
00246 IMAGE *source,
00247 INT32 xstart,
00248 INT32 ystart,
00249 INT32 xext,
00250 INT32 yext,
00251 IMAGE *dest,
00252 INT32 xdest,
00253 INT32 ydest,
00254 BOOL8 adjust_grey
00255 ) {
00256 IMAGELINE copyline;
00257 UINT8 *copy;
00258 INT8 shift;
00259 INT32 pixel;
00260 INT32 y;
00261 INT32 yoffset;
00262 INT32 bytesize;
00263 INT32 srcppb;
00264 BOOL8 aligned;
00265
00266 if (xstart < 0 || ystart < 0 || xdest < 0 || ydest < 0)
00267 return;
00268 if (xext <= 0)
00269 xext = source->xsize;
00270 if (xext > source->xsize - xstart)
00271
00272 xext = source->xsize - xstart;
00273 if (xext > dest->xsize - xdest)
00274 xext = dest->xsize - xdest;
00275 if (yext <= 0)
00276 yext = source->ysize;
00277 if (yext > source->ysize - ystart)
00278
00279 yext = source->ysize - ystart;
00280 if (yext > dest->ysize - ydest)
00281 yext = dest->ysize - ydest;
00282 if (xext <= 0 || yext <= 0)
00283 return;
00284
00285 srcppb = 8 / source->bpp;
00286 if (source->bpp == dest->bpp || !adjust_grey)
00287 shift = 0;
00288 else {
00289 shift = source->bps - dest->bps;
00290 if (shift < 0)
00291 shift = -shift;
00292 }
00293 aligned = source->bpp == dest->bpp;
00294 if (aligned && srcppb != 0) {
00295 aligned = xstart % srcppb == 0
00296 && xdest % srcppb == 0
00297 && (xext % srcppb == 0 || xdest + xext == dest->xsize);
00298 }
00299 for (y = 0; y < yext; y++) {
00300 if (ystart >= ydest)
00301 yoffset = y;
00302 else
00303 yoffset = yext - y - 1;
00304 source->check_legal_access (xstart, ystart + yoffset, xext);
00305 dest->check_legal_access (xdest, ydest + yoffset, xext);
00306 if (aligned) {
00307 bytesize = COMPUTE_IMAGE_XDIM (xext, source->bpp);
00308
00309 if (srcppb == 0)
00310
00311 memmove (dest->image + (dest->ymax - 1 - ydest - yoffset)
00312 * dest->xdim + xdest * 3, source->image
00313 + (source->ymax - 1 - ystart - yoffset)
00314 * source->xdim + xstart * 3, (unsigned) bytesize);
00315 else
00316
00317 memmove (dest->image
00318 + (dest->ymax - 1 - ydest - yoffset)
00319 * dest->xdim + xdest / srcppb, source->image
00320 + (source->ymax - 1 - ystart - yoffset)
00321 * source->xdim + xstart / srcppb, (unsigned) bytesize);
00322 }
00323 else {
00324 if (shift == 0) {
00325 source->fast_get_line (xstart, ystart + yoffset, xext,
00326 ©line);
00327 }
00328 else if (source->bpp < dest->bpp) {
00329 source->get_line (xstart, ystart + yoffset, xext, ©line, 0);
00330 if (source->bpp <= shift
00331 && (source->bpp == 1 || source->bpp == 4)) {
00332 if (source->bpp == 1) {
00333 for (pixel = 0, copy = copyline.pixels; pixel < xext;
00334 pixel++, copy++)
00335 if (*copy)
00336 *copy = 0xff;
00337 }
00338 else {
00339 for (pixel = 0, copy = copyline.pixels; pixel < xext;
00340 pixel++, copy++)
00341
00342 *copy = (*copy << shift) | *copy;
00343 }
00344 }
00345 else {
00346 for (pixel = 0, copy = copyline.pixels; pixel < xext;
00347 pixel++)
00348 *copy++ <<= shift;
00349 }
00350 }
00351 else {
00352 source->get_line (xstart, ystart + yoffset, xext, ©line, 0);
00353 if (source->bpp == 24) {
00354 for (pixel = 0, copy = copyline.pixels + 1; pixel < xext;
00355 pixel++) {
00356 *copy >>= shift;
00357 copy += 3;
00358 }
00359 }
00360 else {
00361 for (pixel = 0, copy = copyline.pixels; pixel < xext;
00362 pixel++)
00363 *copy++ >>= shift;
00364 }
00365 }
00366 dest->put_line (xdest, ydest + yoffset, xext, ©line, 0);
00367 }
00368 }
00369 }
00370
00371
00379 DLLSYM void enlarge_sub_image(
00380 IMAGE *source,
00381 INT32 xstart,
00382 INT32 ystart,
00383 IMAGE *dest,
00384 INT32 xdest,
00385 INT32 ydest,
00386 INT32 xext,
00387 INT32 yext,
00388 INT32 scale,
00389 BOOL8 adjust_grey
00390 ) {
00391 INT8 shift;
00392 UINT8 pixel;
00393 INT32 srcext;
00394 INT32 xoffset;
00395 INT32 yoffset;
00396 INT32 xindex, yindex;
00397 INT32 startxindex;
00398 INT32 xscale;
00399 UINT8 *src;
00400 UINT8 *destpix;
00401 IMAGELINE copyline;
00402 IMAGELINE bigline;
00403
00404 if (xstart < 0 || ystart < 0 || xdest < 0 || ydest < 0)
00405 return;
00406
00407 if (xext <= 0)
00408 xext = dest->xsize;
00409 if (xext > source->xsize * scale - xstart)
00410
00411 xext = source->xsize * scale - xstart;
00412 if (xext > dest->xsize - xdest)
00413 xext = dest->xsize - xdest;
00414 if (yext <= 0)
00415 yext = dest->ysize;
00416 if (yext > source->ysize * scale - ystart)
00417 yext = source->ysize * scale - ystart;
00418 if (yext > dest->ysize - ydest)
00419 yext = dest->ysize - ydest;
00420 if (xext <= 0 || yext <= 0)
00421 return;
00422
00423 xindex = xstart % scale;
00424 startxindex = xindex;
00425 yindex = ystart % scale;
00426
00427 srcext = (xext + xindex + scale - 1) / scale;
00428 xstart /= scale;
00429 ystart /= scale;
00430 if (adjust_grey) {
00431 shift = dest->bps - source->bps;
00432 }
00433 else
00434 shift = 0;
00435 bigline.init (xext * 3);
00436 bigline.bpp = dest->bpp == 24 ? source->bpp : dest->bpp;
00437
00438 for (yoffset = 0; yoffset < yext; ystart++) {
00439 source->check_legal_access (xstart, ystart, srcext);
00440 dest->check_legal_access (xdest, ydest + yoffset, xext);
00441 source->fast_get_line (xstart, ystart, srcext, ©line);
00442 src = copyline.pixels;
00443 destpix = bigline.pixels;
00444 xscale = scale;
00445 if (source->bpp == 24 && dest->bpp == 24) {
00446 for (xoffset = 0, xindex = startxindex; xoffset < xext;
00447 src += source->bytespp) {
00448 xoffset += xscale - xindex;
00449 if (xoffset > xext)
00450 xscale -= xoffset - xext;
00451 for (; xindex < xscale; xindex++) {
00452 *destpix++ = *src;
00453 *destpix++ = *(src + 1);
00454 *destpix++ = *(src + 2);
00455 }
00456 xindex = 0;
00457 }
00458 }
00459 else {
00460 if (source->bpp == 24)
00461 src++;
00462 for (xoffset = 0, xindex = startxindex; xoffset < xext;
00463 src += source->bytespp) {
00464 xoffset += xscale - xindex;
00465 if (xoffset > xext)
00466
00467 xscale -= xoffset - xext;
00468 if (shift == 0)
00469 pixel = *src;
00470 else if (shift > 0)
00471 pixel = *src << shift;
00472 else
00473 pixel = *src >> (-shift);
00474 for (; xindex < xscale; xindex++)
00475 *destpix++ = pixel;
00476 xindex = 0;
00477 }
00478 }
00479 for (; yoffset < yext && yindex < scale; yindex++, yoffset++) {
00480 dest->put_line (xdest, ydest + yoffset, xext, &bigline, 0);
00481 }
00482 yindex = 0;
00483 }
00484 }
00485
00486
00496 DLLSYM void fast_reduce_sub_image(
00497 IMAGE *source,
00498 INT32 xstart,
00499 INT32 ystart,
00500 INT32 xext,
00501 INT32 yext,
00502 IMAGE *dest,
00503 INT32 xdest,
00504 INT32 ydest,
00505 INT32 scale,
00506 BOOL8 adjust_grey
00507 ) {
00508 INT8 shift;
00509 INT32 xfactor;
00510 INT32 divisor;
00511 INT32 xindex, yindex;
00512 INT32 xcoord;
00513 INT32 destext;
00514 INT32 yoffset;
00515 UINT8 *pixel;
00516 INT32 *sums;
00517 IMAGELINE copyline;
00518 INT32 *linesums;
00519
00520 if (xstart < 0 || ystart < 0 || xdest < 0 || ydest < 0)
00521 return;
00522 if (xext <= 0)
00523 xext = source->xsize;
00524 if (xext > source->xsize - xstart)
00525
00526 xext = source->xsize - xstart;
00527 if (xext > (dest->xsize - xdest) * scale)
00528 xext = (dest->xsize - xdest) * scale;
00529 if (yext <= 0)
00530 yext = source->ysize;
00531 if (yext > source->ysize - ystart)
00532
00533 yext = source->ysize - ystart;
00534 if (yext > (dest->ysize - ydest) * scale)
00535 yext = (dest->ysize - ydest) * scale;
00536 if (xext <= 0 || yext <= 0)
00537 return;
00538
00539 xfactor = xext % scale;
00540 if (xfactor == 0)
00541 xfactor = scale;
00542
00543 destext = (xext + scale - 1) / scale;
00544 if (adjust_grey)
00545
00546 shift = dest->bps - source->bps;
00547 else
00548 shift = 0;
00549 linesums = new INT32[destext * source->bytespp];
00550
00551 for (yoffset = 0; yoffset < yext; ydest++) {
00552 source->check_legal_access (xstart, ystart + yoffset, xext);
00553 dest->check_legal_access (xdest, ydest, destext);
00554 for (xindex = destext * source->bytespp - 1; xindex >= 0; xindex--)
00555 linesums[xindex] = 0;
00556 for (yindex = 0; yindex < scale
00557 && ystart + yoffset < source->ysize; yindex += 3) {
00558 source->fast_get_line (xstart, ystart + yoffset, xext, ©line);
00559 pixel = copyline.pixels;
00560 if (source->bpp == 24) {
00561 for (xcoord = 1, sums = linesums; xcoord < destext;
00562 xcoord++, sums += 3) {
00563 for (xindex = 0; xindex < scale; xindex += 2) {
00564 *sums += *pixel++;
00565 *(sums + 1) += *pixel++;
00566 *(sums + 2) += *pixel++;
00567 pixel += 3;
00568 }
00569 if (scale & 1)
00570 pixel -= 3;
00571 }
00572 for (xindex = 0; xindex < xfactor; xindex += 2) {
00573 *sums += *pixel++;
00574 *(sums + 1) += *pixel++;
00575 *(sums + 2) += *pixel++;
00576 pixel += 3;
00577 }
00578 }
00579 else {
00580 for (xcoord = 1, sums = linesums; xcoord < destext;
00581 xcoord++, sums++) {
00582 for (xindex = 0; xindex < scale; xindex += 2) {
00583 *sums += *pixel;
00584 pixel += 2;
00585 }
00586 if (scale & 1)
00587 pixel--;
00588 }
00589 for (xindex = 0; xindex < xfactor; xindex += 2) {
00590 *sums += *pixel;
00591 pixel += 2;
00592 }
00593 }
00594 yoffset += 3;
00595 }
00596 if (yindex > scale)
00597 yoffset -= yindex - scale;
00598 copyline.init ();
00599 copyline.bpp = source->bpp;
00600 pixel = copyline.pixels;
00601
00602 divisor = ((yindex + 2) / 3) * ((scale + 1) / 2);
00603 if (shift <= 0) {
00604 divisor <<= (-shift);
00605 for (sums = linesums, xindex = (destext - 1) * source->bytespp;
00606 xindex > 0; xindex--)
00607
00608 *pixel++ = (UINT8) (*sums++ / divisor);
00609 for (xindex = source->bytespp; xindex > 0; xindex--)
00610 *pixel++ = *sums++
00611 / (((yindex + 2) / 3) * ((xfactor + 1) / 2) << (-shift));
00612
00613 }
00614 else {
00615 for (sums = linesums, xindex = (destext - 1) * source->bytespp;
00616 xindex > 0; xindex--)
00617 *pixel++ = (UINT8) ((*sums++ << shift) / divisor);
00618
00619 for (xindex = source->bytespp; xindex > 0; xindex--)
00620
00621 *pixel++ = (*(sums++) << shift) /
00622 (((yindex + 2) / 3) * ((xfactor + 1) / 2));
00623 }
00624
00625 dest->put_line (xdest, ydest, destext, ©line, 0);
00626 }
00627 delete linesums;
00628 }
00629
00630
00637 DLLSYM void reduce_sub_image(
00638 IMAGE *source,
00639 INT32 xstart,
00640 INT32 ystart,
00641 INT32 xext,
00642 INT32 yext,
00643 IMAGE *dest,
00644 INT32 xdest,
00645 INT32 ydest,
00646 INT32 scale,
00647 BOOL8 adjust_grey
00648 ) {
00649 INT8 shift;
00650 INT32 xfactor;
00651 INT32 divisor;
00652 INT32 div2;
00653 INT32 xindex, yindex;
00654 INT32 xcoord;
00655 INT32 destext;
00656 INT32 yoffset;
00657 UINT8 *pixel;
00658 INT32 *sums;
00659 IMAGELINE copyline;
00660 INT32 *linesums;
00661
00662 if (xstart < 0 || ystart < 0 || xdest < 0 || ydest < 0)
00663 return;
00664 if (xext <= 0)
00665 xext = source->xsize;
00666 if (xext > source->xsize - xstart)
00667
00668 xext = source->xsize - xstart;
00669 if (xext > (dest->xsize - xdest) * scale)
00670 xext = (dest->xsize - xdest) * scale;
00671 if (yext <= 0)
00672 yext = source->ysize;
00673 if (yext > source->ysize - ystart)
00674
00675 yext = source->ysize - ystart;
00676 if (yext > (dest->ysize - ydest) * scale)
00677 yext = (dest->ysize - ydest) * scale;
00678 if (xext <= 0 || yext <= 0)
00679 return;
00680
00681 xfactor = xext % scale;
00682 if (xfactor == 0)
00683 xfactor = scale;
00684
00685 destext = (xext + scale - 1) / scale;
00686 if (adjust_grey)
00687
00688 shift = dest->bps - source->bps;
00689 else
00690 shift = 0;
00691 linesums = new INT32[destext * source->bytespp];
00692
00693 for (yoffset = 0; yoffset < yext; ydest++) {
00694 source->check_legal_access (xstart, ystart + yoffset, xext);
00695 dest->check_legal_access (xdest, ydest, destext);
00696 for (xindex = 0; xindex < (destext) * source->bytespp; xindex++)
00697 linesums[xindex] = 0;
00698 for (yindex = 0; yindex < scale && ystart + yoffset < source->ysize;
00699 yindex++) {
00700 source->fast_get_line (xstart, ystart + yoffset, xext, ©line);
00701 pixel = copyline.pixels;
00702 if (source->bpp == 24) {
00703 for (xcoord = 1, sums = linesums; xcoord < destext;
00704 xcoord++, sums += 3) {
00705 for (xindex = 0; xindex < scale; xindex++) {
00706 *sums += *pixel++;
00707 *(sums + 1) += *pixel++;
00708 *(sums + 2) += *pixel++;
00709 }
00710 }
00711 for (xindex = 0; xindex < xfactor; xindex++) {
00712 *sums += *pixel++;
00713 *(sums + 1) += *pixel++;
00714 *(sums + 2) += *pixel++;
00715 }
00716 }
00717 else {
00718 for (xcoord = 1, sums = linesums; xcoord < destext;
00719 xcoord++, sums++) {
00720 for (xindex = 0; xindex < scale; xindex++)
00721 *sums += *pixel++;
00722 }
00723 for (xindex = 0; xindex < xfactor; xindex++)
00724 *sums += *pixel++;
00725 }
00726 yoffset++;
00727 }
00728 copyline.init ();
00729 copyline.set_bpp (source->bpp);
00730 pixel = copyline.pixels;
00731 divisor = yindex * scale;
00732 if (divisor == 0) {
00733 tprintf
00734 ("Impossible:divisor=0!, yindex=%d, scale=%d, yoffset=%d,yext=%d\n",
00735 yindex, scale, yoffset, yext);
00736 break;
00737 }
00738 if (shift <= 0) {
00739 divisor <<= (-shift);
00740 div2 = divisor / 2;
00741 for (sums = linesums, xindex = (destext - 1) * source->bytespp;
00742 xindex > 0; xindex--)
00743 *pixel++ = (UINT8) ((div2 + *sums++) / divisor);
00744
00745 div2 = (yindex * xfactor << (-shift)) / 2;
00746 for (xindex = source->bytespp; xindex > 0; xindex--)
00747 *pixel++ =
00748 (UINT8) ((div2 + *sums++) / (yindex * xfactor << (-shift)));
00749
00750 }
00751 else {
00752 div2 = divisor / 2;
00753 for (sums = linesums, xindex = (destext - 1) * source->bytespp;
00754 xindex > 0; xindex--)
00755 *pixel++ = (UINT8) ((div2 + (*sums++ << shift)) / divisor);
00756
00757 div2 = (yindex * xfactor) / 2;
00758 for (xindex = source->bytespp; xindex > 0; xindex--)
00759 *pixel++ =
00760 (UINT8) ((div2 + (*sums++ << shift)) / (yindex * xfactor));
00761
00762 }
00763
00764 dest->put_line (xdest, ydest, destext, ©line, 0);
00765 }
00766 delete linesums;
00767 }
00768
00769
00773 DLLSYM void invert_image(
00774 IMAGE *image
00775 ) {
00776 UINT8 mask;
00777 UINT8 bytespp;
00778 INT32 xsize, ysize;
00779 INT32 xindex, yindex;
00780 UINT8 *pixel;
00781 IMAGELINE line;
00782
00783 bytespp = image->get_bpp () == 24 ? 3 : 1;
00784 xsize = image->get_xsize ();
00785 ysize = image->get_ysize ();
00786
00787 mask = (1 << image->get_bpp ()) - 1;
00788
00789 for (yindex = ysize - 1; yindex >= 0; yindex--) {
00790 image->fast_get_line (0, yindex, xsize, &line);
00791 for (pixel = line.pixels, xindex = xsize * bytespp; xindex > 0;
00792 xindex--) {
00793 *pixel = (*pixel) ^ mask;
00794 ++pixel;
00795 }
00796
00797 image->fast_put_line (0, yindex, xsize, &line);
00798 }
00799 }
00800
00801
00805 DLLSYM void bias_sub_image(
00806 IMAGE *source,
00807 INT32 xstart,
00808 INT32 ystart,
00809 INT32 xext,
00810 INT32 yext,
00811 UINT8 bias
00812 ) {
00813 IMAGELINE copyline;
00814 UINT8 *copy;
00815 INT32 pixel;
00816 INT32 y;
00817 UINT8 bytespp;
00818
00819 if (xstart < 0 || ystart < 0)
00820 return;
00821 if (xext <= 0)
00822 xext = source->get_xsize ();
00823 if (xext > source->get_xsize () - xstart)
00824
00825 xext = source->get_xsize () - xstart;
00826 if (yext <= 0)
00827 yext = source->get_ysize ();
00828 if (yext > source->get_ysize () - ystart)
00829
00830 yext = source->get_ysize () - ystart;
00831 if (xext <= 0 || yext <= 0)
00832 return;
00833
00834 bytespp = source->get_bpp () == 24 ? 3 : 1;
00835 for (y = 0; y < yext; y++) {
00836 source->check_legal_access (xstart, ystart + y, xext);
00837 source->fast_get_line (xstart, ystart + y, xext, ©line);
00838 for (pixel = xext * bytespp, copy = copyline.pixels; pixel > 0;
00839 pixel--, copy++)
00840 *copy += bias;
00841
00842 source->fast_put_line (xstart, ystart + y, xext, ©line);
00843 }
00844 }
00845
00846
00853 DLLSYM void starbase_to_normal(
00854 IMAGE *source,
00855 INT32 xstart,
00856 INT32 ystart,
00857 INT32 xext,
00858 INT32 yext,
00859 IMAGE *dest,
00860 INT32 xdest,
00861 INT32 ydest,
00862 BOOL8 preserve_grey
00863 ) {
00864 IMAGELINE copyline;
00865 UINT8 *copy;
00866 INT8 shift4;
00867 INT8 shift6;
00868 INT8 colour_shift;
00869 UINT8 white_level;
00870 INT32 pixel;
00871 INT32 y;
00872 INT32 yoffset;
00873 INT8 srcppb;
00874
00875 if (xstart < 0 || ystart < 0 || xdest < 0 || ydest < 0)
00876 return;
00877 if (xext <= 0)
00878 xext = source->get_xsize ();
00879 if (xext > source->get_xsize () - xstart)
00880
00881 xext = source->get_xsize () - xstart;
00882 if (xext > dest->get_xsize () - xdest)
00883 xext = dest->get_xsize () - xdest;
00884 if (yext <= 0)
00885 yext = source->get_ysize ();
00886 if (yext > source->get_ysize () - ystart)
00887
00888 yext = source->get_ysize () - ystart;
00889 if (yext > dest->get_ysize () - ydest)
00890 yext = dest->get_ysize () - ydest;
00891 if (xext <= 0 || yext <= 0)
00892 return;
00893
00894
00895 srcppb = 8 / source->get_bpp ();
00896 shift4 = 4 - dest->get_bpp ();
00897 shift6 = 6 - dest->get_bpp ();
00898
00899 colour_shift = 8 - dest->get_bpp ();
00900 white_level = dest->get_white_level ();
00901 for (y = 0; y < yext; y++) {
00902 if (ystart >= ydest)
00903 yoffset = y;
00904 else
00905 yoffset = yext - y - 1;
00906 source->check_legal_access (xstart, ystart + yoffset, xext);
00907 dest->check_legal_access (xdest, ydest + yoffset, xext);
00908 source->get_line (xstart, ystart + yoffset, xext, ©line, 0);
00909 for (pixel = 0, copy = copyline.pixels; pixel < xext; pixel++) {
00910 if (*copy < FIXED_COLOURS && preserve_grey)
00911 *copy = grey_scales[*copy] >> colour_shift;
00912 else if (*copy < FIXED_COLOURS) {
00913 if (*copy == BLACK_PIX)
00914 *copy = white_level;
00915 else
00916 *copy = 0;
00917 }
00918 else if (*copy >= MIN_4BIT && *copy < MAX_4BIT) {
00919 if (shift4 < 0)
00920 *copy = (*copy - MIN_4BIT) << (-shift4);
00921 else
00922 *copy = (*copy - MIN_4BIT) >> shift4;
00923 }
00924 else if (*copy >= MIN_6BIT && *copy < MAX_6BIT) {
00925 if (shift6 < 0)
00926 *copy = (*copy - MIN_6BIT) << (-shift6);
00927 else
00928 *copy = (*copy - MIN_6BIT) >> shift6;
00929 }
00930 else {
00931 *copy = white_level;
00932 }
00933 copy++;
00934 }
00935 dest->put_line (xdest, ydest + yoffset, xext, ©line, 0);
00936 }
00937 }
00938
00939
00948 void IMAGE::fast_get_line(
00949 INT32 x,
00950 INT32 y,
00951 INT32 width,
00952 IMAGELINE *linebuf
00953 ) {
00954 if (width > 0 && bpp > 4) {
00955 check_legal_access(x, y, width);
00956
00957 linebuf->pixels = image + xdim * (ymax - 1 - y) + x * bytespp;
00958 }
00959 else
00960
00961 this->get_line (x, y, width, linebuf, 0);
00962 linebuf->bpp = bpp;
00963 }
00964
00965
00971 void IMAGE::get_line(
00972 INT32 x,
00973 INT32 y,
00974 INT32 width,
00975 IMAGELINE *linebuf,
00976 INT32 margins
00977 ) {
00978 UINT8 *src;
00979 UINT8 *dest;
00980 UINT8 *unpacksrc;
00981 INT8 bit;
00982 INT8 pixperbyte;
00983 UINT8 white;
00984 INT32 pixel;
00985
00986
00987 this->check_legal_access (x, y, width);
00988 if (width > xsize - x)
00989 width = xsize - x;
00990 width *= bytespp;
00991 linebuf->init (width + margins * bytespp * 2);
00992 linebuf->bpp = bpp;
00993
00994 src = image + xdim * (ymax - 1 - y);
00995 dest = linebuf->line;
00996 linebuf->pixels = dest;
00997 white = (1 << bpp) - 1;
00998 for (pixel = margins * bytespp; pixel > 0; pixel--) {
00999 *dest++ = white;
01000 }
01001 if (width > 0) {
01002 if (bpp > 4) {
01003 src += x;
01004
01005 memmove (dest, src, (unsigned) width);
01006 }
01007 else if (bpp == 4) {
01008 src += x / 2;
01009 if (x & 1) {
01010
01011 *dest++ = bpp4table[*src++][1];
01012 width--;
01013 }
01014 while (width >= 2) {
01015
01016 unpacksrc = bpp4table[*src++];
01017 *dest++ = *unpacksrc++;
01018 *dest++ = *unpacksrc++;
01019 width -= 2;
01020 }
01021 if (width) {
01022
01023 *dest++ = bpp4table[*src++][0];
01024 }
01025 }
01026 else if (bpp == 2) {
01027 pixperbyte = 4;
01028 src += x / 4;
01029 bit = (INT8) (x % 4);
01030 width += bit;
01031 while (width > 0) {
01032 if (width < pixperbyte)
01033
01034 pixperbyte = (INT8) width;
01035
01036 unpacksrc = &bpp2table[*src++][bit];
01037 for (; bit < pixperbyte; bit++)
01038 *dest++ = *unpacksrc++;
01039 width -= pixperbyte;
01040 bit = 0;
01041 }
01042 }
01043 else {
01044 pixperbyte = 8;
01045 src += x / 8;
01046 bit = (INT8) (x % 8);
01047 width += bit;
01048 while (width > 0) {
01049 if (width < pixperbyte)
01050
01051 pixperbyte = (INT8) width;
01052
01053 unpacksrc = &bpp1table[*src++][bit];
01054 for (; bit < pixperbyte; bit++)
01055 *dest++ = *unpacksrc++;
01056 width -= pixperbyte;
01057 bit = 0;
01058 }
01059 }
01060 }
01061 for (pixel = margins * bytespp; pixel > 0; pixel--) {
01062 *dest++ = white;
01063 }
01064 }
01065
01066
01072 void IMAGE::get_column(
01073 INT32 x,
01074 INT32 y,
01075 INT32 height,
01076 IMAGELINE *linebuf,
01077 INT32 margins
01078 ) {
01079 UINT8 *src;
01080 UINT8 *dest;
01081 INT8 bit;
01082 INT8 pixperbyte;
01083 UINT8 white;
01084 INT32 pixel;
01085
01086
01087 this->check_legal_access (x, y, 1);
01088
01089 this->check_legal_access (x, y + height - 1, 1);
01090 if (height > ysize - y)
01091 height = ysize - y;
01092 linebuf->init (height * bytespp + margins * bytespp * 2);
01093
01094 src = image + xdim * (ymax - 1 - y);
01095 dest = linebuf->line;
01096 linebuf->pixels = dest;
01097 white = (1 << bpp) - 1;
01098 for (pixel = margins * bytespp; pixel > 0; pixel--) {
01099 *dest++ = white;
01100 }
01101 if (height > 0) {
01102 if (bpp == 24) {
01103 src += x * bytespp;
01104 for (; height > 0; --height) {
01105 *dest++ = *src;
01106 *dest++ = *(src + 1);
01107 *dest++ = *(src + 2);
01108 src -= xdim;
01109 }
01110 }
01111 else if (bpp > 4) {
01112 src += x;
01113 for (; height > 0; --height) {
01114 *dest++ = *src;
01115 src -= xdim;
01116 }
01117 }
01118 else if (bpp == 4) {
01119 src += x / 2;
01120 if (x & 1) {
01121 for (; height > 0; --height) {
01122
01123 *dest++ = bpp4table[*src][1];
01124 src -= xdim;
01125 }
01126 }
01127 else {
01128 for (; height > 0; --height) {
01129
01130 *dest++ = bpp4table[*src][0];
01131 src -= xdim;
01132 }
01133 }
01134 }
01135 else if (bpp == 2) {
01136 pixperbyte = 4;
01137 src += x / 4;
01138 bit = (INT8) (x % 4);
01139 for (; height > 0; --height) {
01140
01141 *dest++ = bpp2table[*src][bit];
01142 src -= xdim;
01143 }
01144 }
01145 else {
01146 pixperbyte = 8;
01147 src += x / 8;
01148 bit = (INT8) (x % 8);
01149 for (; height > 0; --height) {
01150
01151 *dest++ = bpp1table[*src][bit];
01152 src -= xdim;
01153 }
01154 }
01155 }
01156 for (pixel = margins * bytespp; pixel > 0; pixel--) {
01157 *dest++ = white;
01158 }
01159 }
01160
01161
01168 void IMAGE::fast_put_line(
01169 INT32 x,
01170 INT32 y,
01171 INT32 width,
01172 IMAGELINE *linebuf
01173 ) {
01174 if (width > 0 && (bpp <= 4 || linebuf->pixels == linebuf->line))
01175
01176 put_line (x, y, width, linebuf, 0);
01177 }
01178
01179
01185 void IMAGE::put_line(
01186 INT32 x,
01187 INT32 y,
01188 INT32 width,
01189 IMAGELINE *linebuf,
01190 INT32 margins
01191 ) {
01192 UINT8 *src;
01193 UINT8 *dest;
01194 INT8 bit;
01195 UINT8 pixel;
01196 INT8 pixperbyte;
01197 INT8 bytesperpix;
01198
01199 this->check_legal_access (x, y, width);
01200 if (width > xsize - x)
01201 width = xsize - x;
01202 if (width <= 0)
01203 return;
01204
01205 src = linebuf->pixels + margins;
01206
01207 dest = image + xdim * (ymax - 1 - y);
01208
01209 if (linebuf->bpp == 24) {
01210 src++;
01211 bytesperpix = 3;
01212 }
01213 else
01214 bytesperpix = 1;
01215 if (bpp == 24 && linebuf->bpp == 24) {
01216 dest += x * bytespp;
01217 width *= bytespp;
01218 memmove (dest, src - 1, (unsigned) width);
01219 }
01220 else if (bpp == 24) {
01221 src--;
01222 dest += x * bytespp;
01223 while (width > 0) {
01224 pixel = *src++;
01225 *dest++ = pixel;
01226 *dest++ = pixel;
01227 *dest++ = pixel;
01228 width--;
01229 }
01230 }
01231 else if (bpp > 4) {
01232 dest += x;
01233 if (linebuf->bpp == 24) {
01234 while (width > 0) {
01235 *dest++ = *src;
01236 src += 3;
01237 width--;
01238 }
01239 }
01240 else
01241
01242 memmove (dest, src, (unsigned) width);
01243 }
01244 else if (bpp == 4) {
01245 dest += x / 2;
01246 if (x & 1) {
01247 *dest &= 0xf0;
01248 *dest++ |= *src & 0x0f;
01249 src += bytesperpix;
01250 width--;
01251 }
01252 while (width >= 2) {
01253 pixel = *src << 4;
01254 src += bytesperpix;
01255 pixel |= *src & 0x0f;
01256 src += bytesperpix;
01257 *dest++ = pixel;
01258 width -= 2;
01259 }
01260 if (width) {
01261 *dest &= 0x0f;
01262 *dest |= *src << 4;
01263 }
01264 }
01265 else if (bpp == 2) {
01266 pixperbyte = 4;
01267 dest += x / 4;
01268 bit = (INT8) (x % 4);
01269 width += bit;
01270 pixel = *dest >> (8 - bit - bit);
01271 while (width >= 4) {
01272 for (; bit < 4; bit++) {
01273 pixel <<= 2;
01274 pixel |= *src & 3;
01275 src += bytesperpix;
01276 }
01277 *dest++ = pixel;
01278 width -= 4;
01279 bit = 0;
01280 }
01281 if (width > 0) {
01282 for (bit = 0; bit < width; bit++) {
01283 pixel <<= 2;
01284 pixel |= *src & 3;
01285 src += bytesperpix;
01286 }
01287 pixel <<= (8 - bit - bit);
01288
01289 pixel |= *dest & ((1 << (8 - bit - bit)) - 1);
01290 *dest++ = pixel;
01291 }
01292 }
01293 else {
01294 pixperbyte = 8;
01295 dest += x / 8;
01296 bit = (INT8) (x % 8);
01297 width += bit;
01298 pixel = *dest >> (8 - bit);
01299 while (width >= 8) {
01300 for (; bit < 8; bit++) {
01301 pixel <<= 1;
01302 pixel |= *src & 1;
01303 src += bytesperpix;
01304 }
01305 *dest++ = pixel;
01306 width -= 8;
01307 bit = 0;
01308 }
01309 width -= bit;
01310 if (width > 0) {
01311 while (width > 0) {
01312 pixel <<= 1;
01313 pixel |= *src & 1;
01314 src += bytesperpix;
01315 bit++;
01316 width--;
01317 }
01318 pixel <<= (8 - bit);
01319
01320 pixel |= *dest & ((1 << (8 - bit)) - 1);
01321 *dest++ = pixel;
01322 }
01323 }
01324 }
01325
01326
01332 void IMAGE::put_column(
01333 INT32 x,
01334 INT32 y,
01335 INT32 height,
01336 IMAGELINE *linebuf,
01337 INT32 margins
01338 ) {
01339 UINT8 *src;
01340 UINT8 *dest;
01341 INT8 bit;
01342 UINT8 pixel;
01343 INT8 bytesperpix;
01344
01345 this->check_legal_access (x, y, 1);
01346 this->check_legal_access (x, y + height - 1, 1);
01347 if (height > ysize - y)
01348 height = ysize - y;
01349 if (height <= 0)
01350 return;
01351
01352 src = linebuf->pixels + margins;
01353
01354 dest = image + xdim * (ymax - 1 - y);
01355
01356 if (linebuf->bpp == 24) {
01357 src++;
01358 bytesperpix = 3;
01359 }
01360 else
01361 bytesperpix = 1;
01362
01363 if (bpp == 24 && linebuf->bpp == 24) {
01364 dest += x * bytesperpix;
01365 src--;
01366 for (; height > 0; --height) {
01367 *dest = *src++;
01368 *(dest + 1) = *src++;
01369 *(dest + 2) = *src++;
01370 dest -= xdim;
01371 }
01372 }
01373 else if (bpp == 24) {
01374 src--;
01375 dest += x * bytesperpix;
01376 for (; height > 0; --height) {
01377 pixel = *src++;
01378 *dest = pixel;
01379 *(dest + 1) = pixel;
01380 *(dest + 2) = pixel;
01381 dest -= xdim;
01382 }
01383 }
01384 else if (bpp > 4) {
01385 dest += x;
01386 for (; height > 0; --height) {
01387 *dest = *src;
01388 src += bytesperpix;
01389 dest -= xdim;
01390 }
01391 }
01392 else if (bpp == 4) {
01393 dest += x / 2;
01394 if (x & 1) {
01395 for (; height > 0; --height) {
01396 *dest &= 0xf0;
01397 *dest |= *src & 0x0f;
01398 src += bytesperpix;
01399 dest -= xdim;
01400 }
01401 }
01402 else {
01403 for (; height > 0; --height) {
01404 *dest &= 0x0f;
01405 *dest |= *src << 4;
01406 src += bytesperpix;
01407 dest -= xdim;
01408 }
01409 }
01410 }
01411 else if (bpp == 2) {
01412 dest += x / 4;
01413 bit = (INT8) (x % 4);
01414 bit = 6 - bit - bit;
01415 pixel = ~(3 << bit);
01416 for (; height > 0; --height) {
01417
01418 *dest = (*dest & pixel) | ((*src & 3) << bit);
01419 src += bytesperpix;
01420 dest -= xdim;
01421 }
01422 }
01423 else {
01424 dest += x / 8;
01425 bit = (INT8) (x % 8);
01426 bit = 7 - bit;
01427 pixel = ~(1 << bit);
01428 for (; height > 0; --height) {
01429
01430 *dest = (*dest & pixel) | ((*src & 1) << bit);
01431 src += bytesperpix;
01432 dest -= xdim;
01433 }
01434 }
01435 }
01436
01437
01443 void IMAGE::check_legal_access(
01444 INT32 x,
01445 INT32 y,
01446 INT32 xext
01447 ) {
01448 if (x < 0 || x >= xsize || y < 0 || y >= ysize || x + xext > xsize)
01449 BADIMAGECOORDS.error ("IMAGE::check_legal_access",
01450 ABORT, "(%d+%d,%d)", x, xext, y);
01451 if (y >= ymax)
01452 BADIMAGESEEK.error ("IMAGE::check_legal_access", ABORT, "(%d,%d)", x, y);
01453 if (y < ymin)
01454 bufread(y);
01455 }
01456
01457
01467 void
01468 IMAGE::convolver (
01469 INT32 win_width,
01470 INT32 win_height,
01471 void (*convolve) (
01472 UINT8 ** pixels,
01473 UINT8 bytespp,
01474 INT32 win_wd,
01475 INT32 win_ht,
01476 UINT8 ret_white_value,
01477 UINT8 * result)
01478 ) {
01479 IMAGELINE new_row;
01480 IMAGELINE *old_rows;
01481 INT32 oldest_imline;
01482 UINT8 **window;
01483 UINT8 **winmax;
01484 UINT8 **win;
01485 INT32 current_row;
01486 INT32 current_col;
01487 INT32 row = 0;
01488
01489 INT32 i, j;
01490 UINT8 *pix;
01491 UINT8 *max;
01492 INT32 xmargin = win_width / 2;
01493 INT32 ymargin = win_height / 2;
01494 UINT8 white = get_white_level ();
01495 const UINT8 max_white = 255;
01496 float white_scale = (float) 255 / get_white_level ();
01497
01498 if (((win_width % 2) == 0) ||
01499 ((win_height % 2) == 0) ||
01500 (win_height < 3) ||
01501 (win_width < 3) || (win_height > ysize / 2) || (win_width > xsize / 2))
01502 BADWINDOW.error ("IMAGE::convolver",
01503 ABORT, "(%d x %d)", win_width, win_height);
01504
01505 new_row.init (xsize * bytespp);
01506 new_row.set_bpp (bpp);
01507 old_rows = new IMAGELINE[win_height];
01508 for (i = 0; i < win_height; i++) {
01509 old_rows[i].init ((xsize + 2 * xmargin) * bytespp);
01510 old_rows[i].set_bpp (bpp);
01511 }
01512
01513 window = (UINT8 **) alloc_mem (win_height * sizeof (UINT8 *));
01514 winmax = window + win_height;
01515
01516
01517 for (oldest_imline = 0; oldest_imline < ymargin; oldest_imline++) {
01518 pix = old_rows[oldest_imline].pixels;
01519 max = pix + (xsize + 2 * xmargin) * bytespp;
01520 while (pix < max)
01521 *pix++ = max_white;
01522 }
01523
01524 for (; oldest_imline < win_height - 1; oldest_imline++) {
01525 get_line (0, row++, xsize, &old_rows[oldest_imline], xmargin);
01526 if (max_white != white) {
01527 pix = old_rows[oldest_imline].pixels;
01528 max = pix + (xsize + 2 * xmargin) * bytespp;
01529 while (pix < max) {
01530 *pix = (UINT8) (*pix * white_scale);
01531 ++pix;
01532 }
01533 }
01534 }
01535
01536
01537
01538 for (current_row = 0; current_row < ysize;) {
01539
01540 if (row < ysize) {
01541 get_line (0, row++, xsize, &old_rows[oldest_imline], xmargin);
01542 if (max_white != white) {
01543 pix = old_rows[oldest_imline].pixels;
01544 max = pix + (xsize + 2 * xmargin) * bytespp;
01545 while (pix < max) {
01546 *pix = (UINT8) (*pix * white_scale);
01547 ++pix;
01548 }
01549 }
01550 }
01551 else {
01552 pix = old_rows[oldest_imline].pixels;
01553 max = pix + (xsize + 2 * xmargin) * bytespp;
01554 while (pix < max)
01555 *pix++ = max_white;
01556 }
01557 oldest_imline++;
01558 if (oldest_imline >= win_height)
01559 oldest_imline = 0;
01560
01561
01562 pix = new_row.pixels;
01563 for (current_col = 0; current_col < xsize;) {
01564
01565 if (current_col == 0) {
01566 j = oldest_imline;
01567 for (i = 0; i < win_height; i++) {
01568 window[i] = old_rows[j++].pixels;
01569 if (j >= win_height)
01570 j = 0;
01571 }
01572 }
01573 else {
01574 for (win = window; win < winmax; (*win++) += bytespp);
01575
01576 }
01577
01578 convolve(window, bytespp, win_width, win_height, white, pix);
01579 pix += bytespp;
01580 current_col++;
01581 }
01582
01583 put_line (0, current_row, xsize, &new_row, 0);
01584 new_row.init ();
01585 new_row.set_bpp (bpp);
01586 current_row++;
01587 }
01588 }