1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
|
//C- -*- C++ -*-
//C- -------------------------------------------------------------------
//C- DjVuLibre-3.5
//C- Copyright (c) 2002 Leon Bottou and Yann Le Cun.
//C- Copyright (c) 2001 AT&T
//C-
//C- This software is subject to, and may be distributed under, the
//C- GNU General Public License, Version 2. The license should have
//C- accompanied the software or you may obtain a copy of the license
//C- from the Free Software Foundation at http://www.fsf.org .
//C-
//C- This program is distributed in the hope that it will be useful,
//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//C- GNU General Public License for more details.
//C-
//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library
//C- distributed by Lizardtech Software. On July 19th 2002, Lizardtech
//C- Software authorized us to replace the original DjVu(r) Reference
//C- Library notice by the following text (see doc/lizard2002.djvu):
//C-
//C- ------------------------------------------------------------------
//C- | DjVu (r) Reference Library (v. 3.5)
//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
//C- | The DjVu Reference Library is protected by U.S. Pat. No.
//C- | 6,058,214 and patents pending.
//C- |
//C- | This software is subject to, and may be distributed under, the
//C- | GNU General Public License, Version 2. The license should have
//C- | accompanied the software or you may obtain a copy of the license
//C- | from the Free Software Foundation at http://www.fsf.org .
//C- |
//C- | The computer code originally released by LizardTech under this
//C- | license and unmodified by other parties is deemed "the LIZARDTECH
//C- | ORIGINAL CODE." Subject to any third party intellectual property
//C- | claims, LizardTech grants recipient a worldwide, royalty-free,
//C- | non-exclusive license to make, use, sell, or otherwise dispose of
//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the
//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU
//C- | General Public License. This grant only confers the right to
//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to
//C- | the extent such infringement is reasonably necessary to enable
//C- | recipient to make, have made, practice, sell, or otherwise dispose
//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to
//C- | any greater extent that may be necessary to utilize further
//C- | modifications or combinations.
//C- |
//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
//C- +------------------------------------------------------------------
//
// $Id: GPixmap.h,v 1.8 2003/11/07 22:08:21 leonb Exp $
// $Name: release_3_5_15 $
#ifndef _GPIXMAP_H_
#define _GPIXMAP_H_
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if NEED_GNUG_PRAGMAS
# pragma interface
#endif
/** @name GPixmap.h
Files #"GPixmap.h"# and #"GPixmap.cpp"# implement class \Ref{GPixmap}.
Instances of this class represent color images. Each RGB pixel is
represented by structure \Ref{GPixel}. The ``bottom left'' coordinate system
is used consistently in the DjVu library. Line zero of a GPixmap is the
bottom line in the color image. Pixels are organized from left to right
within each line.
{\bf ToDo} --- More sophisticated color correction schemes.
@memo
Generic support for color images.
@author
L\'eon Bottou <leonb@research.att.com>
@version
#$Id: GPixmap.h,v 1.8 2003/11/07 22:08:21 leonb Exp $# */
//@{
#include "GSmartPointer.h"
#ifdef HAVE_NAMESPACES
namespace DJVU {
# ifdef NOT_DEFINED // Just to fool emacs c++ mode
}
#endif
#endif
class GBitmap;
class GRect;
class ByteStream;
/** Color pixel as a RGB triple.
The colors are represented using three bytes named #r#, #g# and #b#. The
value of these bytes represent additive amounts of light. Color white is
represented by setting all three bytes to #255#. Color black is
represented by setting all three bytes to #0#. This convention should not
be confused with the convention adopted for class \Ref{GBitmap} where the
pixel values represent an ink level. */
struct GPixel
{
/** Blue component. */
unsigned char b;
/** Green component. */
unsigned char g;
/** Red component. */
unsigned char r;
/** Returns true iff colors are identical. */
friend int operator==(const GPixel & p1, const GPixel & p2);
/** Returns true iff colors are different. */
friend int operator!=(const GPixel & p1, const GPixel & p2);
/** Returns a hash code for the color. */
friend unsigned int hash(const GPixel &p);
/** @name Predefined colors. */
//@{
/// GPixel::WHITE is initialized to #rgb:255/255/255#.
static const GPixel WHITE;
/// GPixel::BLACK is initialized to #rgb:0/0/0#.
static const GPixel BLACK;
/// GPixel::BLUE is initialized to #rgb:0/0/255#.
static const GPixel BLUE;
/// GPixel::GREEN is initialized to #rgb:0/255/0#.
static const GPixel GREEN;
/// GPixel::RED is initialized to #rgb:255/0/0#.
static const GPixel RED;
//@}
};
/** RGB Color images.
Instances of class #GPixmap# represent color images as a two dimensional
array of pixels \Ref{GPixel}. The bracket operator returns a pointer to
the pixels composing one line of the image. This pointer can be used as
an array to read or write the pixels of this particular line. Following
the general convention of the DjVu Reference Library, line zero is always
the bottom line of the image.
*/
class GPixmap : public GPEnabled
{
protected:
GPixmap(void);
GPixmap(int nrows, int ncolumns, const GPixel *filler=0);
GPixmap(const GBitmap &ref);
GPixmap(const GBitmap &ref, const GRect &rect);
GPixmap(const GPixmap &ref);
GPixmap(const GPixmap &ref, const GRect &rect);
GPixmap(ByteStream &ref);
public:
/// Virtual destructor.
virtual ~GPixmap();
void destroy(void);
/** @name Construction. */
//@{
/** Creates an empty GBitmap object. The returned GPixmap has zero rows
and zero columns. Use function \Ref{init} to change the size of the
image. */
static GP<GPixmap> create(void) {return new GPixmap();}
/** Creates a GPixmap with #nrows# rows and #ncolumns# columns. When the
optional argument #filler# is specified, all pixels are initialized
with the corresponding color. */
static GP<GPixmap> create(
const int nrows, const int ncolumns, const GPixel *filler=0)
{ return new GPixmap(nrows,ncolumns,filler); }
/** Creates a GPixmap by copying the gray level image #ref#.
The constructed GPixmap has the same size as #ref#. The pixels
are initialized with shades of grays copied from #ref#. */
static GP<GPixmap> create(const GBitmap &ref)
{ return new GPixmap(ref); }
/** Creates a GPixmap by copying the rectangle #rect# of the gray level
image #ref#. The constructed GPixmap has the same size as rectangle
#rect#. The pixels are initialized with shades of grays converted from
the ink levels represented in #ref#. This conversion depends on the
number of gray levels in #ref#. */
static GP<GPixmap> create(const GBitmap &ref, const GRect &rect)
{ return new GPixmap(ref,rect); }
/** Copy constructors. Creates a GPixmap by replicating the size and the
contents of GPixmap #ref#. */
static GP<GPixmap> create(const GPixmap &ref)
{ return new GPixmap(ref); }
/** Creates a GPixmap by copying the rectangle #rect# of the color image #ref#.
The constructed GPixmap has the same size as rectangle #rect#.
The pixels are initialized with colors copied from #ref#. */
static GP<GPixmap> create(const GPixmap &ref, const GRect &rect)
{ return new GPixmap(ref,rect); }
/** Creates a GPixmap by reading PPM data from ByteStream #ref#.
See \Ref{PNM and RLE file formats} for more information. */
static GP<GPixmap> create(ByteStream &ref)
{ return new GPixmap(ref); }
//@}
/** @name Initialization. */
//@{
/** Resets the GPixmap to #nrows# rows and #ncolumns# columns. When the
optional argument #filler# is specified, all pixels are initialized with
the corresponding color. The previous content of the GPixmap is discarded. */
void init(int nrows, int ncolumns, const GPixel *filler=0);
/** Resets the GPixmap by copying the size and the contents of the color
image #ref#. The previous content of the GPixmap is discarded. */
void init(const GPixmap &ref);
/** Resets the GPixmap by copying the rectangle #rect# of the color image #ref#.
The previous content of the GPixmap is discarded. */
void init(const GPixmap &ref, const GRect &rect);
/** Resets the GPixmap by copying the size and the contents of the gray
level image #ref#. The optional argument #ramp# is an array of 256
pixel values used for mapping the gray levels to color values.
Setting #ramp# to zero selects a linear ramp of shades of gray. */
void init(const GBitmap &ref, const GPixel *ramp=0);
/** Resets the GPixmap by copying the rectangle #rect# of the gray level
image #ref#. The optional argument #ramp# is an array of 256 pixel
values used for mapping the gray levels to color values. Setting #ramp#
to zero selects a linear ramp computed according to the maximal number
of gray levels in #ref#. */
void init(const GBitmap &ref, const GRect &rect, const GPixel *ramp=0);
/** Resets the GPixmap by reading PPM data from ByteStream #ref#. See
\Ref{PNM and RLE file formats} for more information. */
void init(ByteStream &ref);
/** Resets the GPixmap by copying the gray level image #ref#. The pixels
are initialized with shades of grays copied from #ref#. */
GPixmap& operator=(const GBitmap &ref);
/** Copy operator. Resets the GPixmap by copying the size and the contents
of the color image #ref#. The previous content of the GPixmap is
discarded. */
GPixmap& operator=(const GPixmap &ref);
//@}
/** @name Accessing pixels. */
//@{
/** Returns the number of rows (the image height). */
unsigned int rows() const;
/** Returns the number of columns (the image width). */
unsigned int columns() const;
/** Returns a constant pointer to the first GPixel in row #row#. This
pointer can be used as an array to read the row elements. */
const GPixel * operator[] (int row) const;
/** Returns a pointer to the first GPixel in row #row#. This pointer can be
used as an array to read or write the row elements. */
GPixel * operator[] (int row);
/** Returns the length (in pixels) of a row in memory. This number is equal
to the difference between pointers to pixels located in the same column
in consecutive rows. This difference may be larger than the number of
columns in the image. */
unsigned int rowsize() const;
//@}
/** @name Resampling images. */
//@{
/** Resets this GPixmap with a subsampled segment of color image #src#.
This function conceptually rescales image #src# by a factor #1:factor#,
and copies rectangle #rect# of the subsampled image into the current GPixmap.
The full subsampled image is copied if #rect# is a null pointer.
Both operations are however performed together for efficiency reasons.
Subsampling works by averaging the colors of the source pixels located
in small squares of size #factor# times #factor#. */
void downsample(const GPixmap *src, int factor, const GRect *rect=0);
/** Resets this GPixmap with a oversampled segment of color image #src#.
This function conceptually rescales image #src# by a factor #factor:1#,
and copies rectangle #rect# of the oversampled image into the current
GPixmap. The full oversampled image is copied if #rect# is a null
pointer. Both operations are however performed together for efficiency
reasons. Oversampling works by replicating the color of the source
pixels into squares of size #factor# times #factor#. */
void upsample(const GPixmap *src, int factor, const GRect *rect=0);
/** Resets this GPixmap with a rescaled segment of #src# (zoom 75%). This
function conceptually rescales image #src# by a factor #3:4#, and copies
rectangle #rect# of the rescaled image into the current GPixmap. The
full rescaled image is copied if #rect# is a null pointer. Both
operations are however performed together for efficiency reasons. This
function has been superseded by class \Ref{GPixmapScaler}. */
void downsample43(const GPixmap *src, const GRect *rect=0);
/** Resets this GPixmap with a rescaled segment of #src# (zoom 150%). This
function conceptually rescales image #src# by a factor #3:2# and copies
rectangle #rect# of the rescaled image into the current GPixmap. The
full rescaled image is copied if #rect# is a null pointer. Both
operations are however performed together for efficiency reasons. This
function has been superseded by class \Ref{GPixmapScaler}. */
void upsample23(const GPixmap *src, const GRect *rect=0);
//@}
/** @name Blitting and applying stencils.
These function is essential for rendering DjVu images. The elementary
functions are \Ref{attenuate} and \Ref{blit}. The combined functions
\Ref{blend} and \Ref{stencil} should be viewed as optimizations. */
//@{
/** Attenuates the color image in preparation for a blit.
Bitmap #bm# is positionned at location #x#,#y# over this color image.
The matching color image pixels are then multiplied by #1.0-Alpha# where
#Alpha# denotes the gray value, in range #[0,1]#, represented by the
corresponding pixel of bitmap #bm#. */
void attenuate(const GBitmap *bm, int x, int y);
/** Blits solid color #color# through transparency mask #bm#.
Bitmap #bm# is positionned at location #x#,#y# over this color image.
The matching color image pixels are then modified by adding color
#color# multiplied by #Alpha#, where #Alpha# denotes the gray value, in
range #[0,1]#, represented by the corresponding pixel of bitmap #bm#. */
void blit(const GBitmap *bm, int x, int y, const GPixel *color);
/** Blits pixmap #color# through transparency mask #bm#.
Bitmap #bm# is positionned at location #x#,#y# over this color image.
The matching color image pixels are then modified by adding the
corresponding pixel color in pixmap #color#, multiplied by #Alpha#,
where #Alpha# denotes the gray value, in range #[0,1]#, represented by
the corresponding pixel of bitmap #bm#. */
void blit(const GBitmap *bm, int x, int y, const GPixmap *color);
/** Performs alpha blending. This function is similar to first calling
\Ref{attenuate} with alpha map #bm# and then calling \Ref{blit} with
alpha map #bm# and color map #color#. Both operations are performed
together for efficiency reasons. */
void blend(const GBitmap *bm, int x, int y, const GPixmap *color);
/** Resample color pixmap and performs color corrected alpha blending. This
function conceptually computes an intermediate color image by first
upsampling the GPixmap #pm# by a factor #pms:1# (see \Ref{upsample}),
extracting the sub-image designated by rectangle #pmr# and applying
color correction #corr# (see \Ref{color_correct}). This intermediate
color image is then blended into this pixel map according to the alpha
map #bm# (see \Ref{blend}). */
void stencil(const GBitmap *bm,
const GPixmap *pm, int pms,
const GRect *pmr, double corr=1.0);
//@}
/** @name Manipulating colors. */
//@{
/** Dithers the image to 216 colors. This function applies an ordered
dithering algorithm to reduce the image to 216 predefined colors. These
predefined colors are located on a color cube of 6x6x6 colors: the color
RGB coordinates can only take the following values: #0#, #51#, #102#,
#163#, #214# or #255#. This is useful for displaying images on a device
supporting a maximum of 256 colors. Arguments #xmin# and #ymin# control
the position of the dithering grids. This is useful for dithering tiled
images. Arguments #xmin# and #ymin# must be the position of the bottom
left corner of the tile contained in this GPixmap. Properly setting
these arguments eliminates dithering artifacts on the tile
boundaries. */
void ordered_666_dither(int xmin=0, int ymin=0);
/** Dithers the image to 32768 colors. This function applies an ordered
dithering algorithm to reduce the image to 32768 predefined colors.
These predefined colors are located on a color cube of 32x32x32 colors:
the color RGB coordinates can only take values in which the three least
significant bits are set to #1#. This is useful for displaying images
with less than 24 bits per pixel. Arguments #xmin# and #ymin# control
the position of the dithering grids. This is useful for dithering tiled
images. Arguments #xmin# and #ymin# must be the position of the bottom
left corner of the tile contained in this GPixmap. Properly setting
these arguments eliminates dithering artifacts on the tile
boundaries. */
void ordered_32k_dither(int xmin=0, int ymin=0);
/** Applies a luminance gamma correction factor of #corr#. Values greater than
#1.0# make the image brighter. Values smaller than #1.0# make the image
darker. The documentation of program \Ref{ppmcoco} explains how to
properly use this function. */
void color_correct(double corr);
/** Applies a luminance gamma correction to an array of pixels.
This function is {\em static} and does not modify this pixmap. */
static void color_correct(double corr, GPixel *pixels, int npixels);
//@}
/** @name Miscellaneous. */
//@{
/** Returns the number of bytes allocated for this image. */
inline unsigned int get_memory_usage() const;
/** Saves the image into ByteStream #bs# using the PPM format.
Argument #raw# selects the ``Raw PPM'' (1) or the ``Ascii PPM'' (0) format.
See \Ref{PNM and RLE file formats} for more information. */
void save_ppm(ByteStream &bs, int raw=1) const;
//@}
/** @name Stealing or borrowing the memory buffer (advanced). */
//@{
/** Steals the memory buffer of a GPixmap. This function returns the
address of the memory buffer allocated by this GPixmap object. The
offset of the first pixel in the bottom line is written into variable
#offset#. Other lines can be accessed using pointer arithmetic (see
\Ref{rowsize}). The GPixmap object no longer ``owns'' the buffer: you
must explicitly de-allocate the buffer using #operator delete []#. This
de-allocation should take place after the destruction or the
re-initialization of the GPixmap object. This function will return a
null pointer if the GPixmap object does not ``own'' the buffer in the
first place. */
GPixel *take_data(size_t &offset);
/** Initializes this GPixmap by borrowing a memory segment. The GPixmap
then directly addresses the memory buffer #data# provided by the user.
This buffer must be large enough to hold #w*h# GPixels. The GPixmap
object does not ``own'' the buffer: you must explicitly de-allocate the
buffer using #operator delete []#. This de-allocation should take place
after the destruction or the re-initialization of the GPixmap object. */
inline void borrow_data(GPixel &data, int w, int h);
/// Identical to the above, but GPixmap will do the delete [].
void donate_data(GPixel *data, int w, int h);
/** Rotates pixmap by 90, 180 or 270 degrees anticlockwise
and returns a new pixmap, input pixmap is not changed.
count can be 1, 2, or 3 for 90, 180, 270 degree rotation.
It returns the same pixmap if not rotated. */
GP<GPixmap> rotate(int count=0);
//@}
// Please ignore these two functions. Their only purpose is to allow
// DjVu viewer compile w/o errors. eaf.
// Is this still useful ?. lyb.
int get_grays(void) const { return 256; };
void set_grays(int) {};\
protected:
// data
unsigned short nrows;
unsigned short ncolumns;
unsigned short nrowsize;
GPixel *pixels;
GPixel *pixels_data;
friend class DjVu_PixImage;
};
//@}
// INLINE --------------------------
inline int
operator==(const GPixel & p1, const GPixel & p2)
{
return p1.r==p2.r && p1.g==p2.g && p1.b==p2.b;
}
inline int
operator!=(const GPixel & p1, const GPixel & p2)
{
return p1.r!=p2.r || p1.g!=p2.g || p1.b!=p2.b;
}
inline unsigned int
hash(const GPixel &p)
{
unsigned int x = (p.b<<16)|(p.g<<8)|(p.r);
return x ^ (p.b<<4) ^ (p.r<<12);
}
inline unsigned int
GPixmap::rows() const
{
return nrows;
}
inline unsigned int
GPixmap::columns() const
{
return ncolumns;
}
inline unsigned int
GPixmap::rowsize() const
{
return nrowsize;
}
inline GPixel *
GPixmap::operator[](int row)
{
if (row<0 || row>=nrows || !pixels) return 0;
return &pixels[row * nrowsize];
}
inline const GPixel *
GPixmap::operator[](int row) const
{
if (row<0 || row>=nrows) return 0;
return &pixels[row * nrowsize];
}
inline GPixmap &
GPixmap::operator=(const GBitmap &ref)
{
init(ref);
return *this;
}
inline GPixmap &
GPixmap::operator=(const GPixmap &ref)
{
init(ref);
return *this;
}
inline void
GPixmap::borrow_data(GPixel &data, int w, int h)
{
donate_data(&data,w,h);
pixels_data=0;
}
//////////////////////////////////////////////////
// Memory usage
//////////////////////////////////////////////////
inline unsigned int
GPixmap::get_memory_usage() const
{
return sizeof(GPixmap)+(nrows * ncolumns * sizeof(GPixel));
}
// ---------------------------------
#ifdef HAVE_NAMESPACES
}
# ifndef NOT_USING_DJVU_NAMESPACE
using namespace DJVU;
# endif
#endif
#endif
|