~ubuntu-branches/ubuntu/intrepid/gwenview/intrepid

« back to all changes in this revision

Viewing changes to gvimageutils/scale.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Christopher Martin
  • Date: 2005-04-06 11:33:06 UTC
  • mfrom: (1.2.1 upstream) (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20050406113306-7zovl7z0io5bacpd
Tags: 1.2.0-1
* New upstream release.
  + Fixes crashes when using "Back" to navigate. (Closes: #301811)
* Enable KIPI support.
* Add a doc-base file for the handbook.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// This file includes code for scaling images, in two versions.
 
2
// One ported from ImageMagick (slower, but can achieve better quality),
 
3
// and from Imlib2 ported by Mosfet (very fast).
 
4
 
 
5
 
 
6
// ImageMagick code begin
 
7
// ----------------------
 
8
 
 
9
// This code is ImageMagick's resize code, adapted for QImage, with
 
10
// fastfloat class added as an optimization.
 
11
// The original license text follows.
 
12
 
 
13
/*
 
14
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
15
%                                                                             %
 
16
%                                                                             %
 
17
%                 RRRR   EEEEE  SSSSS  IIIII  ZZZZZ  EEEEE                    %
 
18
%                 R   R  E      SS       I       ZZ  E                        %
 
19
%                 RRRR   EEE     SSS     I     ZZZ   EEE                      %
 
20
%                 R R    E         SS    I    ZZ     E                        %
 
21
%                 R  R   EEEEE  SSSSS  IIIII  ZZZZZ  EEEEE                    %
 
22
%                                                                             %
 
23
%                     ImageMagick Image Resize Methods                        %
 
24
%                                                                             %
 
25
%                                                                             %
 
26
%                              Software Design                                %
 
27
%                                John Cristy                                  %
 
28
%                                 July 1992                                   %
 
29
%                                                                             %
 
30
%                                                                             %
 
31
%  Copyright (C) 2003 ImageMagick Studio, a non-profit organization dedicated %
 
32
%  to making software imaging solutions freely available.                     %
 
33
%                                                                             %
 
34
%  Permission is hereby granted, free of charge, to any person obtaining a    %
 
35
%  copy of this software and associated documentation files ("ImageMagick"),  %
 
36
%  to deal in ImageMagick without restriction, including without limitation   %
 
37
%  the rights to use, copy, modify, merge, publish, distribute, sublicense,   %
 
38
%  and/or sell copies of ImageMagick, and to permit persons to whom the       %
 
39
%  ImageMagick is furnished to do so, subject to the following conditions:    %
 
40
%                                                                             %
 
41
%  The above copyright notice and this permission notice shall be included in %
 
42
%  all copies or substantial portions of ImageMagick.                         %
 
43
%                                                                             %
 
44
%  The software is provided "as is", without warranty of any kind, express or %
 
45
%  implied, including but not limited to the warranties of merchantability,   %
 
46
%  fitness for a particular purpose and noninfringement.  In no event shall   %
 
47
%  ImageMagick Studio be liable for any claim, damages or other liability,    %
 
48
%  whether in an action of contract, tort or otherwise, arising from, out of  %
 
49
%  or in connection with ImageMagick or the use or other dealings in          %
 
50
%  ImageMagick.                                                               %
 
51
%                                                                             %
 
52
%  Except as contained in this notice, the name of the ImageMagick Studio     %
 
53
%  shall not be used in advertising or otherwise to promote the sale, use or  %
 
54
%  other dealings in ImageMagick without prior written authorization from the %
 
55
%  ImageMagick Studio.                                                        %
 
56
%                                                                             %
 
57
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
58
%
 
59
%
 
60
*/
 
61
 
 
62
// Qt
 
63
#include <qimage.h>
 
64
#include <qcolor.h>
 
65
 
 
66
#include <kdeversion.h>
 
67
#if KDE_IS_VERSION(3, 2, 0)
 
68
#include <kcpuinfo.h>
 
69
#else
 
70
#include <libgvcompat/kcpuinfo.h>
 
71
#endif
 
72
 
 
73
#include <string.h>
 
74
#include <stdlib.h>
 
75
 
 
76
// Local
 
77
#include "gvimageutils.h"
 
78
 
 
79
// everything in namespace
 
80
namespace GVImageUtils {
 
81
 
 
82
 
 
83
#define Max QMAX
 
84
#define Min QMIN
 
85
 
 
86
// mustn't be less than used precision (i.e. 1/fastfloat::RATIO)
 
87
#define MagickEpsilon 0.0002
 
88
 
 
89
// fastfloat begin
 
90
// this class stores floating point numbers as integers, with BITS shift,
 
91
// i.e. value XYZ is stored as XYZ * RATIO
 
92
struct fastfloat
 
93
    {
 
94
    private:
 
95
        enum { BITS = 12, RATIO = 4096 };
 
96
    public:
 
97
        fastfloat() {}
 
98
        fastfloat( long v ) : value( v << BITS ) {}
 
99
        fastfloat( int v ) : value( v << BITS ) {}
 
100
        fastfloat( double v ) : value( static_cast< long >( v * RATIO + 0.5 )) {}
 
101
        double toDouble() const { return static_cast< double >( value ) / RATIO; }
 
102
        long toLong() const { return value >> BITS; }
 
103
        fastfloat& operator += ( fastfloat r ) { value += r.value; return *this; }
 
104
        fastfloat& operator -= ( fastfloat r ) { value -= r.value; return *this; }
 
105
        fastfloat& operator *= ( fastfloat r ) { value = static_cast< long long >( value ) * r.value >> BITS; return *this; }
 
106
        fastfloat& operator /= ( fastfloat r ) { value = ( static_cast< long long >( value ) << BITS ) / r.value; return *this; }
 
107
        bool operator< ( fastfloat r ) const { return value < r.value; }
 
108
        bool operator<= ( fastfloat r ) const { return value <= r.value; }
 
109
        bool operator> ( fastfloat r ) const { return value > r.value; }
 
110
        bool operator>= ( fastfloat r ) const { return value >= r.value; }
 
111
        bool operator== ( fastfloat r ) const { return value == r.value; }
 
112
        bool operator!= ( fastfloat r ) const { return value != r.value; }
 
113
        fastfloat operator-() const { return fastfloat( -value, false ); }
 
114
    private:
 
115
        fastfloat( long v, bool ) : value( v ) {} // for operator-()
 
116
        long value;
 
117
    };
 
118
 
 
119
inline fastfloat operator+ ( fastfloat l, fastfloat r ) { return fastfloat( l ) += r; }
 
120
inline fastfloat operator- ( fastfloat l, fastfloat r ) { return fastfloat( l ) -= r; }
 
121
inline fastfloat operator* ( fastfloat l, fastfloat r ) { return fastfloat( l ) *= r; }
 
122
inline fastfloat operator/ ( fastfloat l, fastfloat r ) { return fastfloat( l ) /= r; }
 
123
 
 
124
inline bool operator< ( fastfloat l, double r ) { return l < fastfloat( r ); }
 
125
inline bool operator<= ( fastfloat l, double r ) { return l <= fastfloat( r ); }
 
126
inline bool operator> ( fastfloat l, double r ) { return l > fastfloat( r ); }
 
127
inline bool operator>= ( fastfloat l, double r ) { return l >= fastfloat( r ); }
 
128
inline bool operator== ( fastfloat l, double r ) { return l == fastfloat( r ); }
 
129
inline bool operator!= ( fastfloat l, double r ) { return l != fastfloat( r ); }
 
130
 
 
131
inline bool operator< ( double l, fastfloat r ) { return fastfloat( l ) < r ; }
 
132
inline bool operator<= ( double l, fastfloat r ) { return fastfloat( l ) <= r ; }
 
133
inline bool operator> ( double l, fastfloat r ) { return fastfloat( l ) > r ; }
 
134
inline bool operator>= ( double l, fastfloat r ) { return fastfloat( l ) >= r ; }
 
135
inline bool operator== ( double l, fastfloat r ) { return fastfloat( l ) == r ; }
 
136
inline bool operator!= ( double l, fastfloat r ) { return fastfloat( l ) != r ; }
 
137
 
 
138
inline double fasttodouble( fastfloat v ) { return v.toDouble(); }
 
139
inline long fasttolong( fastfloat v ) { return v.toLong(); }
 
140
 
 
141
#if 1  // change to 0 to turn fastfloat usage off
 
142
#else
 
143
#define fastfloat double
 
144
#define fasttodouble( v ) double( v )
 
145
#define fasttolong( v ) long( v )
 
146
#endif
 
147
 
 
148
//fastfloat end
 
149
 
 
150
 
 
151
typedef fastfloat (*Filter)(const fastfloat, const fastfloat);
 
152
 
 
153
typedef struct _ContributionInfo
 
154
{
 
155
  fastfloat
 
156
    weight;
 
157
 
 
158
  long
 
159
    pixel;
 
160
} ContributionInfo;
 
161
 
 
162
 
 
163
/*
 
164
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
165
%                                                                             %
 
166
%                                                                             %
 
167
%                                                                             %
 
168
%   R e s i z e I m a g e                                                     %
 
169
%                                                                             %
 
170
%                                                                             %
 
171
%                                                                             %
 
172
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
173
%
 
174
%  ResizeImage() scales an image to the desired dimensions with one of these
 
175
%  filters:
 
176
%
 
177
%    Bessel   Blackman   Box
 
178
%    Catrom   Cubic      Gaussian
 
179
%    Hanning  Hermite    Lanczos
 
180
%    Mitchell Point      Quandratic
 
181
%    Sinc     Triangle
 
182
%
 
183
%  Most of the filters are FIR (finite impulse response), however, Bessel,
 
184
%  Gaussian, and Sinc are IIR (infinite impulse response).  Bessel and Sinc
 
185
%  are windowed (brought down to zero) with the Blackman filter.
 
186
%
 
187
%  ResizeImage() was inspired by Paul Heckbert's zoom program.
 
188
%
 
189
%  The format of the ResizeImage method is:
 
190
%
 
191
%      Image *ResizeImage(Image *image,const unsigned long columns,
 
192
%        const unsigned long rows,const FilterTypes filter,const double blur,
 
193
%        ExceptionInfo *exception)
 
194
%
 
195
%  A description of each parameter follows:
 
196
%
 
197
%    o image: The image.
 
198
%
 
199
%    o columns: The number of columns in the scaled image.
 
200
%
 
201
%    o rows: The number of rows in the scaled image.
 
202
%
 
203
%    o filter: Image filter to use.
 
204
%
 
205
%    o blur: The blur factor where > 1 is blurry, < 1 is sharp.
 
206
%
 
207
%    o exception: Return any errors or warnings in this structure.
 
208
%
 
209
%
 
210
*/
 
211
 
 
212
#if 0
 
213
static fastfloat Bessel(const fastfloat x,const fastfloat)
 
214
{
 
215
  if (x == 0.0)
 
216
    return(MagickPI/4.0);
 
217
  return(BesselOrderOne(MagickPI*x)/(2.0*x));
 
218
}
 
219
 
 
220
static fastfloat Sinc(const fastfloat x,const fastfloat)
 
221
{
 
222
  if (x == 0.0)
 
223
    return(1.0);
 
224
  return(sin(MagickPI*x)/(MagickPI*x));
 
225
}
 
226
 
 
227
static fastfloat Blackman(const fastfloat x,const fastfloat)
 
228
{
 
229
  return(0.42+0.5*cos(MagickPI*x)+0.08*cos(2*MagickPI*x));
 
230
}
 
231
 
 
232
static fastfloat BlackmanBessel(const fastfloat x,const fastfloat)
 
233
{
 
234
  return(Blackman(x/support,support)*Bessel(x,support));
 
235
}
 
236
 
 
237
static fastfloat BlackmanSinc(const fastfloat x,const fastfloat)
 
238
{
 
239
  return(Blackman(x/support,support)*Sinc(x,support));
 
240
}
 
241
#endif
 
242
 
 
243
static fastfloat Box(const fastfloat x,const fastfloat)
 
244
{
 
245
  if (x < -0.5)
 
246
    return(0.0);
 
247
  if (x < 0.5)
 
248
    return(1.0);
 
249
  return(0.0);
 
250
}
 
251
 
 
252
#if 0
 
253
static fastfloat Catrom(const fastfloat x,const fastfloat)
 
254
{
 
255
  if (x < -2.0)
 
256
    return(0.0);
 
257
  if (x < -1.0)
 
258
    return(0.5*(4.0+x*(8.0+x*(5.0+x))));
 
259
  if (x < 0.0)
 
260
    return(0.5*(2.0+x*x*(-5.0-3.0*x)));
 
261
  if (x < 1.0)
 
262
    return(0.5*(2.0+x*x*(-5.0+3.0*x)));
 
263
  if (x < 2.0)
 
264
    return(0.5*(4.0+x*(-8.0+x*(5.0-x))));
 
265
  return(0.0);
 
266
}
 
267
 
 
268
static fastfloat Cubic(const fastfloat x,const fastfloat)
 
269
{
 
270
  if (x < -2.0)
 
271
    return(0.0);
 
272
  if (x < -1.0)
 
273
    return((2.0+x)*(2.0+x)*(2.0+x)/6.0);
 
274
  if (x < 0.0)
 
275
    return((4.0+x*x*(-6.0-3.0*x))/6.0);
 
276
  if (x < 1.0)
 
277
    return((4.0+x*x*(-6.0+3.0*x))/6.0);
 
278
  if (x < 2.0)
 
279
    return((2.0-x)*(2.0-x)*(2.0-x)/6.0);
 
280
  return(0.0);
 
281
}
 
282
 
 
283
static fastfloat Gaussian(const fastfloat x,const fastfloat)
 
284
{
 
285
  return(exp(-2.0*x*x)*sqrt(2.0/MagickPI));
 
286
}
 
287
 
 
288
static fastfloat Hanning(const fastfloat x,const fastfloat)
 
289
{
 
290
  return(0.5+0.5*cos(MagickPI*x));
 
291
}
 
292
 
 
293
static fastfloat Hamming(const fastfloat x,const fastfloat)
 
294
{
 
295
  return(0.54+0.46*cos(MagickPI*x));
 
296
}
 
297
 
 
298
static fastfloat Hermite(const fastfloat x,const fastfloat)
 
299
{
 
300
  if (x < -1.0)
 
301
    return(0.0);
 
302
  if (x < 0.0)
 
303
    return((2.0*(-x)-3.0)*(-x)*(-x)+1.0);
 
304
  if (x < 1.0)
 
305
    return((2.0*x-3.0)*x*x+1.0);
 
306
  return(0.0);
 
307
}
 
308
 
 
309
static fastfloat Lanczos(const fastfloat x,const fastfloat support)
 
310
{
 
311
  if (x < -3.0)
 
312
    return(0.0);
 
313
  if (x < 0.0)
 
314
    return(Sinc(-x,support)*Sinc(-x/3.0,support));
 
315
  if (x < 3.0)
 
316
    return(Sinc(x,support)*Sinc(x/3.0,support));
 
317
  return(0.0);
 
318
}
 
319
#endif
 
320
 
 
321
static fastfloat Mitchell(const fastfloat x,const fastfloat)
 
322
{
 
323
#define B   (1.0/3.0)
 
324
#define C   (1.0/3.0)
 
325
#define P0  ((  6.0- 2.0*B       )/6.0)
 
326
#define P2  ((-18.0+12.0*B+ 6.0*C)/6.0)
 
327
#define P3  (( 12.0- 9.0*B- 6.0*C)/6.0)
 
328
#define Q0  ((       8.0*B+24.0*C)/6.0)
 
329
#define Q1  ((     -12.0*B-48.0*C)/6.0)
 
330
#define Q2  ((       6.0*B+30.0*C)/6.0)
 
331
#define Q3  ((     - 1.0*B- 6.0*C)/6.0)
 
332
 
 
333
  if (x < -2.0)
 
334
    return(0.0);
 
335
  if (x < -1.0)
 
336
    return(Q0-x*(Q1-x*(Q2-x*Q3)));
 
337
  if (x < 0.0)
 
338
    return(P0+x*x*(P2-x*P3));
 
339
  if (x < 1.0)
 
340
    return(P0+x*x*(P2+x*P3));
 
341
  if (x < 2.0)
 
342
    return(Q0+x*(Q1+x*(Q2+x*Q3)));
 
343
  return(0.0);
 
344
}
 
345
 
 
346
#if 0
 
347
static fastfloat Quadratic(const fastfloat x,const fastfloat)
 
348
{
 
349
  if (x < -1.5)
 
350
    return(0.0);
 
351
  if (x < -0.5)
 
352
    return(0.5*(x+1.5)*(x+1.5));
 
353
  if (x < 0.5)
 
354
    return(0.75-x*x);
 
355
  if (x < 1.5)
 
356
    return(0.5*(x-1.5)*(x-1.5));
 
357
  return(0.0);
 
358
}
 
359
#endif
 
360
 
 
361
static fastfloat Triangle(const fastfloat x,const fastfloat)
 
362
{
 
363
  if (x < -1.0)
 
364
    return(0.0);
 
365
  if (x < 0.0)
 
366
    return(1.0+x);
 
367
  if (x < 1.0)
 
368
    return(1.0-x);
 
369
  return(0.0);
 
370
}
 
371
 
 
372
static void HorizontalFilter(const QImage& source,QImage& destination,
 
373
  const fastfloat x_factor,const fastfloat blur,
 
374
  ContributionInfo *contribution, Filter filter, fastfloat filtersupport)
 
375
{
 
376
  fastfloat
 
377
    center,
 
378
    density,
 
379
    scale,
 
380
    support;
 
381
 
 
382
  long
 
383
    n,
 
384
    start,
 
385
    stop,
 
386
    y;
 
387
 
 
388
  register long
 
389
    i,
 
390
    x;
 
391
 
 
392
  /*
 
393
    Apply filter to resize horizontally from source to destination.
 
394
  */
 
395
  scale=blur*Max(1.0/x_factor,1.0);
 
396
  support=scale* filtersupport;
 
397
  if (support <= 0.5)
 
398
    {
 
399
      /*
 
400
        Reduce to point sampling.
 
401
      */
 
402
      support=0.5+MagickEpsilon;
 
403
      scale=1.0;
 
404
    }
 
405
  scale=1.0/scale;
 
406
  for (x=0; x < (long) destination.width(); x++)
 
407
  {
 
408
    center=(fastfloat) (x+0.5)/x_factor;
 
409
    start= fasttolong(Max(center-support+0.5,0));
 
410
    stop= fasttolong(Min(center+support+0.5,source.width()));
 
411
    density=0.0;
 
412
    for (n=0; n < (stop-start); n++)
 
413
    {
 
414
      contribution[n].pixel=start+n;
 
415
      contribution[n].weight=
 
416
        filter (scale*(start+n-center+0.5), filtersupport );
 
417
      density+=contribution[n].weight;
 
418
    }
 
419
    if ((density != 0.0) && (density != 1.0))
 
420
      {
 
421
        /*
 
422
          Normalize.
 
423
        */
 
424
        density=1.0/density;
 
425
        for (i=0; i < n; i++)
 
426
          contribution[i].weight*=density;
 
427
      }
 
428
//    p=AcquireImagePixels(source,contribution[0].pixel,0,contribution[n-1].pixel-
 
429
//      contribution[0].pixel+1,source->rows,exception);
 
430
//    q=SetImagePixels(destination,x,0,1,destination->rows);
 
431
    for (y=0; y < (long) destination.height(); y++)
 
432
    {
 
433
      fastfloat red = 0;
 
434
      fastfloat green = 0;
 
435
      fastfloat blue = 0;
 
436
      fastfloat alpha = 0;
 
437
      for (i=0; i < n; i++)
 
438
      {
 
439
        int px = contribution[i].pixel;
 
440
        int py = y;
 
441
        QRgb p = reinterpret_cast< QRgb* >( source.jumpTable()[ py ])[ px ];
 
442
        red+=contribution[i].weight*qRed(p);
 
443
        green+=contribution[i].weight*qGreen(p);
 
444
        blue+=contribution[i].weight*qBlue(p);
 
445
        alpha+=contribution[i].weight*qAlpha(p);
 
446
      }
 
447
      QRgb pix = qRgba(
 
448
          fasttolong( red < 0 ? 0 : red > 255 ? 255 : red + 0.5 ),
 
449
          fasttolong( green < 0 ? 0 : green > 255 ? 255 : green + 0.5 ),
 
450
          fasttolong( blue < 0 ? 0 : blue > 255 ? 255 : blue + 0.5 ),
 
451
          fasttolong( alpha < 0 ? 0 : alpha > 255 ? 255 : alpha + 0.5 ));
 
452
      reinterpret_cast< QRgb* >( destination.jumpTable()[ y ])[ x ] = pix;
 
453
    }
 
454
  }
 
455
}
 
456
 
 
457
static void VerticalFilter(const QImage& source,QImage& destination,
 
458
  const fastfloat y_factor,const fastfloat blur,
 
459
  ContributionInfo *contribution, Filter filter, fastfloat filtersupport )
 
460
{
 
461
  fastfloat
 
462
    center,
 
463
    density,
 
464
    scale,
 
465
    support;
 
466
 
 
467
  long
 
468
    n,
 
469
    start,
 
470
    stop,
 
471
    x;
 
472
 
 
473
  register long
 
474
    i,
 
475
    y;
 
476
 
 
477
  /*
 
478
    Apply filter to resize vertically from source to destination.
 
479
  */
 
480
  scale=blur*Max(1.0/y_factor,1.0);
 
481
  support=scale* filtersupport;
 
482
  if (support <= 0.5)
 
483
    {
 
484
      /*
 
485
        Reduce to point sampling.
 
486
      */
 
487
      support=0.5+MagickEpsilon;
 
488
      scale=1.0;
 
489
    }
 
490
  scale=1.0/scale;
 
491
  for (y=0; y < (long) destination.height(); y++)
 
492
  {
 
493
    center=(fastfloat) (y+0.5)/y_factor;
 
494
    start= fasttolong(Max(center-support+0.5,0));
 
495
    stop= fasttolong(Min(center+support+0.5,source.height()));
 
496
    density=0.0;
 
497
    for (n=0; n < (stop-start); n++)
 
498
    {
 
499
      contribution[n].pixel=start+n;
 
500
      contribution[n].weight=
 
501
        filter (scale*(start+n-center+0.5), filtersupport);
 
502
      density+=contribution[n].weight;
 
503
    }
 
504
    if ((density != 0.0) && (density != 1.0))
 
505
      {
 
506
        /*
 
507
          Normalize.
 
508
        */
 
509
        density=1.0/density;
 
510
        for (i=0; i < n; i++)
 
511
          contribution[i].weight*=density;
 
512
      }
 
513
//    p=AcquireImagePixels(source,0,contribution[0].pixel,source->columns,
 
514
//      contribution[n-1].pixel-contribution[0].pixel+1,exception);
 
515
//    q=SetImagePixels(destination,0,y,destination->columns,1);
 
516
    for (x=0; x < (long) destination.width(); x++)
 
517
    {
 
518
      fastfloat red = 0;
 
519
      fastfloat green = 0;
 
520
      fastfloat blue = 0;
 
521
      fastfloat alpha = 0;
 
522
      for (i=0; i < n; i++)
 
523
      {
 
524
        int px = x;
 
525
        int py = contribution[i].pixel;
 
526
        QRgb p = reinterpret_cast< QRgb* >( source.jumpTable()[ py ])[ px ];
 
527
        red+=contribution[i].weight*qRed(p);
 
528
        green+=contribution[i].weight*qGreen(p);
 
529
        blue+=contribution[i].weight*qBlue(p);
 
530
        alpha+=contribution[i].weight*qAlpha(p);
 
531
      }
 
532
      QRgb pix = qRgba(
 
533
          fasttolong( red < 0 ? 0 : red > 255 ? 255 : red + 0.5 ),
 
534
          fasttolong( green < 0 ? 0 : green > 255 ? 255 : green + 0.5 ),
 
535
          fasttolong( blue < 0 ? 0 : blue > 255 ? 255 : blue + 0.5 ),
 
536
          fasttolong( alpha < 0 ? 0 : alpha > 255 ? 255 : alpha + 0.5 ));
 
537
      reinterpret_cast< QRgb* >( destination.jumpTable()[ y ])[ x ] = pix;
 
538
    }
 
539
  }
 
540
}
 
541
 
 
542
static QImage ResizeImage(const QImage& image,const int columns,
 
543
  const int rows, Filter filter, fastfloat filtersupport, double blur)
 
544
{
 
545
  ContributionInfo
 
546
    *contribution;
 
547
 
 
548
  fastfloat
 
549
    support,
 
550
    x_factor,
 
551
    x_support,
 
552
    y_factor,
 
553
    y_support;
 
554
 
 
555
  /*
 
556
    Initialize resize image attributes.
 
557
  */
 
558
  if ((columns == image.width()) && (rows == image.height()) && (blur == 1.0))
 
559
    return image.copy();
 
560
  QImage resize_image( columns, rows, 32 );
 
561
  resize_image.setAlphaBuffer( image.hasAlphaBuffer());
 
562
  /*
 
563
    Allocate filter contribution info.
 
564
  */
 
565
  x_factor=(fastfloat) resize_image.width()/image.width();
 
566
  y_factor=(fastfloat) resize_image.height()/image.height();
 
567
//  i=(long) LanczosFilter;
 
568
//  if (image->filter != UndefinedFilter)
 
569
//    i=(long) image->filter;
 
570
//  else
 
571
//    if ((image->storage_class == PseudoClass) || image->matte ||
 
572
//        ((x_factor*y_factor) > 1.0))
 
573
//      i=(long) MitchellFilter;
 
574
  x_support=blur*Max(1.0/x_factor,1.0)*filtersupport;
 
575
  y_support=blur*Max(1.0/y_factor,1.0)*filtersupport;
 
576
  support=Max(x_support,y_support);
 
577
  if (support < filtersupport)
 
578
    support=filtersupport;
 
579
  contribution=new ContributionInfo[ fasttolong( 2.0*Max(support,0.5)+3 ) ];
 
580
  Q_CHECK_PTR( contribution );
 
581
  /*
 
582
    Resize image.
 
583
  */
 
584
  if (((fastfloat) columns*(image.height()+rows)) >
 
585
      ((fastfloat) rows*(image.width()+columns)))
 
586
    {
 
587
      QImage source_image( columns, image.height(), 32 );
 
588
      source_image.setAlphaBuffer( image.hasAlphaBuffer());
 
589
      HorizontalFilter(image,source_image,x_factor,blur,
 
590
        contribution,filter,filtersupport);
 
591
      VerticalFilter(source_image,resize_image,y_factor,
 
592
        blur,contribution,filter,filtersupport);
 
593
    }
 
594
  else
 
595
    {
 
596
      QImage source_image( image.width(), rows, 32 );
 
597
      source_image.setAlphaBuffer( image.hasAlphaBuffer());
 
598
      VerticalFilter(image,source_image,y_factor,blur,
 
599
        contribution,filter,filtersupport);
 
600
      HorizontalFilter(source_image,resize_image,x_factor,
 
601
        blur,contribution,filter,filtersupport);
 
602
    }
 
603
  /*
 
604
    Free allocated memory.
 
605
  */
 
606
  delete[] contribution;
 
607
  return(resize_image);
 
608
}
 
609
 
 
610
 
 
611
#undef Max
 
612
#undef Min
 
613
#undef MagickEpsilon
 
614
 
 
615
 
 
616
// filters and their matching support values
 
617
#if 0
 
618
  static const FilterInfo
 
619
    filters[SincFilter+1] =
 
620
    {
 
621
      { Box, 0.0 },
 
622
      { Box, 0.0 },
 
623
      { Box, 0.5 },
 
624
      { Triangle, 1.0 },
 
625
      { Hermite, 1.0 },
 
626
      { Hanning, 1.0 },
 
627
      { Hamming, 1.0 },
 
628
      { Blackman, 1.0 },
 
629
      { Gaussian, 1.25 },
 
630
      { Quadratic, 1.5 },
 
631
      { Cubic, 2.0 },
 
632
      { Catrom, 2.0 },
 
633
      { Mitchell, 2.0 },
 
634
      { Lanczos, 3.0 },
 
635
      { BlackmanBessel, 3.2383 },
 
636
      { BlackmanSinc, 4.0 }
 
637
    };
 
638
#endif
 
639
 
 
640
 
 
641
/*
 
642
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
643
%                                                                             %
 
644
%                                                                             %
 
645
%                                                                             %
 
646
%   S a m p l e I m a g e                                                     %
 
647
%                                                                             %
 
648
%                                                                             %
 
649
%                                                                             %
 
650
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
651
%
 
652
%  SampleImage() scales an image to the desired dimensions with pixel
 
653
%  sampling.  Unlike other scaling methods, this method does not introduce
 
654
%  any additional color into the scaled image.
 
655
%
 
656
%  The format of the SampleImage method is:
 
657
%
 
658
%      Image *SampleImage(const Image *image,const unsigned long columns,
 
659
%        const unsigned long rows,ExceptionInfo *exception)
 
660
%
 
661
%  A description of each parameter follows:
 
662
%
 
663
%    o image: The image.
 
664
%
 
665
%    o columns: The number of columns in the sampled image.
 
666
%
 
667
%    o rows: The number of rows in the sampled image.
 
668
%
 
669
%    o exception: Return any errors or warnings in this structure.
 
670
%
 
671
%
 
672
*/
 
673
QImage SampleImage(const QImage& image,const int columns,
 
674
  const int rows)
 
675
{
 
676
  int
 
677
    *x_offset,
 
678
    *y_offset;
 
679
 
 
680
  long
 
681
    j,
 
682
    y;
 
683
 
 
684
  uchar
 
685
    *pixels;
 
686
 
 
687
  register const uchar
 
688
    *p;
 
689
 
 
690
  register long
 
691
    x;
 
692
 
 
693
  register uchar
 
694
    *q;
 
695
 
 
696
  /*
 
697
    Initialize sampled image attributes.
 
698
  */
 
699
  if ((columns == image.width()) && (rows == image.height()))
 
700
    return image;
 
701
  // This function is modified to handle any image depth, not only
 
702
  // 32bit like the ImageMagick original. This avoids the relatively
 
703
  // expensive conversion.
 
704
  const int d = image.depth() / 8;
 
705
  QImage sample_image( columns, rows, image.depth());
 
706
  sample_image.setAlphaBuffer( image.hasAlphaBuffer());
 
707
  /*
 
708
    Allocate scan line buffer and column offset buffers.
 
709
  */
 
710
  pixels= new uchar[ image.width() * d ];
 
711
  x_offset= new int[ sample_image.width() ];
 
712
  y_offset= new int[ sample_image.height() ];
 
713
  /*
 
714
    Initialize pixel offsets.
 
715
  */
 
716
// In the following several code 0.5 needs to be added, otherwise the image
 
717
// would be moved by half a pixel to bottom-right, just like
 
718
// with Qt's QImage::scale()
 
719
  for (x=0; x < (long) sample_image.width(); x++)
 
720
  {
 
721
    x_offset[x]=int((x+0.5)*image.width()/sample_image.width());
 
722
  }
 
723
  for (y=0; y < (long) sample_image.height(); y++)
 
724
  {
 
725
    y_offset[y]=int((y+0.5)*image.height()/sample_image.height());
 
726
  }
 
727
  /*
 
728
    Sample each row.
 
729
  */
 
730
  j=(-1);
 
731
  for (y=0; y < (long) sample_image.height(); y++)
 
732
  {
 
733
    q= sample_image.scanLine( y );
 
734
    if (j != y_offset[y] )
 
735
      {
 
736
        /*
 
737
          Read a scan line.
 
738
        */
 
739
        j= y_offset[y];
 
740
        p= image.scanLine( j );
 
741
        (void) memcpy(pixels,p,image.width()*d);
 
742
      }
 
743
    /*
 
744
      Sample each column.
 
745
    */
 
746
    switch( d )
 
747
    {
 
748
    case 1: // 8bit
 
749
      for (x=0; x < (long) sample_image.width(); x++)
 
750
      {
 
751
        *q++=pixels[ x_offset[x] ];
 
752
      }
 
753
      break;
 
754
    case 4: // 32bit
 
755
      for (x=0; x < (long) sample_image.width(); x++)
 
756
      {
 
757
        *(QRgb*)q=((QRgb*)pixels)[ x_offset[x] ];
 
758
        q += d;
 
759
      }
 
760
      break;
 
761
    default:
 
762
      for (x=0; x < (long) sample_image.width(); x++)
 
763
      {
 
764
        memcpy( q, pixels + x_offset[x] * d, d );
 
765
        q += d;
 
766
      }
 
767
      break;
 
768
    }
 
769
  }
 
770
  if( d != 4 ) // != 32bit
 
771
  {
 
772
    sample_image.setNumColors( image.numColors());
 
773
    for( int i = 0; i < image.numColors(); ++i )
 
774
      sample_image.setColor( i, image.color( i ));
 
775
  }
 
776
  delete[] y_offset;
 
777
  delete[] x_offset;
 
778
  delete[] pixels;
 
779
  return sample_image;
 
780
}
 
781
 
 
782
 
 
783
// ImageMagick code end
 
784
 
 
785
 
 
786
// Imlib2/Mosfet code begin
 
787
// ------------------------
 
788
 
 
789
// This code is Imlib2 code, additionally modified by Mosfet, and with few small
 
790
// modifications for Gwenview. The MMX scaling code also belongs to it.
 
791
 
 
792
// The original license texts follow.
 
793
 
 
794
/**
 
795
 * This is the normal smoothscale method, based on Imlib2's smoothscale.
 
796
 *
 
797
 * Originally I took the algorithm used in NetPBM and Qt and added MMX/3dnow
 
798
 * optimizations. It ran in about 1/2 the time as Qt. Then I ported Imlib's
 
799
 * C algorithm and it ran at about the same speed as my MMX optimized one...
 
800
 * Finally I ported Imlib's MMX version and it ran in less than half the
 
801
 * time as my MMX algorithm, (taking only a quarter of the time Qt does).
 
802
 *
 
803
 * Changes include formatting, namespaces and other C++'ings, removal of old
 
804
 * #ifdef'ed code, and removal of unneeded border calculation code.
 
805
 *
 
806
 * Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code
 
807
 * is by Willem Monsuwe <willem@stack.nl>. All other modifications are
 
808
 * (C) Daniel M. Duley.
 
809
 */
 
810
 
 
811
/*
 
812
    Copyright (C) 2004 Daniel M. Duley <dan.duley@verizon.net>
 
813
 
 
814
Redistribution and use in source and binary forms, with or without
 
815
modification, are permitted provided that the following conditions
 
816
are met:
 
817
 
 
818
1. Redistributions of source code must retain the above copyright
 
819
   notice, this list of conditions and the following disclaimer.
 
820
2. Redistributions in binary form must reproduce the above copyright
 
821
   notice, this list of conditions and the following disclaimer in the
 
822
   documentation and/or other materials provided with the distribution.
 
823
 
 
824
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 
825
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
826
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
827
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 
828
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
829
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
830
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
831
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
832
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
833
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
834
 
 
835
*/
 
836
 
 
837
/*
 
838
Copyright (C) 2000 Carsten Haitzler and various contributors (see AUTHORS)
 
839
 
 
840
Permission is hereby granted, free of charge, to any person obtaining a copy
 
841
of this software and associated documentation files (the "Software"), to
 
842
deal in the Software without restriction, including without limitation the
 
843
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 
844
sell copies of the Software, and to permit persons to whom the Software is
 
845
furnished to do so, subject to the following conditions:
 
846
 
 
847
The above copyright notice and this permission notice shall be included in
 
848
all copies of the Software and its Copyright notices. In addition publicly
 
849
documented acknowledgment must be given that this software has been used if no
 
850
source code of this software is made available publicly. This includes
 
851
acknowledgments in either Copyright notices, Manuals, Publicity and Marketing
 
852
documents or any documentation provided with any product containing this
 
853
software. This License does not apply to any software that links to the
 
854
libraries provided by this software (statically or dynamically), but only to
 
855
the software provided.
 
856
 
 
857
Please see the COPYING.PLAIN for a plain-english explanation of this notice
 
858
and it's intent.
 
859
 
 
860
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
861
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
862
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 
863
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
 
864
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
865
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
866
*/
 
867
 
 
868
namespace MImageScale{
 
869
    typedef struct __mimage_scale_info
 
870
    {
 
871
        int *xpoints;
 
872
        unsigned int **ypoints;
 
873
        int *xapoints, *yapoints;
 
874
        int xup_yup;
 
875
    } MImageScaleInfo;
 
876
 
 
877
    unsigned int** mimageCalcYPoints(unsigned int *src, int sw, int sh,
 
878
                                     int dh);
 
879
    int* mimageCalcXPoints(int sw, int dw);
 
880
    int* mimageCalcApoints(int s, int d, int up);
 
881
    MImageScaleInfo* mimageFreeScaleInfo(MImageScaleInfo *isi);
 
882
    MImageScaleInfo *mimageCalcScaleInfo(QImage &img, int sw, int sh,
 
883
                                         int dw, int dh, char aa);
 
884
    void mimageSampleRGBA(MImageScaleInfo *isi, unsigned int *dest, int dxx,
 
885
                          int dyy, int dx, int dy, int dw, int dh, int dow);
 
886
    void mimageScaleAARGBA(MImageScaleInfo *isi, unsigned int *dest, int dxx,
 
887
                           int dyy, int dx, int dy, int dw, int dh, int dow,
 
888
                           int sow);
 
889
    void mimageScaleAARGB(MImageScaleInfo *isi, unsigned int *dest, int dxx,
 
890
                          int dyy, int dx, int dy, int dw, int dh, int dow, int
 
891
                          sow);
 
892
    QImage smoothScale(const QImage& img, int dw, int dh);
 
893
}
 
894
 
 
895
#ifdef HAVE_X86_MMX
 
896
extern "C" {
 
897
    void __mimageScale_mmx_AARGBA(MImageScale::MImageScaleInfo *isi,
 
898
                                  unsigned int *dest, int dxx, int dyy,
 
899
                                  int dx, int dy, int dw, int dh,
 
900
                                  int dow, int sow);
 
901
};
 
902
#endif
 
903
 
 
904
using namespace MImageScale;
 
905
 
 
906
QImage MImageScale::smoothScale(const QImage& image, int dw, int dh)
 
907
{
 
908
    QImage img = image.depth() < 32 ? image.convertDepth( 32 ) : image;
 
909
    int w = img.width();
 
910
    int h = img.height();
 
911
 
 
912
    MImageScaleInfo *scaleinfo =
 
913
        mimageCalcScaleInfo(img, w, h, dw, dh, true);
 
914
    if(!scaleinfo)
 
915
        return QImage();
 
916
 
 
917
    QImage buffer(dw, dh, 32);
 
918
    buffer.setAlphaBuffer(img.hasAlphaBuffer());
 
919
 
 
920
#ifdef HAVE_X86_MMX
 
921
//#warning Using MMX Smoothscale
 
922
    bool haveMMX = KCPUInfo::haveExtension( KCPUInfo::IntelMMX );
 
923
    if(haveMMX){
 
924
        __mimageScale_mmx_AARGBA(scaleinfo, (unsigned int *)buffer.scanLine(0),
 
925
                                 0, 0, 0, 0, dw, dh, dw, w);
 
926
    }
 
927
    else
 
928
#endif
 
929
    {
 
930
        if(img.hasAlphaBuffer())
 
931
            mimageScaleAARGBA(scaleinfo, (unsigned int *)buffer.scanLine(0), 0, 0,
 
932
                              0, 0, dw, dh, dw, w);
 
933
        else
 
934
            mimageScaleAARGB(scaleinfo, (unsigned int *)buffer.scanLine(0), 0, 0,
 
935
                             0, 0, dw, dh, dw, w);
 
936
    }
 
937
    mimageFreeScaleInfo(scaleinfo);
 
938
    return(buffer);
 
939
}
 
940
 
 
941
//
 
942
// Code ported from Imlib...
 
943
//
 
944
 
 
945
// FIXME: replace with mRed, etc... These work on pointers to pixels, not
 
946
// pixel values
 
947
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
 
948
#define A_VAL(p) ((unsigned char *)(p))[0]
 
949
#define R_VAL(p) ((unsigned char *)(p))[1]
 
950
#define G_VAL(p) ((unsigned char *)(p))[2]
 
951
#define B_VAL(p) ((unsigned char *)(p))[3]
 
952
#elif Q_BYTE_ORDER == Q_LITTLE_ENDIAN
 
953
#define A_VAL(p) ((unsigned char *)(p))[3]
 
954
#define R_VAL(p) ((unsigned char *)(p))[2]
 
955
#define G_VAL(p) ((unsigned char *)(p))[1]
 
956
#define B_VAL(p) ((unsigned char *)(p))[0]
 
957
#endif
 
958
 
 
959
#define INV_XAP                   (256 - xapoints[x])
 
960
#define XAP                       (xapoints[x])
 
961
#define INV_YAP                   (256 - yapoints[dyy + y])
 
962
#define YAP                       (yapoints[dyy + y])
 
963
 
 
964
unsigned int** MImageScale::mimageCalcYPoints(unsigned int *src,
 
965
                                              int sw, int sh, int dh)
 
966
{
 
967
    unsigned int **p;
 
968
    int i, j = 0;
 
969
    int val, inc, rv = 0;
 
970
 
 
971
    if(dh < 0){
 
972
        dh = -dh;
 
973
        rv = 1;
 
974
    }
 
975
    p = new unsigned int* [dh+1];
 
976
 
 
977
    val = 0;
 
978
    inc = (sh << 16) / dh;
 
979
    for(i = 0; i < dh; i++){
 
980
        p[j++] = src + ((val >> 16) * sw);
 
981
        val += inc;
 
982
    }
 
983
    if(rv){
 
984
        for(i = dh / 2; --i >= 0; ){
 
985
            unsigned int *tmp = p[i];
 
986
            p[i] = p[dh - i - 1];
 
987
            p[dh - i - 1] = tmp;
 
988
        }
 
989
    }
 
990
    return(p);
 
991
}
 
992
 
 
993
int* MImageScale::mimageCalcXPoints(int sw, int dw)
 
994
{
 
995
    int *p, i, j = 0;
 
996
    int val, inc, rv = 0;
 
997
 
 
998
    if(dw < 0){
 
999
        dw = -dw;
 
1000
        rv = 1;
 
1001
    }
 
1002
    p = new int[dw+1];
 
1003
 
 
1004
    val = 0;
 
1005
    inc = (sw << 16) / dw;
 
1006
    for(i = 0; i < dw; i++){
 
1007
        p[j++] = (val >> 16);
 
1008
        val += inc;
 
1009
    }
 
1010
 
 
1011
    if(rv){
 
1012
        for(i = dw / 2; --i >= 0; ){
 
1013
            int tmp = p[i];
 
1014
            p[i] = p[dw - i - 1];
 
1015
            p[dw - i - 1] = tmp;
 
1016
        }
 
1017
    }
 
1018
   return(p);
 
1019
}
 
1020
 
 
1021
int* MImageScale::mimageCalcApoints(int s, int d, int up)
 
1022
{
 
1023
    int *p, i, j = 0, rv = 0;
 
1024
 
 
1025
    if(d < 0){
 
1026
        rv = 1;
 
1027
        d = -d;
 
1028
    }
 
1029
    p = new int[d];
 
1030
 
 
1031
    /* scaling up */
 
1032
    if(up){
 
1033
        int val, inc;
 
1034
 
 
1035
        val = 0;
 
1036
        inc = (s << 16) / d;
 
1037
        for(i = 0; i < d; i++){
 
1038
            p[j++] = (val >> 8) - ((val >> 8) & 0xffffff00);
 
1039
            if((val >> 16) >= (s - 1))
 
1040
                p[j - 1] = 0;
 
1041
            val += inc;
 
1042
        }
 
1043
    }
 
1044
    /* scaling down */
 
1045
    else{
 
1046
        int val, inc, ap, Cp;
 
1047
        val = 0;
 
1048
        inc = (s << 16) / d;
 
1049
        Cp = ((d << 14) / s) + 1;
 
1050
        for(i = 0; i < d; i++){
 
1051
            ap = ((0x100 - ((val >> 8) & 0xff)) * Cp) >> 8;
 
1052
            p[j] = ap | (Cp << 16);
 
1053
            j++;
 
1054
            val += inc;
 
1055
        }
 
1056
    }
 
1057
    if(rv){
 
1058
        int tmp;
 
1059
        for(i = d / 2; --i >= 0; ){
 
1060
            tmp = p[i];
 
1061
            p[i] = p[d - i - 1];
 
1062
            p[d - i - 1] = tmp;
 
1063
        }
 
1064
    }
 
1065
    return(p);
 
1066
}
 
1067
 
 
1068
MImageScaleInfo* MImageScale::mimageFreeScaleInfo(MImageScaleInfo *isi)
 
1069
{
 
1070
    if(isi){
 
1071
        delete[] isi->xpoints;
 
1072
        delete[] isi->ypoints;
 
1073
        delete[] isi->xapoints;
 
1074
        delete[] isi->yapoints;
 
1075
        delete isi;
 
1076
    }
 
1077
    return(NULL);
 
1078
}
 
1079
 
 
1080
MImageScaleInfo* MImageScale::mimageCalcScaleInfo(QImage &img, int sw, int sh,
 
1081
                                                  int dw, int dh, char aa)
 
1082
{
 
1083
    MImageScaleInfo *isi;
 
1084
    int scw, sch;
 
1085
 
 
1086
    scw = dw * img.width() / sw;
 
1087
    sch = dh * img.height() / sh;
 
1088
 
 
1089
    isi = new MImageScaleInfo;
 
1090
    if(!isi)
 
1091
        return(NULL);
 
1092
    memset(isi, 0, sizeof(MImageScaleInfo));
 
1093
 
 
1094
    isi->xup_yup = (abs(dw) >= sw) + ((abs(dh) >= sh) << 1);
 
1095
 
 
1096
    isi->xpoints = mimageCalcXPoints(img.width(), scw);
 
1097
    if(!isi->xpoints)
 
1098
        return(mimageFreeScaleInfo(isi));
 
1099
    isi->ypoints = mimageCalcYPoints((unsigned int *)img.scanLine(0),
 
1100
                                     img.width(), img.height(), sch);
 
1101
    if (!isi->ypoints)
 
1102
        return(mimageFreeScaleInfo(isi));
 
1103
    if(aa){
 
1104
        isi->xapoints = mimageCalcApoints(img.width(), scw, isi->xup_yup & 1);
 
1105
        if(!isi->xapoints)
 
1106
            return(mimageFreeScaleInfo(isi));
 
1107
        isi->yapoints = mimageCalcApoints(img.height(), sch, isi->xup_yup & 2);
 
1108
        if(!isi->yapoints)
 
1109
            return(mimageFreeScaleInfo(isi));
 
1110
    }
 
1111
    return(isi);
 
1112
}
 
1113
 
 
1114
/* scale by pixel sampling only */
 
1115
void MImageScale::mimageSampleRGBA(MImageScaleInfo *isi, unsigned int *dest,
 
1116
                                   int dxx, int dyy, int dx, int dy, int dw,
 
1117
                                   int dh, int dow)
 
1118
{
 
1119
    unsigned int *sptr, *dptr;
 
1120
    int x, y, end;
 
1121
    unsigned int **ypoints = isi->ypoints;
 
1122
    int *xpoints = isi->xpoints;
 
1123
 
 
1124
    /* whats the last pixel ont he line so we stop there */
 
1125
    end = dxx + dw;
 
1126
    /* go through every scanline in the output buffer */
 
1127
    for(y = 0; y < dh; y++){
 
1128
        /* get the pointer to the start of the destination scanline */
 
1129
        dptr = dest + dx + ((y + dy) * dow);
 
1130
        /* calculate the source line we'll scan from */
 
1131
        sptr = ypoints[dyy + y];
 
1132
        /* go thru the scanline and copy across */
 
1133
        for(x = dxx; x < end; x++)
 
1134
            *dptr++ = sptr[xpoints[x]];
 
1135
    }
 
1136
}
 
1137
 
 
1138
/* FIXME: NEED to optimise ScaleAARGBA - currently its "ok" but needs work*/
 
1139
 
 
1140
/* scale by area sampling */
 
1141
void MImageScale::mimageScaleAARGBA(MImageScaleInfo *isi, unsigned int *dest,
 
1142
                                    int dxx, int dyy, int dx, int dy, int dw,
 
1143
                                    int dh, int dow, int sow)
 
1144
{
 
1145
    unsigned int *sptr, *dptr;
 
1146
    int x, y, end;
 
1147
    unsigned int **ypoints = isi->ypoints;
 
1148
    int *xpoints = isi->xpoints;
 
1149
    int *xapoints = isi->xapoints;
 
1150
    int *yapoints = isi->yapoints;
 
1151
 
 
1152
    end = dxx + dw;
 
1153
    /* scaling up both ways */
 
1154
    if(isi->xup_yup == 3){
 
1155
        /* go through every scanline in the output buffer */
 
1156
        for(y = 0; y < dh; y++){
 
1157
            /* calculate the source line we'll scan from */
 
1158
            dptr = dest + dx + ((y + dy) * dow);
 
1159
            sptr = ypoints[dyy + y];
 
1160
            if(YAP > 0){
 
1161
                for(x = dxx; x < end; x++){
 
1162
                    int r, g, b, a;
 
1163
                    int rr, gg, bb, aa;
 
1164
                    unsigned int *pix;
 
1165
 
 
1166
                    if(XAP > 0){
 
1167
                        pix = ypoints[dyy + y] + xpoints[x];
 
1168
                        r = R_VAL(pix) * INV_XAP;
 
1169
                        g = G_VAL(pix) * INV_XAP;
 
1170
                        b = B_VAL(pix) * INV_XAP;
 
1171
                        a = A_VAL(pix) * INV_XAP;
 
1172
                        pix++;
 
1173
                        r += R_VAL(pix) * XAP;
 
1174
                        g += G_VAL(pix) * XAP;
 
1175
                        b += B_VAL(pix) * XAP;
 
1176
                        a += A_VAL(pix) * XAP;
 
1177
                        pix += sow;
 
1178
                        rr = R_VAL(pix) * XAP;
 
1179
                        gg = G_VAL(pix) * XAP;
 
1180
                        bb = B_VAL(pix) * XAP;
 
1181
                        aa = A_VAL(pix) * XAP;
 
1182
                        pix--;
 
1183
                        rr += R_VAL(pix) * INV_XAP;
 
1184
                        gg += G_VAL(pix) * INV_XAP;
 
1185
                        bb += B_VAL(pix) * INV_XAP;
 
1186
                        aa += A_VAL(pix) * INV_XAP;
 
1187
                        r = ((rr * YAP) + (r * INV_YAP)) >> 16;
 
1188
                        g = ((gg * YAP) + (g * INV_YAP)) >> 16;
 
1189
                        b = ((bb * YAP) + (b * INV_YAP)) >> 16;
 
1190
                        a = ((aa * YAP) + (a * INV_YAP)) >> 16;
 
1191
                        *dptr++ = qRgba(r, g, b, a);
 
1192
                    }
 
1193
                    else{
 
1194
                        pix = ypoints[dyy + y] + xpoints[x];
 
1195
                        r = R_VAL(pix) * INV_YAP;
 
1196
                        g = G_VAL(pix) * INV_YAP;
 
1197
                        b = B_VAL(pix) * INV_YAP;
 
1198
                        a = A_VAL(pix) * INV_YAP;
 
1199
                        pix += sow;
 
1200
                        r += R_VAL(pix) * YAP;
 
1201
                        g += G_VAL(pix) * YAP;
 
1202
                        b += B_VAL(pix) * YAP;
 
1203
                        a += A_VAL(pix) * YAP;
 
1204
                        r >>= 8;
 
1205
                        g >>= 8;
 
1206
                        b >>= 8;
 
1207
                        a >>= 8;
 
1208
                        *dptr++ = qRgba(r, g, b, a);
 
1209
                    }
 
1210
                }
 
1211
            }
 
1212
            else{
 
1213
                for(x = dxx; x < end; x++){
 
1214
                    int r, g, b, a;
 
1215
                    unsigned int *pix;
 
1216
 
 
1217
                    if(XAP > 0){
 
1218
                        pix = ypoints[dyy + y] + xpoints[x];
 
1219
                        r = R_VAL(pix) * INV_XAP;
 
1220
                        g = G_VAL(pix) * INV_XAP;
 
1221
                        b = B_VAL(pix) * INV_XAP;
 
1222
                        a = A_VAL(pix) * INV_XAP;
 
1223
                        pix++;
 
1224
                        r += R_VAL(pix) * XAP;
 
1225
                        g += G_VAL(pix) * XAP;
 
1226
                        b += B_VAL(pix) * XAP;
 
1227
                        a += A_VAL(pix) * XAP;
 
1228
                        r >>= 8;
 
1229
                        g >>= 8;
 
1230
                        b >>= 8;
 
1231
                        a >>= 8;
 
1232
                        *dptr++ = qRgba(r, g, b, a);
 
1233
                    }
 
1234
                    else
 
1235
                        *dptr++ = sptr[xpoints[x] ];
 
1236
                }
 
1237
            }
 
1238
        }
 
1239
    }
 
1240
    /* if we're scaling down vertically */
 
1241
    else if(isi->xup_yup == 1){
 
1242
        /*\ 'Correct' version, with math units prepared for MMXification \*/
 
1243
        int Cy, j;
 
1244
        unsigned int *pix;
 
1245
        int r, g, b, a, rr, gg, bb, aa;
 
1246
        int yap;
 
1247
                 
 
1248
        /* go through every scanline in the output buffer */
 
1249
        for(y = 0; y < dh; y++){
 
1250
            Cy = YAP >> 16;
 
1251
            yap = YAP & 0xffff;
 
1252
 
 
1253
            dptr = dest + dx + ((y + dy) * dow);
 
1254
            for(x = dxx; x < end; x++){
 
1255
                pix = ypoints[dyy + y] + xpoints[x];
 
1256
                r = (R_VAL(pix) * yap) >> 10;
 
1257
                g = (G_VAL(pix) * yap) >> 10;
 
1258
                b = (B_VAL(pix) * yap) >> 10;
 
1259
                a = (A_VAL(pix) * yap) >> 10;
 
1260
                for(j = (1 << 14) - yap; j > Cy; j -= Cy){
 
1261
                    pix += sow;
 
1262
                    r += (R_VAL(pix) * Cy) >> 10;
 
1263
                    g += (G_VAL(pix) * Cy) >> 10;
 
1264
                    b += (B_VAL(pix) * Cy) >> 10;
 
1265
                    a += (A_VAL(pix) * Cy) >> 10;
 
1266
                }
 
1267
                if(j > 0){
 
1268
                    pix += sow;
 
1269
                    r += (R_VAL(pix) * j) >> 10;
 
1270
                    g += (G_VAL(pix) * j) >> 10;
 
1271
                    b += (B_VAL(pix) * j) >> 10;
 
1272
                    a += (A_VAL(pix) * j) >> 10;
 
1273
                }
 
1274
                if(XAP > 0){
 
1275
                    pix = ypoints[dyy + y] + xpoints[x] + 1;
 
1276
                    rr = (R_VAL(pix) * yap) >> 10;
 
1277
                    gg = (G_VAL(pix) * yap) >> 10;
 
1278
                    bb = (B_VAL(pix) * yap) >> 10;
 
1279
                    aa = (A_VAL(pix) * yap) >> 10;
 
1280
                    for(j = (1 << 14) - yap; j > Cy; j -= Cy){
 
1281
                        pix += sow;
 
1282
                        rr += (R_VAL(pix) * Cy) >> 10;
 
1283
                        gg += (G_VAL(pix) * Cy) >> 10;
 
1284
                        bb += (B_VAL(pix) * Cy) >> 10;
 
1285
                        aa += (A_VAL(pix) * Cy) >> 10;
 
1286
                    }
 
1287
                    if(j > 0){
 
1288
                        pix += sow;
 
1289
                        rr += (R_VAL(pix) * j) >> 10;
 
1290
                        gg += (G_VAL(pix) * j) >> 10;
 
1291
                        bb += (B_VAL(pix) * j) >> 10;
 
1292
                        aa += (A_VAL(pix) * j) >> 10;
 
1293
                    }
 
1294
                    r = r * INV_XAP;
 
1295
                    g = g * INV_XAP;
 
1296
                    b = b * INV_XAP;
 
1297
                    a = a * INV_XAP;
 
1298
                    r = (r + ((rr * XAP))) >> 12;
 
1299
                    g = (g + ((gg * XAP))) >> 12;
 
1300
                    b = (b + ((bb * XAP))) >> 12;
 
1301
                    a = (a + ((aa * XAP))) >> 12;
 
1302
                }
 
1303
                else{
 
1304
                    r >>= 4;
 
1305
                    g >>= 4;
 
1306
                    b >>= 4;
 
1307
                    a >>= 4;
 
1308
                }
 
1309
                *dptr = qRgba(r, g, b, a);
 
1310
                dptr++;
 
1311
            }
 
1312
        }
 
1313
    }
 
1314
    /* if we're scaling down horizontally */
 
1315
    else if(isi->xup_yup == 2){
 
1316
        /*\ 'Correct' version, with math units prepared for MMXification \*/
 
1317
        int Cx, j;
 
1318
        unsigned int *pix;
 
1319
        int r, g, b, a, rr, gg, bb, aa;
 
1320
        int xap;
 
1321
 
 
1322
        /* go through every scanline in the output buffer */
 
1323
        for(y = 0; y < dh; y++){
 
1324
            dptr = dest + dx + ((y + dy) * dow);
 
1325
            for(x = dxx; x < end; x++){
 
1326
                Cx = XAP >> 16;
 
1327
                xap = XAP & 0xffff;
 
1328
 
 
1329
                pix = ypoints[dyy + y] + xpoints[x];
 
1330
                r = (R_VAL(pix) * xap) >> 10;
 
1331
                g = (G_VAL(pix) * xap) >> 10;
 
1332
                b = (B_VAL(pix) * xap) >> 10;
 
1333
                a = (A_VAL(pix) * xap) >> 10;
 
1334
                for(j = (1 << 14) - xap; j > Cx; j -= Cx){
 
1335
                    pix++;
 
1336
                    r += (R_VAL(pix) * Cx) >> 10;
 
1337
                    g += (G_VAL(pix) * Cx) >> 10;
 
1338
                    b += (B_VAL(pix) * Cx) >> 10;
 
1339
                    a += (A_VAL(pix) * Cx) >> 10;
 
1340
                }
 
1341
                if(j > 0){
 
1342
                    pix++;
 
1343
                    r += (R_VAL(pix) * j) >> 10;
 
1344
                    g += (G_VAL(pix) * j) >> 10;
 
1345
                    b += (B_VAL(pix) * j) >> 10;
 
1346
                    a += (A_VAL(pix) * j) >> 10;
 
1347
                }
 
1348
                if(YAP > 0){
 
1349
                    pix = ypoints[dyy + y] + xpoints[x] + sow;
 
1350
                    rr = (R_VAL(pix) * xap) >> 10;
 
1351
                    gg = (G_VAL(pix) * xap) >> 10;
 
1352
                    bb = (B_VAL(pix) * xap) >> 10;
 
1353
                    aa = (A_VAL(pix) * xap) >> 10;
 
1354
                    for(j = (1 << 14) - xap; j > Cx; j -= Cx){
 
1355
                        pix++;
 
1356
                        rr += (R_VAL(pix) * Cx) >> 10;
 
1357
                        gg += (G_VAL(pix) * Cx) >> 10;
 
1358
                        bb += (B_VAL(pix) * Cx) >> 10;
 
1359
                        aa += (A_VAL(pix) * Cx) >> 10;
 
1360
                    }
 
1361
                    if(j > 0){
 
1362
                        pix++;
 
1363
                        rr += (R_VAL(pix) * j) >> 10;
 
1364
                        gg += (G_VAL(pix) * j) >> 10;
 
1365
                        bb += (B_VAL(pix) * j) >> 10;
 
1366
                        aa += (A_VAL(pix) * j) >> 10;
 
1367
                    }
 
1368
                    r = r * INV_YAP;
 
1369
                    g = g * INV_YAP;
 
1370
                    b = b * INV_YAP;
 
1371
                    a = a * INV_YAP;
 
1372
                    r = (r + ((rr * YAP))) >> 12;
 
1373
                    g = (g + ((gg * YAP))) >> 12;
 
1374
                    b = (b + ((bb * YAP))) >> 12;
 
1375
                    a = (a + ((aa * YAP))) >> 12;
 
1376
                }
 
1377
                else{
 
1378
                    r >>= 4;
 
1379
                    g >>= 4;
 
1380
                    b >>= 4;
 
1381
                    a >>= 4;
 
1382
                }
 
1383
                *dptr = qRgba(r, g, b, a);
 
1384
                dptr++;
 
1385
            }
 
1386
        }
 
1387
    }
 
1388
    /* if we're scaling down horizontally & vertically */
 
1389
    else{
 
1390
        /*\ 'Correct' version, with math units prepared for MMXification:
 
1391
         |*|  The operation 'b = (b * c) >> 16' translates to pmulhw,
 
1392
         |*|  so the operation 'b = (b * c) >> d' would translate to
 
1393
         |*|  psllw (16 - d), %mmb; pmulh %mmc, %mmb
 
1394
         \*/
 
1395
        int Cx, Cy, i, j;
 
1396
        unsigned int *pix;
 
1397
        int a, r, g, b, ax, rx, gx, bx;
 
1398
        int xap, yap;
 
1399
 
 
1400
        for(y = 0; y < dh; y++){
 
1401
            Cy = YAP >> 16;
 
1402
            yap = YAP & 0xffff;
 
1403
 
 
1404
            dptr = dest + dx + ((y + dy) * dow);
 
1405
            for(x = dxx; x < end; x++){
 
1406
                Cx = XAP >> 16;
 
1407
                xap = XAP & 0xffff;
 
1408
 
 
1409
                sptr = ypoints[dyy + y] + xpoints[x];
 
1410
                pix = sptr;
 
1411
                sptr += sow;
 
1412
                rx = (R_VAL(pix) * xap) >> 9;
 
1413
                gx = (G_VAL(pix) * xap) >> 9;
 
1414
                bx = (B_VAL(pix) * xap) >> 9;
 
1415
                ax = (A_VAL(pix) * xap) >> 9;
 
1416
                pix++;
 
1417
                for(i = (1 << 14) - xap; i > Cx; i -= Cx){
 
1418
                    rx += (R_VAL(pix) * Cx) >> 9;
 
1419
                    gx += (G_VAL(pix) * Cx) >> 9;
 
1420
                    bx += (B_VAL(pix) * Cx) >> 9;
 
1421
                    ax += (A_VAL(pix) * Cx) >> 9;
 
1422
                    pix++;
 
1423
                }
 
1424
                if(i > 0){
 
1425
                    rx += (R_VAL(pix) * i) >> 9;
 
1426
                    gx += (G_VAL(pix) * i) >> 9;
 
1427
                    bx += (B_VAL(pix) * i) >> 9;
 
1428
                    ax += (A_VAL(pix) * i) >> 9;
 
1429
                }
 
1430
 
 
1431
                r = (rx * yap) >> 14;
 
1432
                g = (gx * yap) >> 14;
 
1433
                b = (bx * yap) >> 14;
 
1434
                a = (ax * yap) >> 14;
 
1435
 
 
1436
                for(j = (1 << 14) - yap; j > Cy; j -= Cy){
 
1437
                    pix = sptr;
 
1438
                    sptr += sow;
 
1439
                    rx = (R_VAL(pix) * xap) >> 9;
 
1440
                    gx = (G_VAL(pix) * xap) >> 9;
 
1441
                    bx = (B_VAL(pix) * xap) >> 9;
 
1442
                    ax = (A_VAL(pix) * xap) >> 9;
 
1443
                    pix++;
 
1444
                    for(i = (1 << 14) - xap; i > Cx; i -= Cx){
 
1445
                        rx += (R_VAL(pix) * Cx) >> 9;
 
1446
                        gx += (G_VAL(pix) * Cx) >> 9;
 
1447
                        bx += (B_VAL(pix) * Cx) >> 9;
 
1448
                        ax += (A_VAL(pix) * Cx) >> 9;
 
1449
                        pix++;
 
1450
                    }
 
1451
                    if(i > 0){
 
1452
                        rx += (R_VAL(pix) * i) >> 9;
 
1453
                        gx += (G_VAL(pix) * i) >> 9;
 
1454
                        bx += (B_VAL(pix) * i) >> 9;
 
1455
                        ax += (A_VAL(pix) * i) >> 9;
 
1456
                    }
 
1457
 
 
1458
                    r += (rx * Cy) >> 14;
 
1459
                    g += (gx * Cy) >> 14;
 
1460
                    b += (bx * Cy) >> 14;
 
1461
                    a += (ax * Cy) >> 14;
 
1462
                }
 
1463
                if(j > 0){
 
1464
                    pix = sptr;
 
1465
                    sptr += sow;
 
1466
                    rx = (R_VAL(pix) * xap) >> 9;
 
1467
                    gx = (G_VAL(pix) * xap) >> 9;
 
1468
                    bx = (B_VAL(pix) * xap) >> 9;
 
1469
                    ax = (A_VAL(pix) * xap) >> 9;
 
1470
                    pix++;
 
1471
                    for(i = (1 << 14) - xap; i > Cx; i -= Cx){
 
1472
                        rx += (R_VAL(pix) * Cx) >> 9;
 
1473
                        gx += (G_VAL(pix) * Cx) >> 9;
 
1474
                        bx += (B_VAL(pix) * Cx) >> 9;
 
1475
                        ax += (A_VAL(pix) * Cx) >> 9;
 
1476
                        pix++;
 
1477
                    }
 
1478
                    if(i > 0){
 
1479
                        rx += (R_VAL(pix) * i) >> 9;
 
1480
                        gx += (G_VAL(pix) * i) >> 9;
 
1481
                        bx += (B_VAL(pix) * i) >> 9;
 
1482
                        ax += (A_VAL(pix) * i) >> 9;
 
1483
                    }
 
1484
 
 
1485
                    r += (rx * j) >> 14;
 
1486
                    g += (gx * j) >> 14;
 
1487
                    b += (bx * j) >> 14;
 
1488
                    a += (ax * j) >> 14;
 
1489
                }
 
1490
 
 
1491
                R_VAL(dptr) = r >> 5;
 
1492
                G_VAL(dptr) = g >> 5;
 
1493
                B_VAL(dptr) = b >> 5;
 
1494
                A_VAL(dptr) = a >> 5;
 
1495
                dptr++;
 
1496
            }
 
1497
        }
 
1498
    }
 
1499
}
 
1500
 
 
1501
/* scale by area sampling - IGNORE the ALPHA byte*/
 
1502
void MImageScale::mimageScaleAARGB(MImageScaleInfo *isi, unsigned int *dest,
 
1503
                                   int dxx, int dyy, int dx, int dy, int dw,
 
1504
                                   int dh, int dow, int sow)
 
1505
{
 
1506
    unsigned int *sptr, *dptr;
 
1507
    int x, y, end;
 
1508
    unsigned int **ypoints = isi->ypoints;
 
1509
    int *xpoints = isi->xpoints;
 
1510
    int *xapoints = isi->xapoints;
 
1511
    int *yapoints = isi->yapoints;
 
1512
 
 
1513
    end = dxx + dw;
 
1514
    /* scaling up both ways */
 
1515
    if(isi->xup_yup == 3){
 
1516
        /* go through every scanline in the output buffer */
 
1517
        for(y = 0; y < dh; y++){
 
1518
            /* calculate the source line we'll scan from */
 
1519
            dptr = dest + dx + ((y + dy) * dow);
 
1520
            sptr = ypoints[dyy + y];
 
1521
            if(YAP > 0){
 
1522
                for(x = dxx; x < end; x++){
 
1523
                    int r = 0, g = 0, b = 0;
 
1524
                    int rr = 0, gg = 0, bb = 0;
 
1525
                    unsigned int *pix;
 
1526
 
 
1527
                    if(XAP > 0){
 
1528
                        pix = ypoints[dyy + y] + xpoints[x];
 
1529
                        r = R_VAL(pix) * INV_XAP;
 
1530
                        g = G_VAL(pix) * INV_XAP;
 
1531
                        b = B_VAL(pix) * INV_XAP;
 
1532
                        pix++;
 
1533
                        r += R_VAL(pix) * XAP;
 
1534
                        g += G_VAL(pix) * XAP;
 
1535
                        b += B_VAL(pix) * XAP;
 
1536
                        pix += sow;
 
1537
                        rr = R_VAL(pix) * XAP;
 
1538
                        gg = G_VAL(pix) * XAP;
 
1539
                        bb = B_VAL(pix) * XAP;
 
1540
                        pix --;
 
1541
                        rr += R_VAL(pix) * INV_XAP;
 
1542
                        gg += G_VAL(pix) * INV_XAP;
 
1543
                        bb += B_VAL(pix) * INV_XAP;
 
1544
                        r = ((rr * YAP) + (r * INV_YAP)) >> 16;
 
1545
                        g = ((gg * YAP) + (g * INV_YAP)) >> 16;
 
1546
                        b = ((bb * YAP) + (b * INV_YAP)) >> 16;
 
1547
                        *dptr++ = qRgba(r, g, b, 0xff);
 
1548
                    }
 
1549
                    else{
 
1550
                        pix = ypoints[dyy + y] + xpoints[x];
 
1551
                        r = R_VAL(pix) * INV_YAP;
 
1552
                        g = G_VAL(pix) * INV_YAP;
 
1553
                        b = B_VAL(pix) * INV_YAP;
 
1554
                        pix += sow;
 
1555
                        r += R_VAL(pix) * YAP;
 
1556
                        g += G_VAL(pix) * YAP;
 
1557
                        b += B_VAL(pix) * YAP;
 
1558
                        r >>= 8;
 
1559
                        g >>= 8;
 
1560
                        b >>= 8;
 
1561
                        *dptr++ = qRgba(r, g, b, 0xff);
 
1562
                    }
 
1563
                }
 
1564
            }
 
1565
            else{
 
1566
                for(x = dxx; x < end; x++){
 
1567
                    int r = 0, g = 0, b = 0;
 
1568
                    unsigned int *pix;
 
1569
 
 
1570
                    if(XAP > 0){
 
1571
                        pix = ypoints[dyy + y] + xpoints[x];
 
1572
                        r = R_VAL(pix) * INV_XAP;
 
1573
                        g = G_VAL(pix) * INV_XAP;
 
1574
                        b = B_VAL(pix) * INV_XAP;
 
1575
                        pix++;
 
1576
                        r += R_VAL(pix) * XAP;
 
1577
                        g += G_VAL(pix) * XAP;
 
1578
                        b += B_VAL(pix) * XAP;
 
1579
                        r >>= 8;
 
1580
                        g >>= 8;
 
1581
                        b >>= 8;
 
1582
                        *dptr++ = qRgba(r, g, b, 0xff);
 
1583
                    }
 
1584
                    else
 
1585
                        *dptr++ = sptr[xpoints[x] ];
 
1586
                }
 
1587
            }
 
1588
        }
 
1589
    }
 
1590
    /* if we're scaling down vertically */
 
1591
    else if(isi->xup_yup == 1){
 
1592
        /*\ 'Correct' version, with math units prepared for MMXification \*/
 
1593
        int Cy, j;
 
1594
        unsigned int *pix;
 
1595
        int r, g, b, rr, gg, bb;
 
1596
        int yap;
 
1597
 
 
1598
        /* go through every scanline in the output buffer */
 
1599
        for(y = 0; y < dh; y++){
 
1600
            Cy = YAP >> 16;
 
1601
            yap = YAP & 0xffff;
 
1602
 
 
1603
            dptr = dest + dx + ((y + dy) * dow);
 
1604
            for(x = dxx; x < end; x++){
 
1605
                pix = ypoints[dyy + y] + xpoints[x];
 
1606
                r = (R_VAL(pix) * yap) >> 10;
 
1607
                g = (G_VAL(pix) * yap) >> 10;
 
1608
                b = (B_VAL(pix) * yap) >> 10;
 
1609
                pix += sow;
 
1610
                for(j = (1 << 14) - yap; j > Cy; j -= Cy){
 
1611
                    r += (R_VAL(pix) * Cy) >> 10;
 
1612
                    g += (G_VAL(pix) * Cy) >> 10;
 
1613
                    b += (B_VAL(pix) * Cy) >> 10;
 
1614
                    pix += sow;
 
1615
                }
 
1616
                if(j > 0){
 
1617
                    r += (R_VAL(pix) * j) >> 10;
 
1618
                    g += (G_VAL(pix) * j) >> 10;
 
1619
                    b += (B_VAL(pix) * j) >> 10;
 
1620
                }
 
1621
                if(XAP > 0){
 
1622
                    pix = ypoints[dyy + y] + xpoints[x] + 1;
 
1623
                    rr = (R_VAL(pix) * yap) >> 10;
 
1624
                    gg = (G_VAL(pix) * yap) >> 10;
 
1625
                    bb = (B_VAL(pix) * yap) >> 10;
 
1626
                    pix += sow;
 
1627
                    for(j = (1 << 14) - yap; j > Cy; j -= Cy){
 
1628
                        rr += (R_VAL(pix) * Cy) >> 10;
 
1629
                        gg += (G_VAL(pix) * Cy) >> 10;
 
1630
                        bb += (B_VAL(pix) * Cy) >> 10;
 
1631
                        pix += sow;
 
1632
                    }
 
1633
                    if(j > 0){
 
1634
                        rr += (R_VAL(pix) * j) >> 10;
 
1635
                        gg += (G_VAL(pix) * j) >> 10;
 
1636
                        bb += (B_VAL(pix) * j) >> 10;
 
1637
                    }
 
1638
                    r = r * INV_XAP;
 
1639
                    g = g * INV_XAP;
 
1640
                    b = b * INV_XAP;
 
1641
                    r = (r + ((rr * XAP))) >> 12;
 
1642
                    g = (g + ((gg * XAP))) >> 12;
 
1643
                    b = (b + ((bb * XAP))) >> 12;
 
1644
                }
 
1645
                else{
 
1646
                    r >>= 4;
 
1647
                    g >>= 4;
 
1648
                    b >>= 4;
 
1649
                }
 
1650
                *dptr = qRgba(r, g, b, 0xff);
 
1651
                dptr++;
 
1652
            }
 
1653
        }
 
1654
    }
 
1655
    /* if we're scaling down horizontally */
 
1656
    else if(isi->xup_yup == 2){
 
1657
        /*\ 'Correct' version, with math units prepared for MMXification \*/
 
1658
        int Cx, j;
 
1659
        unsigned int *pix;
 
1660
        int r, g, b, rr, gg, bb;
 
1661
        int xap;
 
1662
 
 
1663
        /* go through every scanline in the output buffer */
 
1664
        for(y = 0; y < dh; y++){
 
1665
            dptr = dest + dx + ((y + dy) * dow);
 
1666
            for(x = dxx; x < end; x++){
 
1667
                Cx = XAP >> 16;
 
1668
                xap = XAP & 0xffff;
 
1669
 
 
1670
                pix = ypoints[dyy + y] + xpoints[x];
 
1671
                r = (R_VAL(pix) * xap) >> 10;
 
1672
                g = (G_VAL(pix) * xap) >> 10;
 
1673
                b = (B_VAL(pix) * xap) >> 10;
 
1674
                pix++;
 
1675
                for(j = (1 << 14) - xap; j > Cx; j -= Cx){
 
1676
                    r += (R_VAL(pix) * Cx) >> 10;
 
1677
                    g += (G_VAL(pix) * Cx) >> 10;
 
1678
                    b += (B_VAL(pix) * Cx) >> 10;
 
1679
                    pix++;
 
1680
                }
 
1681
                if(j > 0){
 
1682
                    r += (R_VAL(pix) * j) >> 10;
 
1683
                    g += (G_VAL(pix) * j) >> 10;
 
1684
                    b += (B_VAL(pix) * j) >> 10;
 
1685
                }
 
1686
                if(YAP > 0){
 
1687
                    pix = ypoints[dyy + y] + xpoints[x] + sow;
 
1688
                    rr = (R_VAL(pix) * xap) >> 10;
 
1689
                    gg = (G_VAL(pix) * xap) >> 10;
 
1690
                    bb = (B_VAL(pix) * xap) >> 10;
 
1691
                    pix++;
 
1692
                    for(j = (1 << 14) - xap; j > Cx; j -= Cx){
 
1693
                        rr += (R_VAL(pix) * Cx) >> 10;
 
1694
                        gg += (G_VAL(pix) * Cx) >> 10;
 
1695
                        bb += (B_VAL(pix) * Cx) >> 10;
 
1696
                        pix++;
 
1697
                    }
 
1698
                    if(j > 0){
 
1699
                        rr += (R_VAL(pix) * j) >> 10;
 
1700
                        gg += (G_VAL(pix) * j) >> 10;
 
1701
                        bb += (B_VAL(pix) * j) >> 10;
 
1702
                    }
 
1703
                    r = r * INV_YAP;
 
1704
                    g = g * INV_YAP;
 
1705
                    b = b * INV_YAP;
 
1706
                    r = (r + ((rr * YAP))) >> 12;
 
1707
                    g = (g + ((gg * YAP))) >> 12;
 
1708
                    b = (b + ((bb * YAP))) >> 12;
 
1709
                }
 
1710
                else{
 
1711
                    r >>= 4;
 
1712
                    g >>= 4;
 
1713
                    b >>= 4;
 
1714
                }
 
1715
                *dptr = qRgba(r, g, b, 0xff);
 
1716
                dptr++;
 
1717
            }
 
1718
        }
 
1719
    }
 
1720
    /* fully optimized (i think) - onyl change of algorithm can help */
 
1721
    /* if we're scaling down horizontally & vertically */
 
1722
    else{
 
1723
        /*\ 'Correct' version, with math units prepared for MMXification \*/
 
1724
        int Cx, Cy, i, j;
 
1725
        unsigned int *pix;
 
1726
        int r, g, b, rx, gx, bx;
 
1727
        int xap, yap;
 
1728
 
 
1729
        for(y = 0; y < dh; y++){
 
1730
            Cy = YAP >> 16;
 
1731
            yap = YAP & 0xffff;
 
1732
 
 
1733
            dptr = dest + dx + ((y + dy) * dow);
 
1734
            for(x = dxx; x < end; x++){
 
1735
                Cx = XAP >> 16;
 
1736
                xap = XAP & 0xffff;
 
1737
 
 
1738
                sptr = ypoints[dyy + y] + xpoints[x];
 
1739
                pix = sptr;
 
1740
                sptr += sow;
 
1741
                rx = (R_VAL(pix) * xap) >> 9;
 
1742
                gx = (G_VAL(pix) * xap) >> 9;
 
1743
                bx = (B_VAL(pix) * xap) >> 9;
 
1744
                pix++;
 
1745
                for(i = (1 << 14) - xap; i > Cx; i -= Cx){
 
1746
                    rx += (R_VAL(pix) * Cx) >> 9;
 
1747
                    gx += (G_VAL(pix) * Cx) >> 9;
 
1748
                    bx += (B_VAL(pix) * Cx) >> 9;
 
1749
                    pix++;
 
1750
                }
 
1751
                if(i > 0){
 
1752
                    rx += (R_VAL(pix) * i) >> 9;
 
1753
                    gx += (G_VAL(pix) * i) >> 9;
 
1754
                    bx += (B_VAL(pix) * i) >> 9;
 
1755
                }
 
1756
 
 
1757
                r = (rx * yap) >> 14;
 
1758
                g = (gx * yap) >> 14;
 
1759
                b = (bx * yap) >> 14;
 
1760
 
 
1761
                for(j = (1 << 14) - yap; j > Cy; j -= Cy){
 
1762
                    pix = sptr;
 
1763
                    sptr += sow;
 
1764
                    rx = (R_VAL(pix) * xap) >> 9;
 
1765
                    gx = (G_VAL(pix) * xap) >> 9;
 
1766
                    bx = (B_VAL(pix) * xap) >> 9;
 
1767
                    pix++;
 
1768
                    for(i = (1 << 14) - xap; i > Cx; i -= Cx){
 
1769
                        rx += (R_VAL(pix) * Cx) >> 9;
 
1770
                        gx += (G_VAL(pix) * Cx) >> 9;
 
1771
                        bx += (B_VAL(pix) * Cx) >> 9;
 
1772
                        pix++;
 
1773
                    }
 
1774
                    if(i > 0){
 
1775
                        rx += (R_VAL(pix) * i) >> 9;
 
1776
                        gx += (G_VAL(pix) * i) >> 9;
 
1777
                        bx += (B_VAL(pix) * i) >> 9;
 
1778
                    }
 
1779
 
 
1780
                    r += (rx * Cy) >> 14;
 
1781
                    g += (gx * Cy) >> 14;
 
1782
                    b += (bx * Cy) >> 14;
 
1783
                }
 
1784
                if(j > 0){
 
1785
                    pix = sptr;
 
1786
                    sptr += sow;
 
1787
                    rx = (R_VAL(pix) * xap) >> 9;
 
1788
                    gx = (G_VAL(pix) * xap) >> 9;
 
1789
                    bx = (B_VAL(pix) * xap) >> 9;
 
1790
                    pix++;
 
1791
                    for(i = (1 << 14) - xap; i > Cx; i -= Cx){
 
1792
                        rx += (R_VAL(pix) * Cx) >> 9;
 
1793
                        gx += (G_VAL(pix) * Cx) >> 9;
 
1794
                        bx += (B_VAL(pix) * Cx) >> 9;
 
1795
                        pix++;
 
1796
                    }
 
1797
                    if(i > 0){
 
1798
                        rx += (R_VAL(pix) * i) >> 9;
 
1799
                        gx += (G_VAL(pix) * i) >> 9;
 
1800
                        bx += (B_VAL(pix) * i) >> 9;
 
1801
                    }
 
1802
 
 
1803
                    r += (rx * j) >> 14;
 
1804
                    g += (gx * j) >> 14;
 
1805
                    b += (bx * j) >> 14;
 
1806
                }
 
1807
 
 
1808
                R_VAL(dptr) = r >> 5;
 
1809
                G_VAL(dptr) = g >> 5;
 
1810
                B_VAL(dptr) = b >> 5;
 
1811
                dptr++;
 
1812
            }
 
1813
        }
 
1814
    }
 
1815
}
 
1816
 
 
1817
// Imlib2/Mosfet code end
 
1818
 
 
1819
 
 
1820
// public functions :
 
1821
// ------------------
 
1822
 
 
1823
// This function returns how many pixels around the zoomed area should be
 
1824
// included in the image. This is used when doing incremental painting, because
 
1825
// some smoothing algorithms use surrounding pixels and not including them
 
1826
// could sometimes make the edges between incremental steps visible.
 
1827
int extraScalePixels( SmoothAlgorithm alg, double zoom, double blur )
 
1828
{
 
1829
        double filtersupport = 0;
 
1830
        Filter filter = NULL;
 
1831
        switch( alg ) {
 
1832
        case SMOOTH_NONE:
 
1833
                filter = NULL;
 
1834
                filtersupport = 0.0;
 
1835
                break;
 
1836
        case SMOOTH_FAST:
 
1837
                filter = Box;
 
1838
                filtersupport = 0.5;
 
1839
                break;
 
1840
        case SMOOTH_NORMAL:
 
1841
                filter = Triangle;
 
1842
                filtersupport = 1.0;
 
1843
                break;
 
1844
        case SMOOTH_BEST:
 
1845
                filter = Mitchell;
 
1846
                filtersupport = 2.0;
 
1847
                break;
 
1848
        }
 
1849
        if( zoom == 1.0 || filtersupport == 0.0 ) return 0;
 
1850
        // Imlib2/Mosfet scale - I have really no idea how many pixels it needs
 
1851
        if( filter == Box && blur == 1.0 ) return int( 3 / zoom + 1 );
 
1852
// This is support size for ImageMagick's scaling.
 
1853
        double scale=blur*QMAX(1.0/zoom,1.0);
 
1854
        double support=scale* filtersupport;
 
1855
        if (support <= 0.5) support=0.5+0.000001;
 
1856
        return int( support + 1 );
 
1857
}
 
1858
 
 
1859
QImage scale(const QImage& image, int width, int height,
 
1860
        SmoothAlgorithm alg, QImage::ScaleMode mode, double blur )
 
1861
{
 
1862
        if( image.isNull()) return image.copy();
 
1863
        
 
1864
        QSize newSize( image.size() );
 
1865
        newSize.scale( QSize( width, height ), (QSize::ScaleMode)mode ); // ### remove cast in Qt 4.0
 
1866
        newSize = newSize.expandedTo( QSize( 1, 1 )); // make sure it doesn't become null
 
1867
 
 
1868
        if ( newSize == image.size() ) return image.copy();
 
1869
        
 
1870
        width = newSize.width();
 
1871
        height = newSize.height();
 
1872
        Filter filter = NULL;
 
1873
        fastfloat filtersupport;
 
1874
        
 
1875
        switch( alg ) {
 
1876
        case SMOOTH_NONE:
 
1877
                filter = NULL;
 
1878
                filtersupport = 0.0;
 
1879
                break;
 
1880
        case SMOOTH_FAST:
 
1881
                filter = Box;
 
1882
                filtersupport = 0.5;
 
1883
                break;
 
1884
        case SMOOTH_NORMAL:
 
1885
                filter = Triangle;
 
1886
                filtersupport = 1.0;
 
1887
                break;
 
1888
        case SMOOTH_BEST:
 
1889
                filter = Mitchell;
 
1890
                filtersupport = 2.0;
 
1891
                break;
 
1892
        }
 
1893
        
 
1894
        if( filter == Box && blur == 1.0 )
 
1895
                return MImageScale::smoothScale( image, width, height );
 
1896
 
 
1897
        if( filter == Box && width > image.width() && height > image.height() && blur == 1.0 ) {
 
1898
                filter = NULL; // Box doesn't really smooth when enlarging
 
1899
        }
 
1900
 
 
1901
        if( filter == NULL ) {
 
1902
                return SampleImage( image, width, height ); // doesn't need 32bit
 
1903
        }
 
1904
 
 
1905
        return ResizeImage( image.convertDepth( 32 ), width, height, filter, filtersupport, blur );
 
1906
        // unlike Qt's smoothScale() this function introduces new colors to grayscale images ... oh well
 
1907
}
 
1908
 
 
1909
 
 
1910
} // namespace