summaryrefslogtreecommitdiffstats
path: root/kviewshell/plugins/djvu/libdjvu/GScaler.h
blob: 4843f6d0a36264c118580614ccd9f600870fc1e8 (plain)
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
//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: GScaler.h,v 1.9 2003/11/07 22:08:21 leonb Exp $
// $Name: release_3_5_15 $

#ifndef _GSCALER_H_
#define _GSCALER_H_
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if NEED_GNUG_PRAGMAS
# pragma interface
#endif

// From: Leon Bottou, 1/31/2002
// Almost equal to my initial code.

#include "GException.h"
#include "GRect.h"
#include "GBitmap.h"
#include "GPixmap.h"

#ifdef HAVE_NAMESPACES
namespace DJVU {
# ifdef NOT_DEFINED // Just to fool emacs c++ mode
}
#endif
#endif


/** @name GScaler.h 

    Files #"GScaler.h"# and #"GScaler.cpp"# implement a fast bilinear
    interpolation scheme to rescale a \Ref{GBitmap} or a \Ref{GPixmap}.
    Common setup functions are implemented by the base class \Ref{GScaler}.
    The actual function for rescaling a gray level image is implemented by
    class \Ref{GBitmapScaler}.  The actual function for rescaling a color
    image is implemented by class \Ref{GPixmapScaler}.

    {\bf Remark} --- The bilinear interpolation code relies on fixed precision
    tables.  It becomes suboptimal when upsampling (i.e. zooming into) an
    image by a factor greater than eight.  High contrast images displayed at
    high magnification may contain visible jaggies.

    @memo
    Rescaling images with bilinear interpolation.
    @author
    L\'eon Bottou <leonb@research.att.com>
    @version
    #$Id: GScaler.h,v 1.9 2003/11/07 22:08:21 leonb Exp $# */
//@{


/** Base class for GBitmapScaler and GPixmapScaler.  This base class
    implements the common elements of class \Ref{GBitmapScaler} and
    \Ref{GPixmapScaler}.  Functions \Ref{set_input_size} and
    \Ref{set_output_size} are used to specify the size of the input image and
    the size of the output image.  Functions \Ref{set_horz_ratio} and
    \Ref{set_vert_ratio} may be used to override the scaling ratios computed
    from the image sizes.  You can then call function \Ref{get_input_rect} to
    know which pixels of the input image are necessary to compute a specified
    rectangular zone of the output image.  The actual computation is then
    performed by calling function #scale# in class \Ref{GBitmapScaler} and
    \Ref{GPixmapScaler}.  
*/
class GScaler  : public GPEnabled
{
protected:  
  GScaler();
public:
  virtual ~GScaler();
  /** Sets the size of the input image. Argument #w# (resp. #h#) contains the
      horizontal (resp. vertical) size of the input image.  This size is used
      to initialize the internal data structures of the scaler object. */
  void set_input_size(int w, int h);
  /** Sets the size of the output image. Argument #w# (resp. #h#) contains the
      horizontal (resp. vertical) size of the output image. This size is used
      to initialize the internal data structures of the scaler object. */
  void set_output_size(int w, int h);
  /** Sets the horizontal scaling ratio #numer/denom#.  This function may be
      used to force an exact scaling ratio.  The scaling ratios are otherwise
      derived from the sizes of the input and output images. */
  void set_horz_ratio(int numer, int denom);
  /** Sets the vertical scaling ratio to #numer/denom#.  This function may be
      used to force an exact scaling ratio.  The scaling ratios are otherwise
      derived from the sizes of the input and output images. */
  void set_vert_ratio(int numer, int denom);
  /** Computes which input pixels are required to compute specified output
      pixels.  Let us assume that we only need a part of the output
      image. This part is defined by rectangle #desired_output#.  Only a part
      of the input image is necessary to compute the output pixels.  Function
      #get_input_rect# computes the coordinates of that part of the input
      image, and stores them into rectangle #required_input#.  */
  void get_input_rect( const GRect &desired_output, GRect &required_input );
protected:
  // The sizes
  int inw, inh;
  int xshift, yshift;
  int redw, redh;
  int outw, outh;
  // Fixed point coordinates
  int *vcoord;
  GPBuffer<int> gvcoord;
  int *hcoord;
  GPBuffer<int> ghcoord;
  // Helper
  void make_rectangles(const GRect &desired, GRect &red, GRect &inp);
};



/** Fast rescaling code for gray level images.  This class augments the base
    class \Ref{GScaler} with a function for rescaling gray level
    images.  Function \Ref{GBitmapScaler::scale} computes an arbitrary segment
    of the output image given the corresponding pixels in the input image.

    {\bf Example} --- The following functions returns an gray level image
    (sixteen gray levels, size #nw# by #nh#) containing a rescaled version of
    the input image #in#.
    \begin{verbatim}
    GBitmap *rescale_bitmap(const GBitmap &in, int nw, int nh)
    {
      int w = in.columns();       // Get input width
      int h = in.raws();          // Get output width
      GBitmapScaler scaler(w,h,nw,nh);  // Creates bitmap scaler
      GRect desired(0,0,nw,nh);   // Desired output = complete bitmap
      GRect provided(0,0,w,h);    // Provided input = complete bitmap
      GBitmap *out = new GBitmap;
      scaler.scale(provided, in, desired, *out);  // Rescale
      out->change_grays(16);      // Reduce to 16 gray levels
      return out;
    }
    \end{verbatim} */
class GBitmapScaler : public GScaler
{
protected:
  GBitmapScaler(void);
  GBitmapScaler(int inw, int inh, int outw, int outh);
public:
  /// Virtual destructor.
  virtual ~GBitmapScaler();

  /** Creates an empty GBitmapScaler. You must call functions
      \Ref{GScaler::set_input_size} and \Ref{GScaler::set_output_size} before
      calling any of the scaling functions. */
  static GP<GBitmapScaler> create(void) {return new GBitmapScaler(); }

  /** Creates a GBitmapScaler. The size of the input image is given by
      #inw# and #inh#.  This function internally calls
      \Ref{GScaler::set_input_size} and \Ref{GScaler::set_output_size}. The
      size of the output image is given by #outw# and #outh#.  . */
  static GP<GBitmapScaler> create(
    const int inw, const int inh, const int outw, const int outh)
  { return new GBitmapScaler(inw,inh,outw,outh); }

  /** Computes a segment of the rescaled output image.  The GBitmap object
      #output# is overwritten with the segment of the output image specified
      by the rectangle #desired_output#.  The rectangle #provided_input#
      specifies which segment of the input image is provided by the GBitmap
      object #input#.  An exception \Ref{GException} is thrown if the
      rectangle #provided_input# is smaller then the rectangle
      #required_input# returned by function \Ref{GScaler::get_input_rect}.
      Note that the output image always contain 256 gray levels. You may want
      to use function \Ref{GBitmap::change_grays} to reduce the number of gray
      levels. */
  void scale( const GRect &provided_input, const GBitmap &input,
              const GRect &desired_output, GBitmap &output );
protected:
  // Helpers
  unsigned char *get_line(int, const GRect &, const GRect &, const GBitmap &);
  // Temporaries
  unsigned char *lbuffer;
  GPBuffer<unsigned char> glbuffer;
  unsigned char *conv;
  GPBuffer<unsigned char> gconv;
  unsigned char *p1;
  GPBuffer<unsigned char> gp1;
  unsigned char *p2;
  GPBuffer<unsigned char> gp2;
  int l1;
  int l2;
};


/** Fast rescaling code for color images.  This class augments the base class
    \Ref{GScaler} with a function for rescaling color images.  Function
    \Ref{GPixmapScaler::scale} computes an arbitrary segment of the output
    image given the corresponding pixels in the input image.

    {\bf Example} --- The following functions returns a color image
    of size #nw# by #nh# containing a rescaled version of
    the input image #in#.
    \begin{verbatim}
    GPixmap *rescale_pixmap(const GPixmap &in, int nw, int nh)
    {
      int w = in.columns();       // Get input width
      int h = in.raws();          // Get output width
      GPixmapScaler scaler(w,h,nw,nh);  // Creates bitmap scaler
      GRect desired(0,0,nw,nh);   // Desired output = complete image
      GRect provided(0,0,w,h);    // Provided input = complete image
      GPixmap *out = new GPixmap;
      scaler.scale(provided, in, desired, *out);  // Rescale
      return out;
    }
    \end{verbatim}

 */
class GPixmapScaler : public GScaler
{
protected:
  GPixmapScaler(void);
  GPixmapScaler(int inw, int inh, int outw, int outh);
public:
  /// Virtual destructor.
  virtual ~GPixmapScaler();

  /** Creates an empty GPixmapScaler. You must call functions
      \Ref{GScaler::set_input_size} and \Ref{GScaler::set_output_size} before
      calling any of the scaling functions. */
  static GP<GPixmapScaler> create(void) {return new GPixmapScaler(); }

  /** Creates a GPixmapScaler. The size of the input image is given by
      #inw# and #inh#.  This function internally calls
      \Ref{GScaler::set_input_size} and \Ref{GScaler::set_output_size}. The
      size of the output image is given by #outw# and #outh#.  . */
  static GP<GPixmapScaler> create(
    const int inw, const int inh, const int outw, const int outh)
  { return new GPixmapScaler(inw,inh,outw,outh); }

  /** Computes a segment of the rescaled output image.  The pixmap #output# is
      overwritten with the segment of the output image specified by the
      rectangle #desired_output#.  The rectangle #provided_input# specifies
      which segment of the input image is provided in the pixmap #input#.  An
      exception \Ref{GException} is thrown if the rectangle #provided_input#
      is smaller then the rectangle #required_input# returned by function
      \Ref{GScaler::get_input_rect}. */
  void scale( const GRect &provided_input, const GPixmap &input,
              const GRect &desired_output, GPixmap &output );
protected:
  // Helpers
  GPixel *get_line(int, const GRect &, const GRect &, const GPixmap &);
  // Temporaries
  GPixel *lbuffer;
  GPBufferBase glbuffer;
  GPixel *p1;
  GPBufferBase gp1;
  GPixel *p2;
  GPBufferBase gp2;
  int    l1;
  int    l2;
};





//@}
    



// -------- END

#ifdef HAVE_NAMESPACES
}
# ifndef NOT_USING_DJVU_NAMESPACE
using namespace DJVU;
# endif
#endif
#endif