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 #ifndef _GBITMAP_H_
00058 #define _GBITMAP_H_
00059 #ifdef HAVE_CONFIG_H
00060 #include "config.h"
00061 #endif
00062 #if NEED_GNUG_PRAGMAS
00063 # pragma interface
00064 #endif
00065
00066
00067 #include "GSmartPointer.h"
00068 #ifndef NDEBUG
00069 #include "GException.h"
00070 #endif
00071
00072 #ifdef HAVE_NAMESPACES
00073 namespace DJVU {
00074 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
00075 }
00076 #endif
00077 #endif
00078
00079
00080 class GRect;
00081 class GMonitor;
00082 class ByteStream;
00083
00108
00109
00128 class GBitmap : public GPEnabled
00129 {
00130 protected:
00131 GBitmap(void);
00132 GBitmap(int nrows, int ncolumns, int border=0);
00133 GBitmap(const GBitmap &ref);
00134 GBitmap(const GBitmap &ref, int border);
00135 GBitmap(const GBitmap &ref, const GRect &rect, int border=0);
00136 GBitmap(ByteStream &ref, int border=0);
00137 public:
00138 virtual ~GBitmap();
00139 void destroy(void);
00145 static GP<GBitmap> create(void) {return new GBitmap;}
00146
00151 static GP<GBitmap> create(const int nrows, const int ncolumns, const int border=0)
00152 {return new GBitmap(nrows,ncolumns, border); }
00153
00156 static GP<GBitmap> create(const GBitmap &ref)
00157 {return new GBitmap(ref);}
00158
00161 static GP<GBitmap> create(const GBitmap &ref, const int border)
00162 { return new GBitmap(ref,border); }
00163
00167 static GP<GBitmap> create(const GBitmap &ref, const GRect &rect, const int border=0)
00168 { return new GBitmap(ref,rect,border); }
00169
00174 static GP<GBitmap> create(ByteStream &ref, const int border=0)
00175 { return new GBitmap(ref,border); }
00176
00178
00185 void init(int nrows, int ncolumns, int border=0);
00189 void init(const GBitmap &ref, int border=0);
00193 void init(const GBitmap &ref, const GRect &rect, int border=0);
00199 void init(ByteStream &ref, int border=0);
00202 GBitmap& operator=(const GBitmap &ref);
00204 void fill(unsigned char value);
00206
00210 unsigned int rows() const;
00212 unsigned int columns() const;
00215 const unsigned char *operator[] (int row) const;
00218 unsigned char *operator[] (int row);
00223 unsigned int rowsize() const;
00228 void minborder(int minimum);
00230
00235 int get_grays() const;
00238 void set_grays(int grays);
00242 void change_grays(int grays);
00247 void binarize_grays(int threshold=0);
00249
00262 void compress();
00265 void uncompress();
00267 unsigned int get_memory_usage() const;
00272 GMonitor *monitor() const;
00277 void share();
00279
00291 int rle_get_bits(int rowno, unsigned char *bits) const;
00292
00297 static void rle_get_bitmap(const int ncolumns,const unsigned char *&runs,
00298 unsigned char *bitmap, const bool invert );
00299
00306 int rle_get_runs(int rowno, int *rlens) const;
00310 int rle_get_rect(GRect &rect) const;
00312
00340 void blit(const GBitmap *bm, int x, int y);
00368 void blit(const GBitmap *shape, int x, int y, int subsample);
00370
00382 void save_pbm(ByteStream &bs, int raw=1);
00387 void save_pgm(ByteStream &bs, int raw=1);
00391 void save_rle(ByteStream &bs);
00393
00406 unsigned char *take_data(size_t &offset);
00414 inline void borrow_data(unsigned char &data, int w, int h);
00416 void donate_data(unsigned char *data, int w, int h);
00418 const unsigned char *get_rle(unsigned int &rle_length);
00428 void donate_rle(unsigned char *rledata, unsigned int rledatalen, int w, int h);
00432 static inline int read_run(const unsigned char *&data);
00433 static inline int read_run(unsigned char *&data);
00438 static inline void append_run(unsigned char *&data, int count);
00444 GP<GBitmap> rotate(int count=0);
00446
00447
00448 enum {MAXRUNSIZE=0x3fff};
00449 enum {RUNOVERFLOWVALUE=0xc0};
00450 enum {RUNMSBMASK=0x3f};
00451 enum {RUNLSBMASK=0xff};
00452
00453
00454 protected:
00455
00456 unsigned short nrows;
00457 unsigned short ncolumns;
00458 unsigned short border;
00459 unsigned short bytes_per_row;
00460 unsigned short grays;
00461 unsigned char *bytes;
00462 unsigned char *bytes_data;
00463 GPBuffer<unsigned char> gbytes_data;
00464 unsigned char *rle;
00465 GPBuffer<unsigned char> grle;
00466 unsigned char **rlerows;
00467 GPBuffer<unsigned char *> grlerows;
00468 unsigned int rlelength;
00469 private:
00470 GMonitor *monitorptr;
00471 public:
00472 class ZeroBuffer;
00473 friend class ZeroBuffer;
00474 GP<ZeroBuffer> gzerobuffer;
00475 private:
00476 static int zerosize;
00477 static unsigned char *zerobuffer;
00478 static GP<ZeroBuffer> zeroes(int ncolumns);
00479 static unsigned int read_integer(char &lookahead, ByteStream &ref);
00480 static void euclidian_ratio(int a, int b, int &q, int &r);
00481 int encode(unsigned char *&pruns,GPBuffer<unsigned char> &gpruns) const;
00482 void decode(unsigned char *runs);
00483 void read_pbm_text(ByteStream &ref);
00484 void read_pgm_text(ByteStream &ref);
00485 void read_pbm_raw(ByteStream &ref);
00486 void read_pgm_raw(ByteStream &ref);
00487 void read_rle_raw(ByteStream &ref);
00488 static void append_long_run(unsigned char *&data, int count);
00489 static void append_line(unsigned char *&data,const unsigned char *row,
00490 const int rowlen,bool invert=false);
00491 static void makerows(int,const int, unsigned char *, unsigned char *[]);
00492 friend class DjVu_Stream;
00493 friend class DjVu_PixImage;
00494 public:
00495 #ifndef NDEBUG
00496 void check_border() const;
00497 #endif
00498 };
00499
00500
00539
00540
00541
00542
00543 inline unsigned int
00544 GBitmap::rows() const
00545 {
00546 return nrows;
00547 }
00548
00549 inline unsigned int
00550 GBitmap::columns() const
00551 {
00552 return ncolumns;
00553 }
00554
00555 inline unsigned int
00556 GBitmap::rowsize() const
00557 {
00558 return bytes_per_row;
00559 }
00560
00561 inline int
00562 GBitmap::get_grays() const
00563 {
00564 return grays;
00565 }
00566
00567 inline unsigned char *
00568 GBitmap::operator[](int row)
00569 {
00570 if (!bytes) uncompress();
00571 if (row<0 || row>=nrows) {
00572 #ifndef NDEBUG
00573 if (zerosize < bytes_per_row + border)
00574 G_THROW( ERR_MSG("GBitmap.zero_small") );
00575 #endif
00576 return zerobuffer + border;
00577 }
00578 return &bytes[row * bytes_per_row + border];
00579 }
00580
00581 inline const unsigned char *
00582 GBitmap::operator[](int row) const
00583 {
00584 if (!bytes) ((GBitmap*)this)->uncompress();
00585 if (row<0 || row>=nrows) {
00586 #ifndef NDEBUG
00587 if (zerosize < bytes_per_row + border)
00588 G_THROW( ERR_MSG("GBitmap.zero_small") );
00589 #endif
00590 return zerobuffer + border;
00591 }
00592 return &bytes[row * bytes_per_row + border];
00593 }
00594
00595 inline GBitmap&
00596 GBitmap::operator=(const GBitmap &ref)
00597 {
00598 init(ref, ref.border);
00599 return *this;
00600 }
00601
00602 inline GMonitor *
00603 GBitmap::monitor() const
00604 {
00605 return monitorptr;
00606 }
00607
00608 inline void
00609 GBitmap::euclidian_ratio(int a, int b, int &q, int &r)
00610 {
00611 q = a / b;
00612 r = a - b*q;
00613 if (r < 0)
00614 {
00615 q -= 1;
00616 r += b;
00617 }
00618 }
00619
00620
00621 inline int
00622 GBitmap::read_run(unsigned char *&data)
00623 {
00624 register int z=*data++;
00625 return (z>=RUNOVERFLOWVALUE)?
00626 ((z&~RUNOVERFLOWVALUE)<<8)|(*data++):z;
00627 }
00628
00629 inline int
00630 GBitmap::read_run(const unsigned char *&data)
00631 {
00632 register int z=*data++;
00633 return (z>=RUNOVERFLOWVALUE)?
00634 ((z&~RUNOVERFLOWVALUE)<<8)|(*data++):z;
00635 }
00636
00637 inline void
00638 GBitmap::append_run(unsigned char *&data, int count)
00639 {
00640 if (count < RUNOVERFLOWVALUE)
00641 {
00642 data[0] = count;
00643 data += 1;
00644 }
00645 else if (count <= MAXRUNSIZE)
00646 {
00647 data[0] = (count>>8) + GBitmap::RUNOVERFLOWVALUE;
00648 data[1] = (count & 0xff);
00649 data += 2;
00650 }
00651 else
00652 {
00653 append_long_run(data, count);
00654 }
00655 }
00656
00657
00658 inline void
00659 GBitmap::borrow_data(unsigned char &data,int w,int h)
00660 {
00661 donate_data(&data,w,h);
00662 bytes_data=0;
00663 }
00664
00665
00666
00667 #ifdef HAVE_NAMESPACES
00668 }
00669 # ifndef NOT_USING_DJVU_NAMESPACE
00670 using namespace DJVU;
00671 # endif
00672 #endif
00673 #endif