• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kviewshell

GBitmap.cpp

Go to the documentation of this file.
00001 //C-  -*- C++ -*-
00002 //C- -------------------------------------------------------------------
00003 //C- DjVuLibre-3.5
00004 //C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
00005 //C- Copyright (c) 2001  AT&T
00006 //C-
00007 //C- This software is subject to, and may be distributed under, the
00008 //C- GNU General Public License, Version 2. The license should have
00009 //C- accompanied the software or you may obtain a copy of the license
00010 //C- from the Free Software Foundation at http://www.fsf.org .
00011 //C-
00012 //C- This program is distributed in the hope that it will be useful,
00013 //C- but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //C- GNU General Public License for more details.
00016 //C- 
00017 //C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library
00018 //C- distributed by Lizardtech Software.  On July 19th 2002, Lizardtech 
00019 //C- Software authorized us to replace the original DjVu(r) Reference 
00020 //C- Library notice by the following text (see doc/lizard2002.djvu):
00021 //C-
00022 //C-  ------------------------------------------------------------------
00023 //C- | DjVu (r) Reference Library (v. 3.5)
00024 //C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
00025 //C- | The DjVu Reference Library is protected by U.S. Pat. No.
00026 //C- | 6,058,214 and patents pending.
00027 //C- |
00028 //C- | This software is subject to, and may be distributed under, the
00029 //C- | GNU General Public License, Version 2. The license should have
00030 //C- | accompanied the software or you may obtain a copy of the license
00031 //C- | from the Free Software Foundation at http://www.fsf.org .
00032 //C- |
00033 //C- | The computer code originally released by LizardTech under this
00034 //C- | license and unmodified by other parties is deemed "the LIZARDTECH
00035 //C- | ORIGINAL CODE."  Subject to any third party intellectual property
00036 //C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
00037 //C- | non-exclusive license to make, use, sell, or otherwise dispose of 
00038 //C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
00039 //C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
00040 //C- | General Public License.   This grant only confers the right to 
00041 //C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
00042 //C- | the extent such infringement is reasonably necessary to enable 
00043 //C- | recipient to make, have made, practice, sell, or otherwise dispose 
00044 //C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
00045 //C- | any greater extent that may be necessary to utilize further 
00046 //C- | modifications or combinations.
00047 //C- |
00048 //C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
00049 //C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
00050 //C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
00051 //C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
00052 //C- +------------------------------------------------------------------
00053 // 
00054 // $Id: GBitmap.cpp,v 1.10 2004/04/17 23:56:11 leonb Exp $
00055 // $Name: release_3_5_15 $
00056 
00057 #ifdef HAVE_CONFIG_H
00058 # include "config.h"
00059 #endif
00060 #if NEED_GNUG_PRAGMAS
00061 # pragma implementation
00062 #endif
00063 
00064 #include "GBitmap.h"
00065 #include "ByteStream.h"
00066 #include "GRect.h"
00067 #include "GString.h"
00068 #include "GThreads.h"
00069 #include "GException.h"
00070 #include <string.h>
00071 
00072 // File "$Id: GBitmap.cpp,v 1.10 2004/04/17 23:56:11 leonb Exp $"
00073 // - Author: Leon Bottou, 05/1997
00074 
00075 
00076 #ifdef HAVE_NAMESPACES
00077 namespace DJVU {
00078 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
00079 }
00080 #endif
00081 #endif
00082 
00083 // ----- constructor and destructor
00084 
00085 GBitmap::~GBitmap()
00086 {
00087 }
00088 
00089 void
00090 GBitmap::destroy(void)
00091 {
00092   gbytes_data.resize(0);
00093   bytes = 0;
00094   grle.resize(0);
00095   grlerows.resize(0);
00096   rlelength = 0;
00097 }
00098 
00099 GBitmap::GBitmap()
00100   : nrows(0), ncolumns(0), border(0), 
00101     bytes_per_row(0), grays(0), bytes(0), gbytes_data(bytes_data), 
00102     grle(rle), grlerows(rlerows), rlelength(0),
00103     monitorptr(0)
00104 {
00105 }
00106 
00107 GBitmap::GBitmap(int nrows, int ncolumns, int border)
00108   : nrows(0), ncolumns(0), border(0), 
00109     bytes_per_row(0), grays(0), bytes(0), gbytes_data(bytes_data), 
00110     grle(rle), grlerows(rlerows), rlelength(0),
00111     monitorptr(0)
00112 {
00113   G_TRY
00114   { 
00115     init(nrows, ncolumns, border);
00116   }
00117   G_CATCH_ALL
00118   {
00119     destroy();
00120     G_RETHROW;
00121   }
00122   G_ENDCATCH;
00123 }
00124 
00125 GBitmap::GBitmap(ByteStream &ref, int border)
00126   : nrows(0), ncolumns(0), border(0), 
00127     bytes_per_row(0), grays(0), bytes(0), gbytes_data(bytes_data),
00128     grle(rle), grlerows(rlerows), rlelength(0),
00129     monitorptr(0)
00130 {
00131   G_TRY
00132   { 
00133     init(ref, border);
00134   }
00135   G_CATCH_ALL
00136   {
00137     destroy();
00138     G_RETHROW;
00139   }
00140   G_ENDCATCH;
00141 }
00142 
00143 GBitmap::GBitmap(const GBitmap &ref)
00144   : nrows(0), ncolumns(0), border(0), 
00145     bytes_per_row(0), grays(0), bytes(0), gbytes_data(bytes_data), 
00146     grle(rle), grlerows(rlerows), rlelength(0),
00147     monitorptr(0)
00148 {
00149   G_TRY
00150   { 
00151     init(ref, ref.border);
00152   }
00153   G_CATCH_ALL
00154   {
00155     destroy();
00156     G_RETHROW;
00157   }
00158   G_ENDCATCH;
00159 }
00160 
00161 GBitmap::GBitmap(const GBitmap &ref, int border)
00162   : nrows(0), ncolumns(0), border(0), 
00163     bytes_per_row(0), grays(0), bytes(0), gbytes_data(bytes_data),
00164     grle(rle), grlerows(rlerows), rlelength(0),
00165     monitorptr(0)
00166 {
00167   G_TRY
00168   { 
00169     init(ref, border);
00170   }
00171   G_CATCH_ALL
00172   {
00173     destroy();
00174     G_RETHROW;
00175   }
00176   G_ENDCATCH;
00177 }
00178 
00179 
00180 GBitmap::GBitmap(const GBitmap &ref, const GRect &rect, int border)
00181   : nrows(0), ncolumns(0), border(0), 
00182     bytes_per_row(0), grays(0), bytes(0), gbytes_data(bytes_data),
00183     grle(rle), grlerows(rlerows), rlelength(0),
00184     monitorptr(0)
00185 {
00186   G_TRY
00187   { 
00188     init(ref, rect, border);
00189   }
00190   G_CATCH_ALL
00191   {
00192     destroy();
00193     G_RETHROW;
00194   }
00195   G_ENDCATCH;
00196 }
00197 
00198 
00199 
00200 
00201 
00202 
00203 // ----- initialization
00204 
00205 void 
00206 GBitmap::init(int arows, int acolumns, int aborder)
00207 {
00208   GMonitorLock lock(monitor());
00209   destroy();
00210   grays = 2;
00211   nrows = arows;
00212   ncolumns = acolumns;
00213   border = aborder;
00214   bytes_per_row = ncolumns + border;
00215   int npixels = nrows * bytes_per_row + border;
00216   gzerobuffer=zeroes(bytes_per_row + border);
00217   if (npixels > 0) 
00218     {
00219       gbytes_data.resize(npixels);
00220       gbytes_data.clear();
00221       bytes = bytes_data;
00222     }
00223 }
00224 
00225 
00226 void 
00227 GBitmap::init(const GBitmap &ref, int aborder)
00228 {
00229   GMonitorLock lock(monitor());
00230   if (this != &ref) 
00231     {
00232       GMonitorLock lock(ref.monitor());
00233       init(ref.nrows, ref.ncolumns, aborder);
00234       grays = ref.grays;
00235       unsigned char *row = bytes_data+border;
00236       for (int n=0; n<nrows; n++, row+=bytes_per_row)
00237       memcpy( (void*)row, (void*)ref[n],  ncolumns );
00238     }
00239   else if (aborder > border)
00240     {
00241       minborder(aborder);
00242     }
00243 }
00244 
00245 
00246 void 
00247 GBitmap::init(const GBitmap &ref, const GRect &rect, int border)
00248 {
00249   GMonitorLock lock(monitor());
00250   // test bitmap physical equality
00251   if (this == &ref)
00252     {
00253       GBitmap tmp;
00254       tmp.grays = grays;
00255       tmp.border = border;
00256       tmp.bytes_per_row = bytes_per_row;
00257       tmp.ncolumns = ncolumns;
00258       tmp.nrows = nrows;
00259       tmp.bytes = bytes;
00260       tmp.gbytes_data.swap(gbytes_data);
00261       tmp.grle.swap(grle);
00262       bytes = 0 ;
00263       init(tmp, rect, border);
00264     }
00265   else
00266     {
00267       GMonitorLock lock(ref.monitor());
00268       // create empty bitmap
00269       init(rect.height(), rect.width(), border);
00270       grays = ref.grays;
00271       // compute destination rectangle
00272       GRect rect2(0, 0, ref.columns(), ref.rows() );
00273       rect2.intersect(rect2, rect);
00274       rect2.translate(-rect.xmin, -rect.ymin);
00275       // copy bits
00276       if (! rect2.isempty())
00277         {
00278           for (int y=rect2.ymin; y<rect2.ymax; y++)
00279             {
00280               unsigned char *dst = (*this)[y];
00281               const unsigned char *src = ref[y+rect.ymin] + rect.xmin;
00282               for (int x=rect2.xmin; x<rect2.xmax; x++)
00283                 dst[x] = src[x];
00284             }
00285         }
00286     }
00287 }
00288 
00289 
00290 void 
00291 GBitmap::init(ByteStream &ref, int aborder)
00292 {
00293   GMonitorLock lock(monitor());
00294   // Get magic number
00295   char magic[2];
00296   magic[0] = magic[1] = 0;
00297   ref.readall((void*)magic, sizeof(magic));
00298   char lookahead = '\n';
00299   int acolumns = read_integer(lookahead, ref);
00300   int arows = read_integer(lookahead, ref);
00301   init(arows, acolumns, aborder);
00302   // go reading file
00303   if (magic[0]=='P')
00304     {
00305       switch(magic[1])
00306         {
00307         case '1':
00308           grays = 2;
00309           read_pbm_text(ref); 
00310           return;
00311         case '2':
00312           grays = 1 + read_integer(lookahead, ref);
00313           if (grays > 256)
00314             G_THROW("Cannot read PGM with depth greater than 8 bits.");
00315           read_pgm_text(ref); 
00316           return;
00317         case '4':
00318           grays = 2;
00319           read_pbm_raw(ref); 
00320           return;
00321         case '5':
00322           grays = 1 + read_integer(lookahead, ref);
00323           if (grays > 256)
00324             grays = 256;
00325           read_pgm_raw(ref); 
00326           return;
00327         }
00328     }
00329   else if (magic[0]=='R')
00330     {
00331       switch(magic[1])
00332         {
00333         case '4':
00334           grays = 2;
00335           read_rle_raw(ref); 
00336           return;
00337         }
00338     }
00339   G_THROW( ERR_MSG("GBitmap.bad_format") );
00340 }
00341 
00342 void
00343 GBitmap::donate_data(unsigned char *data, int w, int h)
00344 {
00345   destroy();
00346   grays = 2;
00347   nrows = h;
00348   ncolumns = w;
00349   border = 0;
00350   bytes_per_row = w;
00351   gbytes_data.replace(data,w*h);
00352   bytes = bytes_data;
00353   rlelength = 0;
00354 }
00355 
00356 void
00357 GBitmap::donate_rle(unsigned char *rledata, unsigned int rledatalen, int w, int h)
00358 {
00359   destroy();
00360   grays = 2;
00361   nrows = h;
00362   ncolumns = w;
00363   border = 0;
00364   bytes_per_row = w;
00365 //  rle = rledata;
00366   grle.replace(rledata,rledatalen);
00367   rlelength = rledatalen;
00368 }
00369 
00370 
00371 unsigned char *
00372 GBitmap::take_data(size_t &offset)
00373 {
00374   GMonitorLock lock(monitor());
00375   unsigned char *ret = bytes_data;
00376   if (ret) offset = (size_t)border;
00377   bytes_data=0;
00378   return ret;
00379 }
00380 
00381 const unsigned char *
00382 GBitmap::get_rle(unsigned int &rle_length)
00383 {
00384   if(!rle)
00385     compress();
00386   rle_length=rlelength;
00387   return rle; 
00388 }
00389 
00390 // ----- compression
00391 
00392 
00393 void 
00394 GBitmap::compress()
00395 {
00396   if (grays > 2)
00397     G_THROW( ERR_MSG("GBitmap.cant_compress") );
00398   GMonitorLock lock(monitor());
00399   if (bytes)
00400     {
00401       grle.resize(0);
00402       grlerows.resize(0);
00403       rlelength = encode(rle,grle);
00404       if (rlelength)
00405         {
00406           gbytes_data.resize(0);
00407           bytes = 0;
00408         }
00409     }
00410 }
00411 
00412 void
00413 GBitmap::uncompress()
00414 {
00415   GMonitorLock lock(monitor());
00416   if (!bytes && rle)
00417     decode(rle);
00418 }
00419 
00420 
00421 
00422 unsigned int 
00423 GBitmap::get_memory_usage() const
00424 {
00425   unsigned long usage = sizeof(GBitmap);
00426   if (bytes)
00427     usage += nrows * bytes_per_row + border;
00428   if (rle)
00429     usage += rlelength;
00430   return usage;
00431 }
00432 
00433 
00434 void 
00435 GBitmap::minborder(int minimum)
00436 {
00437   if (border < minimum)
00438     {
00439       GMonitorLock lock(monitor());
00440       if (border < minimum)
00441         {
00442           if (bytes)
00443             {
00444               GBitmap tmp(*this, minimum);
00445               bytes_per_row = tmp.bytes_per_row;
00446               tmp.gbytes_data.swap(gbytes_data);
00447               bytes = bytes_data;
00448               tmp.bytes = 0;
00449             }
00450           border = minimum;
00451           gzerobuffer=zeroes(border + ncolumns + border);
00452         }
00453     }
00454 }
00455 
00456 
00457 #define NMONITORS 8
00458 static GMonitor monitors[NMONITORS];
00459 
00460 void
00461 GBitmap::share()
00462 {
00463   if (!monitorptr)
00464     {
00465       unsigned long x = (unsigned long)this;
00466       monitorptr = &monitors[(x^(x>>5)) % NMONITORS];
00467     }
00468 }
00469 
00470 
00471 // ----- gray levels
00472 
00473 void
00474 GBitmap::set_grays(int ngrays)
00475 {
00476   if (ngrays<2 || ngrays>256)
00477     G_THROW( ERR_MSG("GBitmap.bad_levels") );
00478   // set gray levels
00479   GMonitorLock lock(monitor());
00480   grays = ngrays;
00481   if (ngrays>2 && !bytes)
00482     uncompress();
00483 }
00484 
00485 void 
00486 GBitmap::change_grays(int ngrays)
00487 {
00488   GMonitorLock lock(monitor());
00489   // set number of grays
00490   int ng = ngrays - 1;
00491   int og = grays - 1;
00492   set_grays(ngrays);
00493   // setup conversion table
00494   unsigned char conv[256];
00495   for (int i=0; i<256; i++)
00496     {
00497       if (i > og)
00498         conv[i] = ng;
00499       else
00500         conv[i] = (i*ng+og/2)/og;
00501     }
00502   // perform conversion
00503   for (int row=0; row<nrows; row++)
00504     {
00505       unsigned char *p = (*this)[row];
00506       for (int n=0; n<ncolumns; n++)
00507         p[n] = conv[ p[n] ];
00508     }
00509 }
00510 
00511 void 
00512 GBitmap::binarize_grays(int threshold)
00513 {
00514   GMonitorLock lock(monitor());
00515   if (bytes)
00516     for (int row=0; row<nrows; row++)
00517       {
00518         unsigned char *p = (*this)[row];
00519         for(unsigned char const * const pend=p+ncolumns;p<pend;++p)
00520         {
00521           *p = (*p>threshold) ? 1 : 0;
00522         }
00523       }
00524   grays = 2;
00525 }
00526 
00527 
00528 // ----- additive blitting
00529 
00530 #undef min
00531 #undef max
00532 
00533 static inline int
00534 min(int x, int y) 
00535 { 
00536   return (x < y ? x : y);
00537 }
00538 
00539 static inline int
00540 max(int x, int y) 
00541 { 
00542   return (x > y ? x : y);
00543 }
00544 
00545 void 
00546 GBitmap::blit(const GBitmap *bm, int x, int y)
00547 {
00548   // Check boundaries
00549   if ((x >= ncolumns)              || 
00550       (y >= nrows)                 ||
00551       (x + (int)bm->columns() < 0) || 
00552       (y + (int)bm->rows() < 0)     )
00553     return;
00554 
00555   // Perform blit
00556   GMonitorLock lock1(monitor());
00557   GMonitorLock lock2(bm->monitor());
00558   if (bm->bytes)
00559     {
00560       if (!bytes_data)
00561         uncompress();
00562       // Blit from bitmap
00563       const unsigned char *srow = bm->bytes + bm->border;
00564       unsigned char *drow = bytes_data + border + y*bytes_per_row + x;
00565       for (int sr = 0; sr < bm->nrows; sr++)
00566         {
00567           if (sr+y>=0 && sr+y<nrows) 
00568             {
00569               int sc = max(0, -x);
00570               int sc1 = min(bm->ncolumns, ncolumns-x);
00571               while (sc < sc1)
00572                 {
00573                   drow[sc] += srow[sc];
00574                   sc += 1;
00575                 }
00576             }
00577           srow += bm->bytes_per_row;
00578           drow += bytes_per_row;
00579         }
00580     }
00581   else if (bm->rle)
00582     {
00583       if (!bytes_data)
00584         uncompress();
00585       // Blit from rle
00586       const unsigned char *runs = bm->rle;
00587       unsigned char *drow = bytes_data + border + y*bytes_per_row + x;
00588       int sr = bm->nrows - 1;
00589       drow += sr * bytes_per_row;
00590       int sc = 0;
00591       char p = 0;
00592       while (sr >= 0)
00593         {
00594           const int z = read_run(runs);
00595           if (sc+z > bm->ncolumns)
00596             G_THROW( ERR_MSG("GBitmap.lost_sync") );
00597           int nc = sc + z;
00598           if (p && sr+y>=0 && sr+y<nrows) 
00599             {
00600               if (sc + x < 0) 
00601                 sc = min(-x, nc); 
00602               while (sc < nc && sc + x<ncolumns)
00603                 drow[sc++] += 1;
00604             }
00605           sc = nc;
00606           p = 1 - p;
00607           if (sc >= bm->ncolumns) 
00608             {
00609               p = 0;
00610               sc = 0;
00611               drow -= bytes_per_row;
00612               sr -= 1; 
00613             }
00614         }
00615     }
00616 }
00617 
00618 
00619 
00620 void 
00621 GBitmap::blit(const GBitmap *bm, int xh, int yh, int subsample)
00622 {
00623   // Use code when no subsampling is necessary
00624   if (subsample == 1)
00625     {
00626       blit(bm, xh, yh);
00627       return;
00628     }
00629 
00630   // Check boundaries
00631   if ((xh >= ncolumns * subsample) || 
00632       (yh >= nrows * subsample)    ||
00633       (xh + (int)bm->columns() < 0)   || 
00634       (yh + (int)bm->rows() < 0)     )
00635     return;
00636 
00637   // Perform subsampling blit
00638   GMonitorLock lock1(monitor());
00639   GMonitorLock lock2(bm->monitor());
00640   if (bm->bytes)
00641     {
00642       if (!bytes_data)
00643         uncompress();
00644       // Blit from bitmap
00645       int dr, dr1, zdc, zdc1;
00646       euclidian_ratio(yh, subsample, dr, dr1);
00647       euclidian_ratio(xh, subsample, zdc, zdc1);
00648       const unsigned char *srow = bm->bytes + bm->border;
00649       unsigned char *drow = bytes_data + border + dr*bytes_per_row;
00650       for (int sr = 0; sr < bm->nrows; sr++)
00651         {
00652           if (dr>=0 && dr<nrows) 
00653             {
00654               int dc = zdc;
00655               int dc1 = zdc1;
00656               for (int sc=0; sc < bm->ncolumns; sc++) 
00657                 {
00658                   if (dc>=0 && dc<ncolumns)
00659                     drow[dc] += srow[sc];
00660                   if (++dc1 >= subsample) 
00661                     {
00662                       dc1 = 0;
00663                       dc += 1;
00664                     }
00665                 }
00666             }
00667           // next line in source
00668           srow += bm->bytes_per_row;
00669           // next line fraction in destination
00670           if (++dr1 >= subsample)
00671             {
00672               dr1 = 0;
00673               dr += 1;
00674               drow += bytes_per_row;
00675             }
00676         }
00677     }
00678   else if (bm->rle)
00679     {
00680       if (!bytes_data)
00681         uncompress();
00682       // Blit from rle
00683       int dr, dr1, zdc, zdc1;
00684       euclidian_ratio(yh+bm->nrows-1, subsample, dr, dr1);
00685       euclidian_ratio(xh, subsample, zdc, zdc1);
00686       const unsigned char *runs = bm->rle;
00687       unsigned char *drow = bytes_data + border + dr*bytes_per_row;
00688       int sr = bm->nrows -1;
00689       int sc = 0;
00690       char p = 0;
00691       int dc = zdc;
00692       int dc1 = zdc1;
00693       while (sr >= 0)
00694         {
00695           int z = read_run(runs);
00696           if (sc+z > bm->ncolumns)
00697             G_THROW( ERR_MSG("GBitmap.lost_sync") );
00698           int nc = sc + z;
00699 
00700           if (dr>=0 && dr<nrows)
00701             while (z>0 && dc<ncolumns)
00702               {
00703                 int zd = subsample - dc1;
00704                 if (zd > z) 
00705                   zd = z;
00706                 if (p && dc>=0) 
00707                   drow[dc] += zd;
00708                 z -= zd;
00709                 dc1 += zd;
00710                 if (dc1 >= subsample)
00711                   {
00712                     dc1 = 0;
00713                     dc += 1;
00714                   }
00715               }
00716           // next fractional row
00717           sc = nc;
00718           p = 1 - p;
00719           if (sc >= bm->ncolumns) 
00720             {
00721               sc = 0;
00722               dc = zdc;
00723               dc1 = zdc1;
00724               p = 0;
00725               sr -= 1; 
00726               if (--dr1 < 0)
00727                 {
00728                   dr1 = subsample - 1;
00729                   dr -= 1;
00730                   drow -= bytes_per_row;
00731                 }
00732             }
00733         }
00734     }
00735 }
00736 
00737 
00738 
00739 // ------ load bitmaps
00740 
00741 
00742 unsigned int 
00743 GBitmap::read_integer(char &c, ByteStream &bs)
00744 {
00745   unsigned int x = 0;
00746   // eat blank before integer
00747   while (c==' ' || c=='\t' || c=='\r' || c=='\n' || c=='#') 
00748     {
00749       if (c=='#') 
00750         do { } while (bs.read(&c,1) && c!='\n' && c!='\r');
00751       c = 0; 
00752       bs.read(&c, 1);
00753     }
00754   // check integer
00755   if (c<'0' || c>'9')
00756     G_THROW( ERR_MSG("GBitmap.not_int") );
00757   // eat integer
00758   while (c>='0' && c<='9') 
00759     {
00760       x = x*10 + c - '0';
00761       c = 0;
00762       bs.read(&c, 1);
00763     }
00764   return x;
00765 }
00766 
00767 
00768 void 
00769 GBitmap::read_pbm_text(ByteStream &bs)
00770 {
00771   unsigned char *row = bytes_data + border;
00772   row += (nrows-1) * bytes_per_row;
00773   for (int n = nrows-1; n>=0; n--) 
00774     {
00775       for (int c = 0; c<ncolumns; c++) 
00776         {
00777           char bit = 0;
00778           bs.read(&bit,1);
00779           while (bit==' ' || bit=='\t' || bit=='\r' || bit=='\n')
00780             { 
00781               bit=0; 
00782               bs.read(&bit,1); 
00783             }
00784           if (bit=='1')
00785             row[c] = 1;
00786           else if (bit=='0')
00787             row[c] = 0;
00788           else
00789             G_THROW( ERR_MSG("GBitmap.bad_PBM") );
00790         }
00791       row -= bytes_per_row;
00792     }
00793 }
00794 
00795 void 
00796 GBitmap::read_pgm_text(ByteStream &bs)
00797 {
00798   unsigned char *row = bytes_data + border;
00799   row += (nrows-1) * bytes_per_row;
00800   char lookahead = '\n';
00801   for (int n = nrows-1; n>=0; n--) 
00802     {
00803       for (int c = 0; c<ncolumns; c++)
00804         row[c] = grays - 1 - read_integer(lookahead, bs);
00805       row -= bytes_per_row;
00806     }
00807 }
00808 
00809 void 
00810 GBitmap::read_pbm_raw(ByteStream &bs)
00811 {
00812   unsigned char *row = bytes_data + border;
00813   row += (nrows-1) * bytes_per_row;
00814   for (int n = nrows-1; n>=0; n--) 
00815     {
00816       unsigned char acc = 0;
00817       unsigned char mask = 0;
00818       for (int c = 0; c<ncolumns; c++)
00819         {
00820           if (!mask) 
00821             {
00822               bs.read(&acc, 1);
00823               mask = (unsigned char)0x80;
00824             }
00825           if (acc & mask)
00826             row[c] = 1;
00827           else
00828             row[c] = 0;
00829           mask >>= 1;
00830         }
00831       row -= bytes_per_row;
00832     }
00833 }
00834 
00835 void 
00836 GBitmap::read_pgm_raw(ByteStream &bs)
00837 {
00838   unsigned char *row = bytes_data + border;
00839   row += (nrows-1) * bytes_per_row;
00840   for (int n = nrows-1; n>=0; n--) 
00841     {
00842       for (int c = 0; c<ncolumns; c++)
00843         {
00844           unsigned char x;
00845           bs.read((void*)&x, 1);
00846           row[c] = grays - 1 - x;
00847         }
00848       row -= bytes_per_row;
00849     }
00850 }
00851 
00852 void 
00853 GBitmap::read_rle_raw(ByteStream &bs)
00854 {
00855   // interpret runs data
00856   unsigned char h;
00857   unsigned char p = 0;
00858   unsigned char *row = bytes_data + border;
00859   int n = nrows - 1;
00860   row += n * bytes_per_row;
00861   int c = 0;
00862   while (n >= 0)
00863     {
00864       bs.read(&h, 1);
00865       int x = h;
00866       if (x >= (int)RUNOVERFLOWVALUE)
00867         {
00868           bs.read(&h, 1);
00869           x = h + ((x - (int)RUNOVERFLOWVALUE) << 8);
00870         }
00871       if (c+x > ncolumns)
00872         G_THROW( ERR_MSG("GBitmap.lost_sync") );
00873       while (x-- > 0)
00874         row[c++] = p;
00875       p = 1 - p;
00876       if (c >= ncolumns) 
00877         {
00878           c = 0;
00879           p = 0;
00880           row -= bytes_per_row;
00881           n -= 1; 
00882         }
00883     }
00884 }
00885 
00886 
00887 // ------ save bitmaps
00888 
00889 void 
00890 GBitmap::save_pbm(ByteStream &bs, int raw)
00891 {
00892   // check arguments
00893   if (grays > 2)
00894     G_THROW( ERR_MSG("GBitmap.cant_make_PBM") );
00895   GMonitorLock lock(monitor());
00896   // header
00897   {
00898     GUTF8String head;
00899     head.format("P%c\n%d %d\n", (raw ? '4' : '1'), ncolumns, nrows);
00900     bs.writall((void*)(const char *)head, head.length());
00901   }
00902   // body
00903   if(raw)
00904   {
00905     if(!rle)
00906       compress();
00907     const unsigned char *runs=rle;
00908     const unsigned char * const runs_end=rle+rlelength;
00909     const int count=(ncolumns+7)>>3;
00910     unsigned char *buf;
00911     GPBuffer<unsigned char> gbuf(buf,count);
00912     while(runs<runs_end)
00913     {
00914       rle_get_bitmap(ncolumns,runs,buf,false);
00915       bs.writall(buf,count);
00916     }
00917   }else
00918   {
00919     if (!bytes)
00920       uncompress();
00921     const unsigned char *row = bytes + border;
00922     int n = nrows - 1;
00923     row += n * bytes_per_row;
00924     while (n >= 0)
00925     {
00926       unsigned char eol='\n';
00927       for (int c=0; c<ncolumns;)
00928       {
00929         unsigned char bit= (row[c] ? '1' : '0');
00930         bs.write((void*)&bit, 1);
00931         c += 1;
00932         if (c==ncolumns || (c&(int)RUNMSBMASK)==0) 
00933           bs.write((void*)&eol, 1);          
00934        }
00935       // next row
00936       row -= bytes_per_row;
00937       n -= 1;
00938     }
00939   }
00940 }
00941 
00942 void 
00943 GBitmap::save_pgm(ByteStream &bs, int raw)
00944 {
00945   // checks
00946   GMonitorLock lock(monitor());
00947   if (!bytes)
00948     uncompress();
00949   // header
00950   GUTF8String head;
00951   head.format("P%c\n%d %d\n%d\n", (raw ? '5' : '2'), ncolumns, nrows, grays-1);
00952   bs.writall((void*)(const char *)head, head.length());
00953   // body
00954   const unsigned char *row = bytes + border;
00955   int n = nrows - 1;
00956   row += n * bytes_per_row;
00957   while (n >= 0)
00958     {
00959       if (raw)
00960         {
00961           for (int c=0; c<ncolumns; c++)
00962             {
00963               char x = grays - 1 - row[c];
00964               bs.write((void*)&x, 1);
00965             }
00966         }
00967       else 
00968         {
00969           unsigned char eol='\n';
00970           for (int c=0; c<ncolumns; )
00971             {
00972               head.format("%d ", grays - 1 - row[c]);
00973               bs.writall((void*)(const char *)head, head.length());
00974               c += 1;
00975               if (c==ncolumns || (c&0x1f)==0) 
00976                 bs.write((void*)&eol, 1);          
00977             }
00978         }
00979       row -= bytes_per_row;
00980       n -= 1;
00981     }
00982 }
00983 
00984 void 
00985 GBitmap::save_rle(ByteStream &bs)
00986 {
00987   // checks
00988   if (ncolumns==0 || nrows==0)
00989     G_THROW( ERR_MSG("GBitmap.not_init") );
00990   GMonitorLock lock(monitor());
00991   if (grays > 2)
00992     G_THROW( ERR_MSG("GBitmap.cant_make_PBM") );
00993   // header
00994   GUTF8String head;
00995   head.format("R4\n%d %d\n", ncolumns, nrows);
00996   bs.writall((void*)(const char *)head, head.length());
00997   // body
00998   if (rle)
00999     {
01000       bs.writall((void*)rle, rlelength);
01001     }
01002   else
01003     {
01004       unsigned char *runs = 0;
01005       GPBuffer<unsigned char> gruns(runs);
01006       int size = encode(runs,gruns);
01007       bs.writall((void*)runs, size);
01008     }
01009 }
01010 
01011 
01012 // ------ runs
01013 
01014 
01015 void
01016 GBitmap::makerows(
01017   int nrows, const int ncolumns, unsigned char *runs, unsigned char *rlerows[])
01018 {
01019   while (nrows-- > 0)
01020   {
01021     rlerows[nrows] = runs;
01022     int c;
01023     for(c=0;c<ncolumns;c+=GBitmap::read_run(runs))
01024       EMPTY_LOOP;
01025     if (c > ncolumns)
01026       G_THROW( ERR_MSG("GBitmap.lost_sync2") );
01027   }
01028 }
01029 
01030 
01031 void
01032 GBitmap::rle_get_bitmap (
01033   const int ncolumns,
01034   const unsigned char *&runs,
01035   unsigned char *bitmap,
01036   const bool invert )
01037 {
01038   const int obyte_def=invert?0xff:0;
01039   const int obyte_ndef=invert?0:0xff;
01040   int mask=0x80,obyte=0;
01041   for(int c=ncolumns;c > 0 ;)
01042   {
01043     int x=read_run(runs);
01044     c-=x;
01045     while((x--)>0)
01046     {
01047       if(!(mask>>=1))
01048       {
01049         *(bitmap++) = obyte^obyte_def;
01050         obyte=0;
01051         mask=0x80;
01052         for(;x>=8;x-=8)
01053         {
01054           *(bitmap++)=obyte_def;
01055         }
01056       }
01057     }
01058     if(c>0)
01059     {
01060       int x=read_run(runs);
01061       c-=x;
01062       while((x--)>0)
01063       {
01064         obyte|=mask;
01065         if(!(mask>>=1))
01066         {
01067           *(bitmap++)=obyte^obyte_def;
01068           obyte=0;
01069           mask=0x80;
01070           for(;(x>8);x-=8)
01071             *(bitmap++)=obyte_ndef;
01072         }
01073       }
01074     }
01075   }
01076   if(mask != 0x80)
01077   {
01078     *(bitmap++)=obyte^obyte_def;
01079   }
01080 }
01081 
01082 int 
01083 GBitmap::rle_get_bits(int rowno, unsigned char *bits) const
01084 {
01085   GMonitorLock lock(monitor());
01086   if (!rle)
01087     return 0;
01088   if (rowno<0 || rowno>=nrows)
01089     return 0;
01090   if (!rlerows)
01091   {
01092     const_cast<GPBuffer<unsigned char *> &>(grlerows).resize(nrows);
01093     makerows(nrows,ncolumns,rle,const_cast<unsigned char **>(rlerows));
01094   }
01095   int n = 0;
01096   int p = 0;
01097   int c = 0;
01098   unsigned char *runs = rlerows[rowno];
01099   while (c < ncolumns)
01100     {
01101       const int x=read_run(runs);
01102       if ((c+=x)>ncolumns)
01103         c = ncolumns;
01104       while (n<c)
01105         bits[n++] = p;
01106       p = 1-p;
01107     }
01108   return n;
01109 }
01110 
01111 
01112 int 
01113 GBitmap::rle_get_runs(int rowno, int *rlens) const
01114 {
01115   GMonitorLock lock(monitor());
01116   if (!rle)
01117     return 0;
01118   if (rowno<0 || rowno>=nrows)
01119     return 0;
01120   if (!rlerows)
01121   {
01122     const_cast<GPBuffer<unsigned char *> &>(grlerows).resize(nrows);
01123     makerows(nrows,ncolumns,rle,const_cast<unsigned char **>(rlerows));
01124   }
01125   int n = 0;
01126   int d = 0;
01127   int c = 0;
01128   unsigned char *runs = rlerows[rowno];
01129   while (c < ncolumns)
01130     {
01131       const int x=read_run(runs);
01132       if (n>0 && !x)
01133         {
01134           n--;
01135           d = d-rlens[n];
01136         }
01137       else 
01138         {
01139           rlens[n++] = (c+=x)-d;
01140           d = c;
01141         }
01142     }
01143   return n;
01144 }
01145 
01146 
01147 int 
01148 GBitmap::rle_get_rect(GRect &rect) const
01149 {
01150   GMonitorLock lock(monitor());
01151   if (!rle) 
01152     return 0;
01153   int area = 0;
01154   unsigned char *runs = rle;
01155   rect.xmin = ncolumns;
01156   rect.ymin = nrows;
01157   rect.xmax = 0;
01158   rect.ymax = 0;
01159   int r = nrows;
01160   while (--r >= 0)
01161     {
01162       int p = 0;
01163       int c = 0;
01164       int n = 0;
01165       while (c < ncolumns)
01166         {
01167           const int x=read_run(runs);
01168           if(x)
01169             {
01170               if (p)
01171                 {
01172                   if (c < rect.xmin) 
01173                     rect.xmin = c;
01174                   if ((c += x) > rect.xmax) 
01175                     rect.xmax = c-1;
01176                   n += x;
01177                 }
01178               else
01179                 {
01180                   c += x;
01181                 }
01182             }
01183           p = 1-p;
01184         }
01185       area += n;
01186       if (n)
01187         {
01188           rect.ymin = r;
01189           if (r > rect.ymax) 
01190             rect.ymax = r;
01191         }
01192     }
01193   if (area==0)
01194     rect.clear();
01195   return area;
01196 }
01197 
01198 
01199 
01200 // ------ helpers
01201 
01202 int
01203 GBitmap::encode(unsigned char *&pruns,GPBuffer<unsigned char> &gpruns) const
01204 {
01205   // uncompress rle information
01206   if (nrows==0 || ncolumns==0)
01207   {
01208     gpruns.resize(0);
01209     return 0;
01210   }
01211   if (!bytes)
01212     {
01213       unsigned char *runs;
01214       GPBuffer<unsigned char> gruns(runs,rlelength);
01215       memcpy((void*)runs, rle, rlelength);
01216       gruns.swap(gpruns);
01217       return rlelength;
01218     }
01219   gpruns.resize(0);
01220   // create run array
01221   int pos = 0;
01222   int maxpos = 1024 + ncolumns + ncolumns;
01223   unsigned char *runs;
01224   GPBuffer<unsigned char> gruns(runs,maxpos);
01225   // encode bitmap as rle
01226   const unsigned char *row = bytes + border;
01227   int n = nrows - 1;
01228   row += n * bytes_per_row;
01229   while (n >= 0)
01230     {
01231       if (maxpos < pos+ncolumns+ncolumns+2)
01232         {
01233           maxpos += 1024 + ncolumns + ncolumns;
01234           gruns.resize(maxpos);
01235         }
01236 
01237       unsigned char *runs_pos=runs+pos;
01238       const unsigned char * const runs_pos_start=runs_pos;
01239       append_line(runs_pos,row,ncolumns);
01240       pos+=(size_t)runs_pos-(size_t)runs_pos_start;
01241       row -= bytes_per_row;
01242       n -= 1;
01243     }
01244   // return result
01245   gruns.resize(pos);
01246   gpruns.swap(gruns);
01247   return pos;
01248 }
01249 
01250 void 
01251 GBitmap::decode(unsigned char *runs)
01252 {
01253   // initialize pixel array
01254   if (nrows==0 || ncolumns==0)
01255     G_THROW( ERR_MSG("GBitmap.not_init") );
01256   bytes_per_row = ncolumns + border;
01257   if (runs==0)
01258     G_THROW( ERR_MSG("GBitmap.null_arg") );
01259   int npixels = nrows * bytes_per_row + border;
01260   if (!bytes_data)
01261   {
01262     gbytes_data.resize(npixels);
01263     bytes = bytes_data;
01264   }
01265   gbytes_data.clear();
01266   gzerobuffer=zeroes(bytes_per_row + border);
01267   // interpret runs data
01268   int c, n;
01269   unsigned char p = 0;
01270   unsigned char *row = bytes_data + border;
01271   n = nrows - 1;
01272   row += n * bytes_per_row;
01273   c = 0;
01274   while (n >= 0)
01275     {
01276       int x = read_run(runs);
01277       if (c+x > ncolumns)
01278         G_THROW( ERR_MSG("GBitmap.lost_sync2") );
01279       while (x-- > 0)
01280         row[c++] = p;
01281       p = 1 - p;
01282       if (c >= ncolumns) 
01283         {
01284           c = 0;
01285           p = 0;
01286           row -= bytes_per_row;
01287           n -= 1; 
01288         }
01289     }
01290   // Free rle data possibly attached to this bitmap
01291   grle.resize(0);
01292   grlerows.resize(0);
01293   rlelength = 0;
01294 #ifndef NDEBUG
01295   check_border();
01296 #endif
01297 }
01298 
01299 class GBitmap::ZeroBuffer : public GPEnabled
01300 {
01301 public:
01302   ZeroBuffer(const unsigned int zerosize);
01303   unsigned char *zerobuffer;
01304   GPBuffer<unsigned char> gzerobuffer;
01305 };
01306 
01307 GBitmap::ZeroBuffer::ZeroBuffer(const unsigned int zerosize)
01308 : gzerobuffer(zerobuffer,zerosize)
01309 {
01310   gzerobuffer.clear();
01311   GBitmap::zerobuffer=zerobuffer;
01312   GBitmap::zerosize=zerosize;
01313 }
01314 
01315 static const unsigned char static_zerobuffer[]=
01316 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 32
01317  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 64
01318  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 96 
01319  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 128 
01320  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 160
01321  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 192
01322  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 234
01323  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 256
01324  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 288
01325  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 320
01326  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 352 
01327  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 384 
01328  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 416
01329  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 448
01330  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 480
01331  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 512
01332  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 544
01333  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 576
01334  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 608 
01335  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 640 
01336  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 672
01337  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 704
01338  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 736
01339  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 768
01340  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 800
01341  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 832
01342  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 864 
01343  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 896 
01344  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 928
01345  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 960
01346  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 992
01347  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024
01348  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+32
01349  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+64
01350  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+96 
01351  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+128 
01352  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+160
01353  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+192
01354  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+234
01355  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+256
01356  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+288
01357  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+320
01358  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+352 
01359  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+384 
01360  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+416
01361  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+448
01362  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+480
01363  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+512
01364  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+544
01365  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+576
01366  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+608 
01367  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+640 
01368  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+672
01369  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+704
01370  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+736
01371  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+768
01372  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+800
01373  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+832
01374  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+864 
01375  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+896 
01376  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+928
01377  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+960
01378  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1024+992
01379  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048
01380  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+32
01381  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+64
01382  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+96 
01383  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+128 
01384  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+160
01385  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+192
01386  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+234
01387  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+256
01388  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+288
01389  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+320
01390  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+352 
01391  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+384 
01392  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+416
01393  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+448
01394  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+480
01395  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+512
01396  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+544
01397  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+576
01398  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+608 
01399  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+640 
01400  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+672
01401  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+704
01402  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+736
01403  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+768
01404  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+800
01405  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+832
01406  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+864 
01407  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+896 
01408  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+928
01409  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+960
01410  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2048+992
01411  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072
01412  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+32
01413  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+64
01414  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+96 
01415  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+128 
01416  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+160
01417  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+192
01418  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+234
01419  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+256
01420  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+288
01421  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+320
01422  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+352 
01423  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+384 
01424  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+416
01425  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+448
01426  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+480
01427  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+512
01428  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+544
01429  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+576
01430  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+608 
01431  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+640 
01432  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+672
01433  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+704
01434  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+736
01435  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+768
01436  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+800
01437  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+832
01438  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+864 
01439  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+896 
01440  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+928
01441  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+960
01442  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3072+992
01443  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // 4096
01444 
01445 int GBitmap::zerosize = sizeof(static_zerobuffer);
01446 unsigned char *GBitmap::zerobuffer=const_cast<unsigned char *>(static_zerobuffer);
01447 
01448 GP<GBitmap::ZeroBuffer>
01449 GBitmap::zeroes(int required)
01450 {
01451   GMonitorLock lock(&monitors[0]); // any monitor would do
01452   static GP<GBitmap::ZeroBuffer> gzerobuffer;
01453   if (zerosize < required)
01454   {
01455     int z;
01456     for(z=zerosize;z<required;z <<= 1)
01457       EMPTY_LOOP;
01458     z=(z+0xfff)&(~0xfff);
01459     gzerobuffer=new GBitmap::ZeroBuffer((unsigned int)z);
01460   }
01461   return gzerobuffer;
01462 }
01463 
01464 
01465 // Fills a bitmap with the given value
01466 void 
01467 GBitmap::fill(unsigned char value)
01468 {
01469   GMonitorLock lock(monitor());
01470   for(unsigned int y=0; y<rows(); y++)
01471     {
01472       unsigned char* bm_y = (*this)[y];
01473       for(unsigned int x=0; x<columns(); x++)
01474         bm_y[x] = value;
01475     }
01476 }
01477 
01478 
01479 void 
01480 GBitmap::append_long_run(unsigned char *&data, int count)
01481 {
01482   while (count > MAXRUNSIZE)
01483     {
01484       data[0] = data[1] = 0xff;
01485       data[2] = 0;
01486       data += 3;
01487       count -= MAXRUNSIZE;
01488     }
01489   if (count < RUNOVERFLOWVALUE)
01490     {
01491       data[0] = count;
01492       data += 1;
01493     }
01494   else
01495     {
01496       data[0] = (count>>8) + GBitmap::RUNOVERFLOWVALUE;
01497       data[1] = (count & 0xff);
01498       data += 2;
01499     }
01500 }
01501 
01502 
01503 void
01504 GBitmap::append_line(unsigned char *&data,const unsigned char *row,
01505                      const int rowlen,bool invert)
01506 {
01507   const unsigned char *rowend=row+rowlen;
01508   bool p=!invert;
01509   while(row<rowend)
01510     {
01511       int count=0;
01512       if ((p=!p)) 
01513         {
01514           if(*row)
01515             for(++count,++row;(row<rowend)&&*row;++count,++row)
01516                 EMPTY_LOOP;
01517         } 
01518       else if(!*row)
01519         {
01520           for(++count,++row;(row<rowend)&&!*row;++count,++row)
01521             EMPTY_LOOP;
01522         }
01523       append_run(data,count);
01524     }
01525 }
01526 
01527 #if 0
01528 static inline int
01529 GetRowTDLRNR(
01530   GBitmap &bit,const int row, const unsigned char *&startptr,
01531   const unsigned char *&stopptr)
01532 {
01533   stopptr=(startptr=bit[row])+bit.columns();
01534   return 1;
01535 }
01536 
01537 static inline int
01538 GetRowTDLRNR(
01539   GBitmap &bit,const int row, const unsigned char *&startptr,
01540   const unsigned char *&stopptr)
01541 {
01542   stopptr=(startptr=bit[row])+bit.columns();
01543   return 1;
01544 }
01545 
01546 static inline int
01547 GetRowTDRLNR(
01548   GBitmap &bit,const int row, const unsigned char *&startptr,
01549   const unsigned char *&stopptr)
01550 {
01551   startptr=(stopptr=bit[row]-1)+bit.columns();
01552   return -1;
01553 }
01554 #endif // 0
01555 
01556 GP<GBitmap> 
01557 GBitmap::rotate(int count)
01558 {
01559   GP<GBitmap> newbitmap=this;
01560   if((count%=4))
01561   {
01562     if( count & 0x01 )
01563     {
01564       newbitmap = new GBitmap(ncolumns, nrows);
01565     }else
01566     {
01567       newbitmap = new GBitmap(nrows, ncolumns);
01568     }
01569     GMonitorLock lock(monitor());
01570     if (!bytes_data)
01571       uncompress();
01572     GBitmap &dbitmap = *newbitmap;
01573     dbitmap.set_grays(grays);
01574     switch(count)
01575     {
01576     case 1: // rotate 90 counter clockwise
01577       {
01578         const int lastrow = dbitmap.rows()-1;
01579         for(int y=0; y<nrows; y++)
01580         {
01581           const unsigned char *r=operator[] (y);
01582           for(int x=0,xnew=lastrow;xnew>=0; x++,xnew--)
01583           {
01584             dbitmap[xnew][y] = r[x];
01585           }
01586         }
01587       }
01588       break;
01589     case 2: // rotate 180 counter clockwise
01590       {
01591         const int lastrow = dbitmap.rows()-1;
01592         const int lastcolumn = dbitmap.columns()-1;
01593         for(int y=0,ynew=lastrow;ynew>=0; y++,ynew--)
01594         {
01595           const unsigned char *r=operator[] (y);
01596           unsigned char *d=dbitmap[ynew];
01597           for(int xnew=lastcolumn;xnew>=0; r++,--xnew)
01598           {
01599             d[xnew] = *r;
01600           }
01601         }
01602       }
01603       break;
01604     case 3: // rotate 270 counter clockwise
01605       {
01606         const int lastcolumn = dbitmap.columns()-1;
01607         for(int y=0,ynew=lastcolumn;ynew>=0;y++,ynew--)
01608         {
01609           const unsigned char *r=operator[] (y);
01610           for(int x=0; x<ncolumns; x++)
01611           {
01612             dbitmap[x][ynew] = r[x];
01613           }
01614         }
01615       }
01616       break;
01617     }
01618     if(grays == 2)
01619     {
01620       compress();
01621       dbitmap.compress();
01622     }
01623   }
01624   return newbitmap;
01625 }
01626 
01627 #ifndef NDEBUG
01628 void 
01629 GBitmap::check_border() const
01630 {int col ;
01631   if (bytes)
01632     {
01633       const unsigned char *p = (*this)[-1];
01634       for (col=-border; col<ncolumns+border; col++)
01635         if (p[col])
01636           G_THROW( ERR_MSG("GBitmap.zero_damaged") );
01637       for (int row=0; row<nrows; row++)
01638         {
01639           p = (*this)[row];
01640           for (col=-border; col<0; col++)
01641             if (p[col])
01642               G_THROW( ERR_MSG("GBitmap.left_damaged") );
01643           for (col=ncolumns; col<ncolumns+border; col++)
01644             if (p[col])
01645               G_THROW( ERR_MSG("GBitmap.right_damaged") );
01646         }
01647     }
01648 }
01649 #endif
01650 
01651 
01652 #ifdef HAVE_NAMESPACES
01653 }
01654 # ifndef NOT_USING_DJVU_NAMESPACE
01655 using namespace DJVU;
01656 # endif
01657 #endif
01658 

kviewshell

Skip menu "kviewshell"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • kviewshell
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal