image/imgs.cpp

Go to the documentation of this file.
00001 
00020 #include          "mfcpch.h"     //precompiled headers
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       /*number of fixed colours */
00039 #define MIN_4BIT      48         /*4bpp range */
00040 #define MAX_4BIT      64
00041 #define MIN_6BIT      64         /*6bpp range */
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() {  //construct an image
00067   bpp = 0;                       //all illegal
00068   fd = -1;
00069   image = NULL;
00070   photo_interp = 1;
00071   res = image_default_resolution;
00072 }
00073 
00074 
00080 IMAGE & IMAGE::operator= (       //assignment
00081 IMAGE & source                   //source image
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;    //copy everything
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;        //source now captured
00102   source.fd = -1;
00103 
00104   return *this;
00105 }
00106 
00107 
00111 INT8 IMAGE::create(                     //get rest of image
00112                    INT32 x,             //x size required
00113                    INT32 y,             //ysize required
00114                    INT8 bits_per_pixel  //bpp required
00115                   ) {
00116   UINT8 *pixels;                 //memory for image
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                                  //allocate to image
00127   this->capture (pixels, x, y, bits_per_pixel);
00128   captured = FALSE;
00129   res = image_default_resolution;
00130   return 0;                      //success
00131 }
00132 
00133 
00137 void IMAGE::destroy() {  //get rid of image
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(                     //get rest of image
00155                     UINT8 *pixels,       //image memory
00156                     INT32 x,             //x size required
00157                     INT32 y,             //ysize required
00158                     INT8 bits_per_pixel  //bpp required
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;                //assign image area
00172   ymin = 0;
00173   ymax = bufheight;              //read it all
00174   captured = TRUE;
00175   res = image_default_resolution;
00176   return 0;                      //success
00177 }
00178 
00179 
00183 UINT8 IMAGE::pixel(          //get rest of image
00184                    INT32 x,  //x coord
00185                    INT32 y   //y coord
00186                   ) {
00187   if (x < 0)
00188     x = 0;                       //silently clip
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(                     //get rest of image
00220                              INT32 x,             //x size required
00221                              INT32 y,             //ysize required
00222                              INT8 bits_per_pixel  //bpp required
00223                             ) {
00224   if (x <= 0 || y <= 0) {
00225     BADIMAGESIZE.error ("check_legal_image_size", LOG, "(%d,%d)", x, y);
00226     return -1;                   //failed
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                                  //bytes per line
00235   return COMPUTE_IMAGE_XDIM (x, bits_per_pixel);
00236 }
00237 
00238 
00245 DLLSYM void copy_sub_image(                   //copy rectangle
00246                            IMAGE *source,     //source image
00247                            INT32 xstart,      //start coords
00248                            INT32 ystart,
00249                            INT32 xext,        //extent to copy
00250                            INT32 yext,
00251                            IMAGE *dest,       //destination image
00252                            INT32 xdest,       //destination coords
00253                            INT32 ydest,
00254                            BOOL8 adjust_grey  //shift to new bpp
00255                           ) {
00256   IMAGELINE copyline;            //copy of line
00257   UINT8 *copy;                   //source pointer
00258   INT8 shift;                    //shift factor
00259   INT32 pixel;                   //pixel index
00260   INT32 y;                       //line index
00261   INT32 yoffset;                 //current adjusted offset
00262   INT32 bytesize;                //no of bytes to copy
00263   INT32 srcppb;                  //pixels per byte
00264   BOOL8 aligned;
00265 
00266   if (xstart < 0 || ystart < 0 || xdest < 0 || ydest < 0)
00267     return;
00268   if (xext <= 0)
00269     xext = source->xsize;        //default to all
00270   if (xext > source->xsize - xstart)
00271                                  //clip to smallest
00272       xext = source->xsize - xstart;
00273   if (xext > dest->xsize - xdest)
00274     xext = dest->xsize - xdest;
00275   if (yext <= 0)
00276     yext = source->ysize;        //default to all
00277   if (yext > source->ysize - ystart)
00278                                  //clip to smallest
00279       yext = source->ysize - ystart;
00280   if (yext > dest->ysize - ydest)
00281     yext = dest->ysize - ydest;
00282   if (xext <= 0 || yext <= 0)
00283     return;                      //nothing to do
00284 
00285   srcppb = 8 / source->bpp;      //pixels per byte
00286   if (source->bpp == dest->bpp || !adjust_grey)
00287     shift = 0;                   //no adjustment
00288   else {
00289     shift = source->bps - dest->bps;
00290     if (shift < 0)
00291       shift = -shift;            //keep positive
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;               //top down
00302     else
00303       yoffset = yext - y - 1;    //bottom up
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       //get bytes per line
00309       if (srcppb == 0)
00310                                  //do cheap move
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                                  //do cheap move
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           &copyline);
00327       }
00328       else if (source->bpp < dest->bpp) {
00329         source->get_line (xstart, ystart + yoffset, xext, &copyline, 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                                  //scale up
00342             *copy = (*copy << shift) | *copy;
00343           }
00344         }
00345         else {
00346           for (pixel = 0, copy = copyline.pixels; pixel < xext;
00347             pixel++)
00348           *copy++ <<= shift;     //scale up
00349         }
00350       }
00351       else {
00352         source->get_line (xstart, ystart + yoffset, xext, &copyline, 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;     //scale down
00364         }
00365       }
00366       dest->put_line (xdest, ydest + yoffset, xext, &copyline, 0);
00367     }
00368   }
00369 }
00370 
00371 
00379 DLLSYM void enlarge_sub_image(                   //enlarge rectangle
00380                               IMAGE *source,     //source image
00381                               INT32 xstart,      //scaled start coords
00382                               INT32 ystart,
00383                               IMAGE *dest,       //destination image
00384                               INT32 xdest,       //dest coords
00385                               INT32 ydest,
00386                               INT32 xext,        //destination extent
00387                               INT32 yext,
00388                               INT32 scale,       //scale factor
00389                               BOOL8 adjust_grey  //shift to new bpp
00390                              ) {
00391   INT8 shift;                    //shift factor
00392   UINT8 pixel;                   //current pixel
00393   INT32 srcext;                  //source extent
00394   INT32 xoffset;                 //column index
00395   INT32 yoffset;                 //line index
00396   INT32 xindex, yindex;          //index in super pixel
00397   INT32 startxindex;             //initial x index
00398   INT32 xscale;                  //x scale factor
00399   UINT8 *src;                    //source pixels
00400   UINT8 *destpix;                //dest pixels
00401   IMAGELINE copyline;            //copy of line
00402   IMAGELINE bigline;             //expanded line
00403 
00404   if (xstart < 0 || ystart < 0 || xdest < 0 || ydest < 0)
00405     return;
00406 
00407   if (xext <= 0)
00408     xext = dest->xsize;          //default to all
00409   if (xext > source->xsize * scale - xstart)
00410                                  //clip to smallest
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;          //default to all
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;                      //nothing to do
00422 
00423   xindex = xstart % scale;       //offset in super pixel
00424   startxindex = xindex;
00425   yindex = ystart % scale;
00426                                  //no of source pixels
00427   srcext = (xext + xindex + scale - 1) / scale;
00428   xstart /= scale;               //actual start
00429   ystart /= scale;
00430   if (adjust_grey) {
00431     shift = dest->bps - source->bps;
00432   }
00433   else
00434     shift = 0;                   //no adjustment
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, &copyline);
00442     src = copyline.pixels;
00443     destpix = bigline.pixels;
00444     xscale = scale;              //enlargement factor
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                                  //clip to dest limit
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;    //duplicate 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(                   //reduce rectangle
00497                                   IMAGE *source,     //source image
00498                                   INT32 xstart,      //start coords
00499                                   INT32 ystart,
00500                                   INT32 xext,        //extent to copy
00501                                   INT32 yext,
00502                                   IMAGE *dest,       //destination image
00503                                   INT32 xdest,       //destination coords
00504                                   INT32 ydest,
00505                                   INT32 scale,       //reduction factor
00506                                   BOOL8 adjust_grey  //shift to new bpp
00507                                  ) {
00508   INT8 shift;                    //shift factor
00509   INT32 xfactor;                 //run on x coord
00510   INT32 divisor;                 //total cell area
00511   INT32 xindex, yindex;          //into averaging square
00512   INT32 xcoord;                  //current x coord
00513   INT32 destext;                 //destination size
00514   INT32 yoffset;                 //current adjusted offset
00515   UINT8 *pixel;                  //ptr to source pixels
00516   INT32 *sums;                   //ptr to sums array
00517   IMAGELINE copyline;            //copy of line
00518   INT32 *linesums;               //averaging sums
00519 
00520   if (xstart < 0 || ystart < 0 || xdest < 0 || ydest < 0)
00521     return;
00522   if (xext <= 0)
00523     xext = source->xsize;        //default to all
00524   if (xext > source->xsize - xstart)
00525                                  //clip to smallest
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;        //default to all
00531   if (yext > source->ysize - ystart)
00532                                  //clip to smallest
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;                      //nothing to do
00538 
00539   xfactor = xext % scale;        //left overs
00540   if (xfactor == 0)
00541     xfactor = scale;
00542                                  //destination pixels
00543   destext = (xext + scale - 1) / scale;
00544   if (adjust_grey)
00545                                  //shift factor
00546     shift = dest->bps - source->bps;
00547   else
00548     shift = 0;                   //no adjustment
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;      //zero sums
00556     for (yindex = 0; yindex < scale
00557     && ystart + yoffset < source->ysize; yindex += 3) {
00558       source->fast_get_line (xstart, ystart + yoffset, xext, &copyline);
00559       pixel = copyline.pixels;   //start of line
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;          //correct position
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--;             //correct position
00588         }
00589         for (xindex = 0; xindex < xfactor; xindex += 2) {
00590           *sums += *pixel;
00591           pixel += 2;
00592         }
00593       }
00594       yoffset += 3;              //every 3 lines
00595     }
00596     if (yindex > scale)
00597       yoffset -= yindex - scale; //back on right scale
00598     copyline.init ();            //set pixels back to array
00599     copyline.bpp = source->bpp;
00600     pixel = copyline.pixels;
00601                                  //pixels in block
00602     divisor = ((yindex + 2) / 3) * ((scale + 1) / 2);
00603     if (shift <= 0) {
00604       divisor <<= (-shift);      //do greyscale correction
00605       for (sums = linesums, xindex = (destext - 1) * source->bytespp;
00606         xindex > 0; xindex--)
00607                                  //turn to destination value
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       //lastone different
00613     }
00614     else {
00615       for (sums = linesums, xindex = (destext - 1) * source->bytespp;
00616         xindex > 0; xindex--)
00617       *pixel++ = (UINT8) ((*sums++ << shift) / divisor);
00618       //destination value
00619       for (xindex = source->bytespp; xindex > 0; xindex--)
00620                                  //last one different
00621         *pixel++ = (*(sums++) << shift) /
00622          (((yindex + 2) / 3) * ((xfactor + 1) / 2));
00623     }
00624                                  //put in destination
00625     dest->put_line (xdest, ydest, destext, &copyline, 0);
00626   }
00627   delete linesums;
00628 }
00629 
00630 
00637 DLLSYM void reduce_sub_image(                   //reduce rectangle
00638                              IMAGE *source,     //source image
00639                              INT32 xstart,      //start coords
00640                              INT32 ystart,
00641                              INT32 xext,        //extent to copy
00642                              INT32 yext,
00643                              IMAGE *dest,       //destination image
00644                              INT32 xdest,       //destination coords
00645                              INT32 ydest,
00646                              INT32 scale,       //reduction factor
00647                              BOOL8 adjust_grey  //shift to new bpp
00648                             ) {
00649   INT8 shift;                    //shift factor
00650   INT32 xfactor;                 //run on x coord
00651   INT32 divisor;                 //total cell area
00652   INT32 div2;                    //total cell area divided by 2
00653   INT32 xindex, yindex;          //into averaging square
00654   INT32 xcoord;                  //current x coord
00655   INT32 destext;                 //destination size
00656   INT32 yoffset;                 //current adjusted offset
00657   UINT8 *pixel;                  //ptr to source pixels
00658   INT32 *sums;                   //ptr to sums array
00659   IMAGELINE copyline;            //copy of line
00660   INT32 *linesums;               //averaging sums
00661 
00662   if (xstart < 0 || ystart < 0 || xdest < 0 || ydest < 0)
00663     return;
00664   if (xext <= 0)
00665     xext = source->xsize;        //default to all
00666   if (xext > source->xsize - xstart)
00667                                  //clip to smallest
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;        //default to all
00673   if (yext > source->ysize - ystart)
00674                                  //clip to smallest
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;                      //nothing to do
00680 
00681   xfactor = xext % scale;        //left overs
00682   if (xfactor == 0)
00683     xfactor = scale;
00684                                  //destination pixels
00685   destext = (xext + scale - 1) / scale;
00686   if (adjust_grey)
00687                                  //shift factor
00688     shift = dest->bps - source->bps;
00689   else
00690     shift = 0;                   //no adjustment
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;      //zero sums
00698     for (yindex = 0; yindex < scale && ystart + yoffset < source->ysize;
00699     yindex++) {
00700       source->fast_get_line (xstart, ystart + yoffset, xext, &copyline);
00701       pixel = copyline.pixels;   //start of line
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++;                 //next line
00727     }
00728     copyline.init ();            //set pixels back to array
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);      //do greyscale correction
00740       div2 = divisor / 2;
00741       for (sums = linesums, xindex = (destext - 1) * source->bytespp;
00742         xindex > 0; xindex--)
00743       *pixel++ = (UINT8) ((div2 + *sums++) / divisor);
00744       //turn to destination value
00745       div2 = (yindex * xfactor << (-shift)) / 2;
00746       for (xindex = source->bytespp; xindex > 0; xindex--)
00747         *pixel++ =
00748           (UINT8) ((div2 + *sums++) / (yindex * xfactor << (-shift)));
00749       //lastone different
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       //destination value
00757       div2 = (yindex * xfactor) / 2;
00758       for (xindex = source->bytespp; xindex > 0; xindex--)
00759         *pixel++ =
00760           (UINT8) ((div2 + (*sums++ << shift)) / (yindex * xfactor));
00761       //last one different
00762     }
00763                                  //put in destination
00764     dest->put_line (xdest, ydest, destext, &copyline, 0);
00765   }
00766   delete linesums;
00767 }
00768 
00769 
00773 DLLSYM void invert_image(              /*invert the image */
00774                          IMAGE *image  /*image ot invert */
00775                         ) {
00776   UINT8 mask;                    //bit mask
00777   UINT8 bytespp;                 //bytes per pixel
00778   INT32 xsize, ysize;            /*size of image */
00779   INT32 xindex, yindex;          /*index into image */
00780   UINT8 *pixel;                  /*current pixel */
00781   IMAGELINE line;                /*line of image */
00782 
00783   bytespp = image->get_bpp () == 24 ? 3 : 1;
00784   xsize = image->get_xsize ();   /*find sizes */
00785   ysize = image->get_ysize ();
00786                                  //pixel mask
00787   mask = (1 << image->get_bpp ()) - 1;
00788                                  /*do each line */
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;  //invert image only
00794       ++pixel;
00795     }
00796                                  /*put it back */
00797     image->fast_put_line (0, yindex, xsize, &line);
00798   }
00799 }
00800 
00801 
00805 DLLSYM void bias_sub_image(                //bias rectangle
00806                            IMAGE *source,  //source image
00807                            INT32 xstart,   //start coords
00808                            INT32 ystart,
00809                            INT32 xext,     //extent to copy
00810                            INT32 yext,
00811                            UINT8 bias      //number to add
00812                           ) {
00813   IMAGELINE copyline;            //copy of line
00814   UINT8 *copy;                   //source pointer
00815   INT32 pixel;                   //pixel index
00816   INT32 y;                       //line index
00817   UINT8 bytespp;                 //bytes per pixel
00818 
00819   if (xstart < 0 || ystart < 0)
00820     return;
00821   if (xext <= 0)
00822     xext = source->get_xsize (); //default to all
00823   if (xext > source->get_xsize () - xstart)
00824                                  //clip to smallest
00825     xext = source->get_xsize () - xstart;
00826   if (yext <= 0)
00827     yext = source->get_ysize (); //default to all
00828   if (yext > source->get_ysize () - ystart)
00829                                  //clip to smallest
00830     yext = source->get_ysize () - ystart;
00831   if (xext <= 0 || yext <= 0)
00832     return;                      //nothing to do
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, &copyline);
00838     for (pixel = xext * bytespp, copy = copyline.pixels; pixel > 0;
00839       pixel--, copy++)
00840     *copy += bias;               //add bias
00841 
00842     source->fast_put_line (xstart, ystart + y, xext, &copyline);
00843   }
00844 }
00845 
00846 
00853 DLLSYM void starbase_to_normal(                     //copy rectangle
00854                                IMAGE *source,       //source image
00855                                INT32 xstart,        //start coords
00856                                INT32 ystart,
00857                                INT32 xext,          //extent to copy
00858                                INT32 yext,
00859                                IMAGE *dest,         //destination image
00860                                INT32 xdest,         //destination coords
00861                                INT32 ydest,
00862                                BOOL8 preserve_grey  //shift to new bpp
00863                               ) {
00864   IMAGELINE copyline;            //copy of line
00865   UINT8 *copy;                   //source pointer
00866   INT8 shift4;                   //shift factor
00867   INT8 shift6;                   //shift factor
00868   INT8 colour_shift;             //shift of colours
00869   UINT8 white_level;             //dest white value
00870   INT32 pixel;                   //pixel index
00871   INT32 y;                       //line index
00872   INT32 yoffset;                 //current adjusted offset
00873   INT8 srcppb;                   //pixels per byte
00874 
00875   if (xstart < 0 || ystart < 0 || xdest < 0 || ydest < 0)
00876     return;
00877   if (xext <= 0)
00878     xext = source->get_xsize (); //default to all
00879   if (xext > source->get_xsize () - xstart)
00880                                  //clip to smallest
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 (); //default to all
00886   if (yext > source->get_ysize () - ystart)
00887                                  //clip to smallest
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;                      //nothing to do
00893 
00894                                  //pixels per byte
00895   srcppb = 8 / source->get_bpp ();
00896   shift4 = 4 - dest->get_bpp (); //for different bpps
00897   shift6 = 6 - dest->get_bpp ();
00898                                  //for grey preserve
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;               //top down
00904     else
00905       yoffset = yext - y - 1;    //bottom up
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, &copyline, 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;   //black->white
00915         else
00916           *copy = 0;             //others->black
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;     //white the rest
00932       }
00933       copy++;
00934     }
00935     dest->put_line (xdest, ydest + yoffset, xext, &copyline, 0);
00936   }
00937 }
00938 
00939 
00948 void IMAGE::fast_get_line(                    //get image line
00949                           INT32 x,            //coord to start at
00950                           INT32 y,            //line to get
00951                           INT32 width,        //no of pixels to get
00952                           IMAGELINE *linebuf  //line to copy to
00953                          ) {
00954   if (width > 0 && bpp > 4) {
00955     check_legal_access(x, y, width); 
00956                                  //get pointer only
00957     linebuf->pixels = image + xdim * (ymax - 1 - y) + x * bytespp;
00958   }
00959   else
00960                                  //just copy it
00961     this->get_line (x, y, width, linebuf, 0);
00962   linebuf->bpp = bpp;
00963 }
00964 
00965 
00971 void IMAGE::get_line(                     //get image line
00972                      INT32 x,             //coord to start at
00973                      INT32 y,             //line to get
00974                      INT32 width,         //no of pixels to get
00975                      IMAGELINE *linebuf,  //line to copy to
00976                      INT32 margins        //size of margins
00977                     ) {
00978   UINT8 *src;                    //source pointer
00979   UINT8 *dest;                   //destination pointer
00980   UINT8 *unpacksrc;              //unpacking pointer
00981   INT8 bit;                      //bit index
00982   INT8 pixperbyte;               //pixels per byte
00983   UINT8 white;                   //white colour
00984   INT32 pixel;                   //pixel index
00985 
00986                                  //test coords
00987   this->check_legal_access (x, y, width);
00988   if (width > xsize - x)
00989     width = xsize - x;           //clip to image
00990   width *= bytespp;
00991   linebuf->init (width + margins * bytespp * 2);
00992   linebuf->bpp = bpp;
00993                                  //start of line
00994   src = image + xdim * (ymax - 1 - y);
00995   dest = linebuf->line;          //destination line
00996   linebuf->pixels = dest;
00997   white = (1 << bpp) - 1;        //max value of pixel
00998   for (pixel = margins * bytespp; pixel > 0; pixel--) {
00999     *dest++ = white;             //margins are white
01000   }
01001   if (width > 0) {
01002     if (bpp > 4) {
01003       src += x;                  //offset
01004                                  //easy way
01005       memmove (dest, src, (unsigned) width);
01006     }
01007     else if (bpp == 4) {
01008       src += x / 2;              //offset on line
01009       if (x & 1) {
01010                                  //get coded nibble
01011         *dest++ = bpp4table[*src++][1];
01012         width--;
01013       }
01014       while (width >= 2) {
01015                                  //get coded bits
01016         unpacksrc = bpp4table[*src++];
01017         *dest++ = *unpacksrc++;
01018         *dest++ = *unpacksrc++;  //copy nibbles
01019         width -= 2;
01020       }
01021       if (width) {
01022                                  //get coded nibble
01023         *dest++ = bpp4table[*src++][0];
01024       }
01025     }
01026     else if (bpp == 2) {
01027       pixperbyte = 4;
01028       src += x / 4;              //offset on line
01029       bit = (INT8) (x % 4);      //offset in byte
01030       width += bit;
01031       while (width > 0) {        //until all done
01032         if (width < pixperbyte)
01033                                  //less on last byte
01034           pixperbyte = (INT8) width;
01035                                  //get coded bits
01036         unpacksrc = &bpp2table[*src++][bit];
01037         for (; bit < pixperbyte; bit++)
01038           *dest++ = *unpacksrc++;//copy bytes
01039         width -= pixperbyte;
01040         bit = 0;
01041       }
01042     }
01043     else {
01044       pixperbyte = 8;
01045       src += x / 8;              //offset on line
01046       bit = (INT8) (x % 8);      //offset in byte
01047       width += bit;
01048       while (width > 0) {        //until all done
01049         if (width < pixperbyte)
01050                                  //less on last byte
01051           pixperbyte = (INT8) width;
01052                                  //get coded bits
01053         unpacksrc = &bpp1table[*src++][bit];
01054         for (; bit < pixperbyte; bit++)
01055           *dest++ = *unpacksrc++;//copy bytes
01056         width -= pixperbyte;
01057         bit = 0;
01058       }
01059     }
01060   }
01061   for (pixel = margins * bytespp; pixel > 0; pixel--) {
01062     *dest++ = white;             //margins are white
01063   }
01064 }
01065 
01066 
01072 void IMAGE::get_column(                     //get image column
01073                        INT32 x,             //coord to start at
01074                        INT32 y,             //line to get
01075                        INT32 height,        //no of pixels to get
01076                        IMAGELINE *linebuf,  //line to copy to
01077                        INT32 margins        //size of margins
01078                       ) {
01079   UINT8 *src;                    //source pointer
01080   UINT8 *dest;                   //destination pointer
01081   INT8 bit;                      //bit index
01082   INT8 pixperbyte;               //pixels per byte
01083   UINT8 white;                   //white colour
01084   INT32 pixel;                   //pixel index
01085 
01086                                  //test coords
01087   this->check_legal_access (x, y, 1);
01088                                  //test coords
01089   this->check_legal_access (x, y + height - 1, 1);
01090   if (height > ysize - y)
01091     height = ysize - y;          //clip to image
01092   linebuf->init (height * bytespp + margins * bytespp * 2);
01093                                  //start of line
01094   src = image + xdim * (ymax - 1 - y);
01095   dest = linebuf->line;          //destination line
01096   linebuf->pixels = dest;
01097   white = (1 << bpp) - 1;        //max value of pixel
01098   for (pixel = margins * bytespp; pixel > 0; pixel--) {
01099     *dest++ = white;             //margins are white
01100   }
01101   if (height > 0) {
01102     if (bpp == 24) {
01103       src += x * bytespp;        //offset
01104       for (; height > 0; --height) {
01105         *dest++ = *src;          //copy bytes
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;          //copy bytes
01115         src -= xdim;
01116       }
01117     }
01118     else if (bpp == 4) {
01119       src += x / 2;              //offset on line
01120       if (x & 1) {
01121         for (; height > 0; --height) {
01122                                  //get coded nibble
01123           *dest++ = bpp4table[*src][1];
01124           src -= xdim;
01125         }
01126       }
01127       else {
01128         for (; height > 0; --height) {
01129                                  //get coded nibble
01130           *dest++ = bpp4table[*src][0];
01131           src -= xdim;
01132         }
01133       }
01134     }
01135     else if (bpp == 2) {
01136       pixperbyte = 4;
01137       src += x / 4;              //offset on line
01138       bit = (INT8) (x % 4);      //offset in byte
01139       for (; height > 0; --height) {
01140                                  //get coded bits
01141         *dest++ = bpp2table[*src][bit];
01142         src -= xdim;
01143       }
01144     }
01145     else {
01146       pixperbyte = 8;
01147       src += x / 8;              //offset on line
01148       bit = (INT8) (x % 8);      //offset in byte
01149       for (; height > 0; --height) {
01150                                  //get coded bits
01151         *dest++ = bpp1table[*src][bit];
01152         src -= xdim;
01153       }
01154     }
01155   }
01156   for (pixel = margins * bytespp; pixel > 0; pixel--) {
01157     *dest++ = white;             //margins are white
01158   }
01159 }
01160 
01161 
01168 void IMAGE::fast_put_line(                    //put image line
01169                           INT32 x,            //coord to start at
01170                           INT32 y,            //line to get
01171                           INT32 width,        //no of pixels to put
01172                           IMAGELINE *linebuf  //line to copy to
01173                          ) {
01174   if (width > 0 && (bpp <= 4 || linebuf->pixels == linebuf->line))
01175                                  //just copy it
01176     put_line (x, y, width, linebuf, 0);
01177 }
01178 
01179 
01185 void IMAGE::put_line(                     //put image line
01186                      INT32 x,             //coord to start at
01187                      INT32 y,             //line to get
01188                      INT32 width,         //no of pixels to get
01189                      IMAGELINE *linebuf,  //line to copy to
01190                      INT32 margins        //margins in buffer
01191                     ) {
01192   UINT8 *src;                    //source pointer
01193   UINT8 *dest;                   //destination pointer
01194   INT8 bit;                      //bit index
01195   UINT8 pixel;                   //collected bits
01196   INT8 pixperbyte;               //pixels in a byte
01197   INT8 bytesperpix;              //in source
01198 
01199   this->check_legal_access (x, y, width);
01200   if (width > xsize - x)
01201     width = xsize - x;           //clip to image
01202   if (width <= 0)
01203     return;                      //nothing to do
01204                                  //source line
01205   src = linebuf->pixels + margins;
01206                                  //start of line
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;                   //offset
01233     if (linebuf->bpp == 24) {
01234       while (width > 0) {
01235         *dest++ = *src;
01236         src += 3;
01237         width--;
01238       }
01239     }
01240     else
01241                                  //easy way
01242       memmove (dest, src, (unsigned) width);
01243   }
01244   else if (bpp == 4) {
01245     dest += x / 2;               //offset on line
01246     if (x & 1) {
01247       *dest &= 0xf0;             //clean odd byte
01248       *dest++ |= *src & 0x0f;    //and copy it
01249       src += bytesperpix;
01250       width--;
01251     }
01252     while (width >= 2) {
01253       pixel = *src << 4;         //left pixel
01254       src += bytesperpix;
01255       pixel |= *src & 0x0f;      //right pixel
01256       src += bytesperpix;
01257       *dest++ = pixel;
01258       width -= 2;
01259     }
01260     if (width) {
01261       *dest &= 0x0f;             //clean odd byte
01262       *dest |= *src << 4;
01263     }
01264   }
01265   else if (bpp == 2) {
01266     pixperbyte = 4;
01267     dest += x / 4;               //offset on line
01268     bit = (INT8) (x % 4);        //offset in byte
01269     width += bit;
01270     pixel = *dest >> (8 - bit - bit);
01271     while (width >= 4) {         //until all done
01272       for (; bit < 4; bit++) {
01273         pixel <<= 2;             //make space for new one
01274         pixel |= *src & 3;
01275         src += bytesperpix;
01276       }
01277       *dest++ = pixel;           //new pixel
01278       width -= 4;
01279       bit = 0;
01280     }
01281     if (width > 0) {             //until all done
01282       for (bit = 0; bit < width; bit++) {
01283         pixel <<= 2;             //make space for new one
01284         pixel |= *src & 3;
01285         src += bytesperpix;
01286       }
01287       pixel <<= (8 - bit - bit); //shift rest
01288                                  //keep trainling bits
01289       pixel |= *dest & ((1 << (8 - bit - bit)) - 1);
01290       *dest++ = pixel;           //new pixel
01291     }
01292   }
01293   else {
01294     pixperbyte = 8;
01295     dest += x / 8;               //offset on line
01296     bit = (INT8) (x % 8);        //offset in byte
01297     width += bit;
01298     pixel = *dest >> (8 - bit);
01299     while (width >= 8) {         //until all done
01300       for (; bit < 8; bit++) {
01301         pixel <<= 1;             //make space for new one
01302         pixel |= *src & 1;
01303         src += bytesperpix;
01304       }
01305       *dest++ = pixel;           //new pixel
01306       width -= 8;
01307       bit = 0;
01308     }
01309     width -= bit;
01310     if (width > 0) {             //until all done
01311       while (width > 0) {
01312         pixel <<= 1;             //make space for new one
01313         pixel |= *src & 1;
01314         src += bytesperpix;
01315         bit++;
01316         width--;
01317       }
01318       pixel <<= (8 - bit);       //shift rest
01319                                  //keep trainling bits
01320       pixel |= *dest & ((1 << (8 - bit)) - 1);
01321       *dest++ = pixel;           //new pixel
01322     }
01323   }
01324 }
01325 
01326 
01332 void IMAGE::put_column(                     //put image column
01333                        INT32 x,             //coord to start at
01334                        INT32 y,             //line to get
01335                        INT32 height,        //no of pixels to get
01336                        IMAGELINE *linebuf,  //line to copy to
01337                        INT32 margins        //margins in buffer
01338                       ) {
01339   UINT8 *src;                    //source pointer
01340   UINT8 *dest;                   //destination pointer
01341   INT8 bit;                      //bit index
01342   UINT8 pixel;                   //collected bits
01343   INT8 bytesperpix;              //in source
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;          //clip to image
01349   if (height <= 0)
01350     return;                      //nothing to do
01351                                  //source line
01352   src = linebuf->pixels + margins;
01353                                  //start of line
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;                   //offset
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;               //offset on line
01394     if (x & 1) {
01395       for (; height > 0; --height) {
01396         *dest &= 0xf0;           //clean odd byte
01397         *dest |= *src & 0x0f;    //and copy it
01398         src += bytesperpix;
01399         dest -= xdim;
01400       }
01401     }
01402     else {
01403       for (; height > 0; --height) {
01404         *dest &= 0x0f;           //clean odd byte
01405         *dest |= *src << 4;
01406         src += bytesperpix;
01407         dest -= xdim;
01408       }
01409     }
01410   }
01411   else if (bpp == 2) {
01412     dest += x / 4;               //offset on line
01413     bit = (INT8) (x % 4);        //offset in byte
01414     bit = 6 - bit - bit;         //bit shift
01415     pixel = ~(3 << bit);         //mask
01416     for (; height > 0; --height) {
01417                                  //change 2 bits
01418       *dest = (*dest & pixel) | ((*src & 3) << bit);
01419       src += bytesperpix;
01420       dest -= xdim;
01421     }
01422   }
01423   else {
01424     dest += x / 8;               //offset on line
01425     bit = (INT8) (x % 8);        //offset in byte
01426     bit = 7 - bit;
01427     pixel = ~(1 << bit);
01428     for (; height > 0; --height) {
01429                                  //change 1 bit
01430       *dest = (*dest & pixel) | ((*src & 1) << bit);
01431       src += bytesperpix;
01432       dest -= xdim;
01433     }
01434   }
01435 }
01436 
01437 
01443 void IMAGE::check_legal_access(            //check coords are legal
01444                                INT32 x,    //coords to check
01445                                INT32 y,
01446                                INT32 xext  //xextent
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);  //read some more
01455 }
01456 
01457 
01467 void
01468 IMAGE::convolver (               //Map fn over window
01469 INT32 win_width,                 //Window width
01470 INT32 win_height,                //Window height
01471 void (*convolve) (               //Conv Function
01472 UINT8 ** pixels,                 //Of window
01473 UINT8 bytespp,                   //1 or 3 for colour
01474 INT32 win_wd,                    //Window width
01475 INT32 win_ht,                    //Window height
01476 UINT8 ret_white_value,           //White value to RETURN
01477 UINT8 * result)                  //Ptr to result pix
01478 ) {
01479   IMAGELINE new_row;             //Replacement pixels
01480   IMAGELINE *old_rows;           //Rows being processed
01481   INT32 oldest_imline;           //Next imline to replace
01482   UINT8 **window;                //ptrs to pixel rows
01483   UINT8 **winmax;                //ptrs to pixel rows
01484   UINT8 **win;                   //ptrs to pixel rows
01485   INT32 current_row;             //Row being calculated
01486   INT32 current_col;             //Col being calculated
01487   INT32 row = 0;                 //Next row to get
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   /* Make bottom border */
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   /* Initialise remaining rows but one*/
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   /* Image Processing */
01537 
01538   for (current_row = 0; current_row < ysize;) {
01539     /* Get next row and re-initialise window array */
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     /* Process line */
01562     pix = new_row.pixels;
01563     for (current_col = 0; current_col < xsize;) {
01564       /* Set up window ptrs */
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         //Move along rows
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 }

Generated on Wed Feb 28 19:49:11 2007 for Tesseract by  doxygen 1.5.1