00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
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
00073
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
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
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
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
00269 init(rect.height(), rect.width(), border);
00270 grays = ref.grays;
00271
00272 GRect rect2(0, 0, ref.columns(), ref.rows() );
00273 rect2.intersect(rect2, rect);
00274 rect2.translate(-rect.xmin, -rect.ymin);
00275
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
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
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
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
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
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
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
00490 int ng = ngrays - 1;
00491 int og = grays - 1;
00492 set_grays(ngrays);
00493
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
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
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
00549 if ((x >= ncolumns) ||
00550 (y >= nrows) ||
00551 (x + (int)bm->columns() < 0) ||
00552 (y + (int)bm->rows() < 0) )
00553 return;
00554
00555
00556 GMonitorLock lock1(monitor());
00557 GMonitorLock lock2(bm->monitor());
00558 if (bm->bytes)
00559 {
00560 if (!bytes_data)
00561 uncompress();
00562
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
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
00624 if (subsample == 1)
00625 {
00626 blit(bm, xh, yh);
00627 return;
00628 }
00629
00630
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
00638 GMonitorLock lock1(monitor());
00639 GMonitorLock lock2(bm->monitor());
00640 if (bm->bytes)
00641 {
00642 if (!bytes_data)
00643 uncompress();
00644
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
00668 srow += bm->bytes_per_row;
00669
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
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
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
00740
00741
00742 unsigned int
00743 GBitmap::read_integer(char &c, ByteStream &bs)
00744 {
00745 unsigned int x = 0;
00746
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
00755 if (c<'0' || c>'9')
00756 G_THROW( ERR_MSG("GBitmap.not_int") );
00757
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
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
00888
00889 void
00890 GBitmap::save_pbm(ByteStream &bs, int raw)
00891 {
00892
00893 if (grays > 2)
00894 G_THROW( ERR_MSG("GBitmap.cant_make_PBM") );
00895 GMonitorLock lock(monitor());
00896
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
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
00936 row -= bytes_per_row;
00937 n -= 1;
00938 }
00939 }
00940 }
00941
00942 void
00943 GBitmap::save_pgm(ByteStream &bs, int raw)
00944 {
00945
00946 GMonitorLock lock(monitor());
00947 if (!bytes)
00948 uncompress();
00949
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
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
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
00994 GUTF8String head;
00995 head.format("R4\n%d %d\n", ncolumns, nrows);
00996 bs.writall((void*)(const char *)head, head.length());
00997
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
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
01201
01202 int
01203 GBitmap::encode(unsigned char *&pruns,GPBuffer<unsigned char> &gpruns) const
01204 {
01205
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
01221 int pos = 0;
01222 int maxpos = 1024 + ncolumns + ncolumns;
01223 unsigned char *runs;
01224 GPBuffer<unsigned char> gruns(runs,maxpos);
01225
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
01245 gruns.resize(pos);
01246 gpruns.swap(gruns);
01247 return pos;
01248 }
01249
01250 void
01251 GBitmap::decode(unsigned char *runs)
01252 {
01253
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
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
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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};
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]);
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
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:
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:
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:
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