summaryrefslogtreecommitdiff
path: root/packages/gtk+/gtk+-2.10.12/plana-pixops.patch
blob: 21fe4879c578253cb72030851d02dee77f56d896 (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
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
diff -urN gtk+-2.10.9.orig/config.h.in gtk+-2.10.9-integer-pixops/config.h.in
--- gtk+-2.10.9.orig/config.h.in	2007-01-22 09:01:23.000000000 -0700
+++ gtk+-2.10.9-integer-pixops/config.h.in	2007-02-10 12:15:39.000000000 -0700
@@ -259,3 +259,7 @@
 
 /* Define to `int' if <sys/types.h> doesn't define. */
 #undef uid_t
+
+/* Define to use integer math rather than floating point where possible.  */
+#undef ENABLE_INTEGER_PIXOPS
+
diff -urN gtk+-2.10.9.orig/configure.in gtk+-2.10.9-integer-pixops/configure.in
--- gtk+-2.10.9.orig/configure.in	2007-01-22 08:59:41.000000000 -0700
+++ gtk+-2.10.9-integer-pixops/configure.in	2007-02-10 12:15:39.000000000 -0700
@@ -203,6 +203,15 @@
               [AC_HELP_STRING([--disable-rebuilds],
                               [disable all source autogeneration rules])],,
               [enable_rebuilds=yes])
+AC_ARG_ENABLE(integer-pixops, 
+              [AC_HELP_STRING([--enable-integer-pixops],
+	                      [use integer math where possible])],,
+	      [enable_integer_pixops=no])
+
+if test "x$enable_integer_pixops" = "xyes"; then
+  AC_DEFINE(ENABLE_INTEGER_PIXOPS)
+fi
+
 AC_ARG_ENABLE(visibility,
               [AC_HELP_STRING([--disable-visibility],
                               [don't use ELF visibility attributes])],,
diff -urN gtk+-2.10.9.orig/gdk-pixbuf/pixops/pixops.c gtk+-2.10.9-integer-pixops/gdk-pixbuf/pixops/pixops.c
--- gtk+-2.10.9.orig/gdk-pixbuf/pixops/pixops.c	2007-01-22 08:50:43.000000000 -0700
+++ gtk+-2.10.9-integer-pixops/gdk-pixbuf/pixops/pixops.c	2007-02-12 01:00:23.000000000 -0700
@@ -28,21 +28,42 @@
 #define SUBSAMPLE_MASK ((1 << SUBSAMPLE_BITS)-1)
 #define SCALE_SHIFT 16
 
+/* TODO: Add a FLOOR() and CEIL() macro to handle normalized values) */
+/* TODO: Get rid of standard C numeric types (ie. int). Replace with glib types */
+#ifdef ENABLE_INTEGER_PIXOPS
+/* The bigger the value of FRAC is, the better the accuracy. Be wary of 
+   overflows, though */
+#define FRAC 0x10000ULL
+#define NORMALIZE(d) (d * FRAC)
+#define UNNORMALIZE(t,i) ((t)(i) / FRAC)
+#define FLOOR(i) (int)((i) / FRAC)
+#define CEIL(i) (((i) - 1) / FRAC + 1)
+#define DOUBLE_TYPE gint32
+#define BIG_DOUBLE_TYPE gint64
+#else
+#define NORMALIZE(d) (d)
+#define UNNORMALIZE(t,i) (t)(i)
+#define FLOOR(i) floor(i)
+#define CEIL(i) ceil(i)
+#define DOUBLE_TYPE double
+#define BIG_DOUBLE_TYPE double
+#endif
+
 typedef struct _PixopsFilter PixopsFilter;
 typedef struct _PixopsFilterDimension PixopsFilterDimension;
 
 struct _PixopsFilterDimension
 {
   int n;
-  double offset;
-  double *weights;
+  BIG_DOUBLE_TYPE offset;
+  DOUBLE_TYPE *weights;
 };
 
 struct _PixopsFilter
 {
   PixopsFilterDimension x;
   PixopsFilterDimension y;
-  double overall_alpha;
+  gint32 overall_alpha; /* Normalized: alpha * 255; Not sure why original devs chose 255 */
 }; 
 
 typedef guchar *(*PixopsLineFunc) (int *weights, int n_x, int n_y,
@@ -86,13 +107,13 @@
 		      int            src_rowstride,
 		      int            src_channels,
 		      gboolean       src_has_alpha,
-		      double         scale_x,
-		      double         scale_y)
+		      DOUBLE_TYPE    scale_x,
+		      DOUBLE_TYPE    scale_y)
 {
   int i;
   int x;
-  int x_step = (1 << SCALE_SHIFT) / scale_x;
-  int y_step = (1 << SCALE_SHIFT) / scale_y;
+  int x_step = NORMALIZE((1 << SCALE_SHIFT)) / scale_x;
+  int y_step = NORMALIZE((1 << SCALE_SHIFT)) / scale_y;
   int xmax, xstart, xstop, x_pos, y_pos;
   const guchar *p;
 
@@ -175,14 +196,14 @@
 			  int            src_rowstride,
 			  int            src_channels,
 			  gboolean       src_has_alpha,
-			  double         scale_x,
-			  double         scale_y,
+			  DOUBLE_TYPE    scale_x,
+			  DOUBLE_TYPE    scale_y,
 			  int            overall_alpha)
 {
   int i;
   int x;
-  int x_step = (1 << SCALE_SHIFT) / scale_x;
-  int y_step = (1 << SCALE_SHIFT) / scale_y;
+  int x_step = NORMALIZE((1 << SCALE_SHIFT)) / scale_x;
+  int y_step = NORMALIZE((1 << SCALE_SHIFT)) / scale_y;
   int xmax, xstart, xstop, x_pos, y_pos;
   const guchar *p;
   unsigned int  a0;
@@ -260,8 +281,8 @@
 				int            src_rowstride,
 				int            src_channels,
 				gboolean       src_has_alpha,
-				double         scale_x,
-				double         scale_y,
+				DOUBLE_TYPE    scale_x,
+				DOUBLE_TYPE    scale_y,
 				int            overall_alpha,
 				int            check_x,
 				int            check_y,
@@ -271,8 +292,8 @@
 {
   int i, j;
   int x;
-  int x_step = (1 << SCALE_SHIFT) / scale_x;
-  int y_step = (1 << SCALE_SHIFT) / scale_y;
+  int x_step = NORMALIZE((1 << SCALE_SHIFT)) / scale_x;
+  int y_step = NORMALIZE((1 << SCALE_SHIFT)) / scale_y;
   int r1, g1, b1, r2, g2, b2;
   int check_shift = get_check_shift (check_size);
   int xmax, xstart, xstop, x_pos, y_pos;
@@ -977,9 +998,9 @@
                int    n_x, 
                int    n_y,
                int    total, 
-               double overall_alpha)
+               gint32 overall_alpha)
 {
-  int correction = (int)(0.5 + 65536 * overall_alpha) - total;
+  int correction = (int)(0.5 + 65536 / 255 * overall_alpha) - total;
   int remaining, c, d, i;
   
   if (correction != 0)
@@ -1009,7 +1030,7 @@
   for (i_offset=0; i_offset < SUBSAMPLE; i_offset++)
     for (j_offset=0; j_offset < SUBSAMPLE; j_offset++)
       {
-        double weight;
+        DOUBLE_TYPE weight;
         int *pixel_weights = weights + ((i_offset*SUBSAMPLE) + j_offset) * n_x * n_y;
         int total = 0;
         int i, j;
@@ -1017,13 +1038,15 @@
         for (i=0; i < n_y; i++)
           for (j=0; j < n_x; j++)
             {
-              weight = filter->x.weights[(j_offset * n_x) + j] *
+              weight = UNNORMALIZE(DOUBLE_TYPE, filter->x.weights[(j_offset * n_x) + j] *
                        filter->y.weights[(i_offset * n_y) + i] *
-                       filter->overall_alpha * 65536 + 0.5;
+                       filter->overall_alpha * 65536 / 255) + NORMALIZE(0.5);
+                       /* Wonder how I should treat the "+ 0.5" for scientific
+                       rouding off */
 
-              total += (int)weight;
+              total += UNNORMALIZE(int, weight);
 
-              *(pixel_weights + n_x * i + j) = weight;
+              *(pixel_weights + n_x * i + j) = UNNORMALIZE(int, weight);
             }
 
         correct_total (pixel_weights, n_x, n_y, total, filter->overall_alpha);
@@ -1047,8 +1070,8 @@
 		int             src_rowstride,
 		int             src_channels,
 		gboolean        src_has_alpha,
-		double          scale_x,
-		double          scale_y,
+		DOUBLE_TYPE     scale_x,
+		DOUBLE_TYPE     scale_y,
 		int             check_x,
 		int             check_y,
 		int             check_size,
@@ -1064,12 +1087,13 @@
   guchar **line_bufs = g_new (guchar *, filter->y.n);
   int *filter_weights = make_filter_table (filter);
 
-  int x_step = (1 << SCALE_SHIFT) / scale_x; /* X step in source (fixed point) */
-  int y_step = (1 << SCALE_SHIFT) / scale_y; /* Y step in source (fixed point) */
+  int x_step = NORMALIZE((1 << SCALE_SHIFT)) / scale_x; /* X step in source (fixed point) */
+  int y_step = NORMALIZE((1 << SCALE_SHIFT)) / scale_y; /* Y step in source (fixed point) */
 
   int check_shift = check_size ? get_check_shift (check_size) : 0;
 
-  int scaled_x_offset = floor (filter->x.offset * (1 << SCALE_SHIFT));
+  /* Possible overflow when scale-shifting which is why offset is BIG_DOUBLE_TYPE */
+  int scaled_x_offset = FLOOR(filter->x.offset * (1 << SCALE_SHIFT));
 
   /* Compute the index where we run off the end of the source buffer. The furthest
    * source pixel we access at index i is:
@@ -1087,7 +1111,7 @@
   int run_end_index = MYDIV (run_end_x + x_step - 1, x_step) - render_x0;
   run_end_index = MIN (run_end_index, render_x1 - render_x0);
 
-  y = render_y0 * y_step + floor (filter->y.offset * (1 << SCALE_SHIFT));
+  y = render_y0 * y_step + FLOOR(filter->y.offset * (1 << SCALE_SHIFT));
   for (i = 0; i < (render_y1 - render_y0); i++)
     {
       int dest_x;
@@ -1180,37 +1204,37 @@
  */
 static void
 tile_make_weights (PixopsFilterDimension *dim,
-		   double                 scale)
+		   DOUBLE_TYPE            scale)
 {
-  int n = ceil (1 / scale + 1);
-  double *pixel_weights = g_new (double, SUBSAMPLE * n);
+  int n = CEIL(NORMALIZE(NORMALIZE(1)) / scale + NORMALIZE(1)); /* Another possible overflow */
+  DOUBLE_TYPE *pixel_weights = g_new (DOUBLE_TYPE, SUBSAMPLE * n);
   int offset;
   int i;
-
+  
   dim->n = n;
-  dim->offset = 0;
+  dim->offset = NORMALIZE(0);
   dim->weights = pixel_weights;
 
   for (offset = 0; offset < SUBSAMPLE; offset++)
     {
-      double x = (double)offset / SUBSAMPLE;
-      double a = x + 1 / scale;
+      DOUBLE_TYPE x = (DOUBLE_TYPE)NORMALIZE(offset) / SUBSAMPLE;
+      DOUBLE_TYPE a = x + NORMALIZE(NORMALIZE(1)) / scale;
 
       for (i = 0; i < n; i++)
         {
-          if (i < x)
+          if (NORMALIZE(i) < x)
             {
-              if (i + 1 > x)
-                *(pixel_weights++)  = (MIN (i + 1, a) - x) * scale;
+              if (NORMALIZE(i + 1) > x)
+                *(pixel_weights++)  = UNNORMALIZE(DOUBLE_TYPE, (MIN(NORMALIZE(i + 1), a) - x) * scale);
               else
-                *(pixel_weights++) = 0;
+                *(pixel_weights++) = NORMALIZE(0);
             }
           else
             {
-              if (a > i)
-                *(pixel_weights++)  = (MIN (i + 1, a) - i) * scale;
+              if (a > NORMALIZE(i))
+                *(pixel_weights++)  = UNNORMALIZE(DOUBLE_TYPE, (MIN(NORMALIZE(i + 1), a) - i) * scale);
               else
-                *(pixel_weights++) = 0;
+                *(pixel_weights++) = NORMALIZE(0);
             }
        }
     }
@@ -1222,41 +1246,44 @@
  */
 static void
 bilinear_magnify_make_weights (PixopsFilterDimension *dim,
-			       double                 scale)
+			       DOUBLE_TYPE            scale)
 {
-  double *pixel_weights;
+  DOUBLE_TYPE *pixel_weights;
   int n;
   int offset;
   int i;
 
-  if (scale > 1.0)            /* Linear */
+  if (scale > NORMALIZE(1.0))            /* Linear */
     {
       n = 2;
-      dim->offset = 0.5 * (1 / scale - 1);
+      dim->offset = NORMALIZE(NORMALIZE(0.5) / (scale - NORMALIZE(1)));
     }
   else                          /* Tile */
     {
-      n = ceil (1.0 + 1.0 / scale);
-      dim->offset = 0.0;
+      n = CEIL(NORMALIZE(1.0) + NORMALIZE(NORMALIZE(1.0)) / scale);
+      dim->offset = NORMALIZE(0.0);
     }
-
+  
   dim->n = n;
-  dim->weights = g_new (double, SUBSAMPLE * n);
+  dim->weights = g_new (DOUBLE_TYPE, SUBSAMPLE * n);
 
   pixel_weights = dim->weights;
 
   for (offset=0; offset < SUBSAMPLE; offset++)
     {
-      double x = (double)offset / SUBSAMPLE;
+      DOUBLE_TYPE x = (DOUBLE_TYPE)NORMALIZE(offset) / SUBSAMPLE;
 
-      if (scale > 1.0)      /* Linear */
+      if (scale > NORMALIZE(1.0))      /* Linear */
         {
           for (i = 0; i < n; i++)
-            *(pixel_weights++) = (((i == 0) ? (1 - x) : x) / scale) * scale;
+            /* In the original, what is the point of dividing by scale then multiplying by scale? */
+            /* *(pixel_weights++) = (((i == 0) ? (1 - x) : x) / scale) * scale;*/
+            /* *(pixel_weights++) = i == 0 ? NORMALIZE(1) - x : x; */
+            *(pixel_weights++) = (((i == 0) ? NORMALIZE(1) - x : x) / scale) * scale;
         }
       else                  /* Tile */
         {
-          double a = x + 1 / scale;
+          DOUBLE_TYPE a = x + NORMALIZE(NORMALIZE(1)) / scale;
 
           /*           x
            * ---------|--.-|----|--.-|-------  SRC
@@ -1264,19 +1291,19 @@
            */
           for (i = 0; i < n; i++)
             {
-              if (i < x)
+              if (NORMALIZE(i) < x)
                 {
-                  if (i + 1 > x)
-                    *(pixel_weights++) = (MIN (i + 1, a) - x) * scale;
+                  if (NORMALIZE(i + 1) > x)
+                    *(pixel_weights++) = UNNORMALIZE(DOUBLE_TYPE, (MIN(NORMALIZE(i + 1), a) - x) * scale);
                   else
-                    *(pixel_weights++) = 0;
+                    *(pixel_weights++) = NORMALIZE(0);
                 }
               else
                 {
-                  if (a > i)
-                    *(pixel_weights++) = (MIN (i + 1, a) - i) * scale;
+                  if (a > NORMALIZE(i))
+                    *(pixel_weights++) = UNNORMALIZE(DOUBLE_TYPE, (MIN(NORMALIZE(i + 1), a) - i) * scale);
                   else
-                    *(pixel_weights++) = 0;
+                    *(pixel_weights++) = NORMALIZE(0);
                 }
             }
         }
@@ -1291,14 +1318,14 @@
  * We combine two of these to compute the convolution of
  * a box filter with a triangular spike.
  */
-static double
-linear_box_half (double b0, double b1)
+static DOUBLE_TYPE
+linear_box_half (DOUBLE_TYPE b0, DOUBLE_TYPE b1)
 {
-  double a0, a1;
-  double x0, x1;
+  DOUBLE_TYPE a0, a1;
+  DOUBLE_TYPE x0, x1;
 
-  a0 = 0.;
-  a1 = 1.;
+  a0 = NORMALIZE(0.);
+  a1 = NORMALIZE(1.);
 
   if (a0 < b0)
     {
@@ -1308,7 +1335,7 @@
           x1 = MIN (a1, b1);
         }
       else
-        return 0;
+        return NORMALIZE(0);
     }
   else
     {
@@ -1318,10 +1345,10 @@
           x1 = MIN (a1, b1);
         }
       else
-        return 0;
+        return NORMALIZE(0);
     }
 
-  return 0.5 * (x1*x1 - x0*x0);
+  return UNNORMALIZE(DOUBLE_TYPE, NORMALIZE(0.5) * UNNORMALIZE(DOUBLE_TYPE, (x1*x1 - x0*x0)));
 }
 
 /* Compute weights for reconstructing with bilinear
@@ -1329,28 +1356,28 @@
  */
 static void
 bilinear_box_make_weights (PixopsFilterDimension *dim,
-			   double                 scale)
+			   DOUBLE_TYPE            scale)
 {
-  int n = ceil (1/scale + 3.0);
-  double *pixel_weights = g_new (double, SUBSAMPLE * n);
-  double w;
+  int n = CEIL(NORMALIZE(NORMALIZE(1))/scale + NORMALIZE(3.0));
+  DOUBLE_TYPE *pixel_weights = g_new (DOUBLE_TYPE, SUBSAMPLE * n);
+  DOUBLE_TYPE w;
   int offset, i;
 
-  dim->offset = -1.0;
+  dim->offset = NORMALIZE(-1.0);
   dim->n = n;
   dim->weights = pixel_weights;
 
   for (offset = 0; offset < SUBSAMPLE; offset++)
     {
-      double x = (double)offset / SUBSAMPLE;
-      double a = x + 1 / scale;
+      DOUBLE_TYPE x = (DOUBLE_TYPE)NORMALIZE(offset) / SUBSAMPLE;
+      DOUBLE_TYPE a = x + NORMALIZE(NORMALIZE(1)) / scale;
 
       for (i = 0; i < n; i++)
         {
-          w  = linear_box_half (0.5 + i - a, 0.5 + i - x);
-          w += linear_box_half (1.5 + x - i, 1.5 + a - i);
+          w  = linear_box_half (NORMALIZE(0.5) + NORMALIZE(i) - a, NORMALIZE(0.5) + NORMALIZE(i) - x);
+          w += linear_box_half (NORMALIZE(1.5) - NORMALIZE(i) + x, NORMALIZE(1.5) - NORMALIZE(i) + a);
       
-          *(pixel_weights++) = w * scale;
+          *(pixel_weights++) = UNNORMALIZE(DOUBLE_TYPE, w * scale);
         }
     }
 }
@@ -1358,8 +1385,8 @@
 static void
 make_weights (PixopsFilter     *filter,
 	      PixopsInterpType  interp_type,	      
-	      double            scale_x,
-	      double            scale_y)
+	      DOUBLE_TYPE       scale_x,
+	      DOUBLE_TYPE       scale_y)
 {
   switch (interp_type)
     {
@@ -1399,8 +1426,8 @@
 			 int             src_rowstride,
 			 int             src_channels,
 			 gboolean        src_has_alpha,
-			 double          scale_x,
-			 double          scale_y,
+			 double          scale_x_d,
+			 double          scale_y_d,
 			 PixopsInterpType   interp_type,
 			 int             overall_alpha,
 			 int             check_x,
@@ -1409,6 +1436,8 @@
 			 guint32         color1,
 			 guint32         color2)
 {
+  DOUBLE_TYPE scale_x = NORMALIZE(scale_x_d);
+  DOUBLE_TYPE scale_y = NORMALIZE(scale_y_d);
   PixopsFilter filter;
   PixopsLineFunc line_func;
   
@@ -1419,7 +1448,7 @@
   g_return_if_fail (!(dest_channels == 3 && dest_has_alpha));
   g_return_if_fail (!(src_channels == 3 && src_has_alpha));
 
-  if (scale_x == 0 || scale_y == 0)
+  if (scale_x == NORMALIZE(0) || scale_y == NORMALIZE(0))
     return;
 
   if (!src_has_alpha && overall_alpha == 255)
@@ -1427,7 +1456,7 @@
       _pixops_scale (dest_buf, render_x0, render_y0, render_x1, render_y1,
 		     dest_rowstride, dest_channels, dest_has_alpha,
 		     src_buf, src_width, src_height, src_rowstride, src_channels,
-		     src_has_alpha, scale_x, scale_y, interp_type);
+		     src_has_alpha, UNNORMALIZE(double, scale_x), UNNORMALIZE(double, scale_y), interp_type);
       return;
     }
 
@@ -1441,7 +1470,8 @@
       return;
     }
   
-  filter.overall_alpha = overall_alpha / 255.;
+  /* filter.overall_alpha = overall_alpha / 255.; /* Why is it 255 instead of 256? */
+  filter.overall_alpha = overall_alpha;
   make_weights (&filter, interp_type, scale_x, scale_y);
 
 #ifdef USE_MMX
@@ -1501,11 +1531,13 @@
 		   int            src_rowstride,
 		   int            src_channels,
 		   gboolean       src_has_alpha,
-		   double         scale_x,
-		   double         scale_y,
+		   double         scale_x_d,
+		   double         scale_y_d,
 		   PixopsInterpType  interp_type,
 		   int            overall_alpha)
 {
+  DOUBLE_TYPE scale_x = NORMALIZE(scale_x_d);
+  DOUBLE_TYPE scale_y = NORMALIZE(scale_y_d);
   PixopsFilter filter;
   PixopsLineFunc line_func;
   
@@ -1516,7 +1548,7 @@
   g_return_if_fail (!(dest_channels == 3 && dest_has_alpha));
   g_return_if_fail (!(src_channels == 3 && src_has_alpha));
 
-  if (scale_x == 0 || scale_y == 0)
+  if (scale_x == NORMALIZE(0) || scale_y == NORMALIZE(0))
     return;
 
   if (!src_has_alpha && overall_alpha == 255)
@@ -1524,7 +1556,7 @@
       _pixops_scale (dest_buf, render_x0, render_y0, render_x1, render_y1,
 		     dest_rowstride, dest_channels, dest_has_alpha,
 		     src_buf, src_width, src_height, src_rowstride, src_channels,
-		     src_has_alpha, scale_x, scale_y, interp_type);
+		     src_has_alpha, UNNORMALIZE(double, scale_x), UNNORMALIZE(double, scale_y), interp_type);
       return;
     }
 
@@ -1537,7 +1569,7 @@
       return;
     }
   
-  filter.overall_alpha = overall_alpha / 255.;
+  filter.overall_alpha = overall_alpha;
   make_weights (&filter, interp_type, scale_x, scale_y);
 
   if (filter.x.n == 2 && filter.y.n == 2 &&
@@ -1578,10 +1610,12 @@
 	       int            src_rowstride,
 	       int            src_channels,
 	       gboolean       src_has_alpha,
-	       double         scale_x,
-	       double         scale_y,
+	       double         scale_x_d,
+	       double         scale_y_d,
 	       PixopsInterpType  interp_type)
 {
+  DOUBLE_TYPE scale_x = NORMALIZE(scale_x_d);
+  DOUBLE_TYPE scale_y = NORMALIZE(scale_y_d);
   PixopsFilter filter;
   PixopsLineFunc line_func;
 
@@ -1593,7 +1627,7 @@
   g_return_if_fail (!(src_channels == 3 && src_has_alpha));
   g_return_if_fail (!(src_has_alpha && !dest_has_alpha));
 
-  if (scale_x == 0 || scale_y == 0)
+  if (scale_x == NORMALIZE(0) || scale_y == NORMALIZE(0))
     return;
 
   if (interp_type == PIXOPS_INTERP_NEAREST)
@@ -1605,7 +1639,7 @@
       return;
     }
   
-  filter.overall_alpha = 1.0;
+  filter.overall_alpha = 255;
   make_weights (&filter, interp_type, scale_x, scale_y);
 
   if (filter.x.n == 2 && filter.y.n == 2 && dest_channels == 3 && src_channels == 3)