Subversion Repositories Games.Prince of Persia

Rev

Rev 4 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4 Rev 5
Line 85... Line 85...
85
#define MIN(a,b) ((a) < (b) ? (a) : (b))
85
#define MIN(a,b) ((a) < (b) ? (a) : (b))
86
#endif // MIN
86
#endif // MIN
87
#ifndef MAX
87
#ifndef MAX
88
#define MAX(a,b) ((a) > (b) ? (a) : (b))
88
#define MAX(a,b) ((a) > (b) ? (a) : (b))
89
#endif // MAX
89
#endif // MAX
90
 
-
 
91
 
-
 
92
typedef void (alphagrad_func) (uint32_t *pixBack, uint32_t pixFront, unsigned int M, unsigned int N);
-
 
93
typedef double (dist_func) (uint32_t pix1, uint32_t pix2);
-
 
94
 
-
 
95
 
-
 
96
 
-
 
97
enum RotationDegree //clock-wise
-
 
98
{
-
 
99
   ROT_0 = 0,
-
 
100
   ROT_90,
-
 
101
   ROT_180,
-
 
102
   ROT_270
-
 
103
};
-
 
104
 
90
 
105
 
91
 
106
enum BlendType
92
enum BlendType
107
{
93
{
108
   BLEND_NONE = 0,
94
   BLEND_NONE = 0,
Line 142... Line 128...
142
typedef struct outmatrix_s
128
typedef struct outmatrix_s
143
{
129
{
144
   size_t size;
130
   size_t size;
145
   uint32_t* ptr;
131
   uint32_t* ptr;
146
   int stride;
132
   int stride;
147
   RotationDegree rotDeg;
133
   int rotDeg; // either 0, 90, 180 or 270
148
} outmatrix_t;
134
} outmatrix_t;
149
 
135
 
150
 
136
 
151
static void outmatrix_create (outmatrix_t *mat, size_t size, uint32_t *ptr, int stride, RotationDegree rotDeg) //access matrix area, top-left at position "out" for image with given width
137
static void outmatrix_create (outmatrix_t *mat, size_t size, uint32_t *ptr, int stride, int rotDeg) //access matrix area, top-left at position "out" for image with given width
152
{
138
{
153
   mat->size = size;
139
   mat->size = size;
154
   mat->ptr = ptr;
140
   mat->ptr = ptr;
155
   mat->stride = stride;
141
   mat->stride = stride;
156
   mat->rotDeg = rotDeg;
142
   mat->rotDeg = rotDeg;
Line 160... Line 146...
160
static uint32_t *outmatrix_ref (outmatrix_t *mat, size_t I, size_t J)
146
static uint32_t *outmatrix_ref (outmatrix_t *mat, size_t I, size_t J)
161
{
147
{
162
   size_t I_old;
148
   size_t I_old;
163
   size_t J_old;
149
   size_t J_old;
164
   // calculate input matrix coordinates after rotation: (i, j) = (row, col) indices, N = size of (square) matrix
150
   // calculate input matrix coordinates after rotation: (i, j) = (row, col) indices, N = size of (square) matrix
165
   if      (mat->rotDeg == ROT_270) { I_old = J;                 J_old = mat->size - 1 - I; }
151
   if (mat->rotDeg == 270) { I_old = J;                 J_old = mat->size - 1 - I; }
166
   else if (mat->rotDeg == ROT_180) { I_old = mat->size - 1 - I; J_old = mat->size - 1 - J; }
152
   else if (mat->rotDeg == 180) { I_old = mat->size - 1 - I; J_old = mat->size - 1 - J; }
167
   else if (mat->rotDeg == ROT_90)  { I_old = mat->size - 1 - J; J_old = I;                 }
153
   else if (mat->rotDeg == 90) { I_old = mat->size - 1 - J; J_old = I; }
168
   else                             { I_old = I;                 J_old = J;                 }
154
   else { I_old = I;                 J_old = J; }
169
 
155
 
170
   return (mat->ptr + I_old * mat->stride + J_old);
156
   return (mat->ptr + I_old * mat->stride + J_old);
171
}
157
}
-
 
158
 
-
 
159
 
-
 
160
typedef void (alphagrad_func) (uint32_t *pixBack, uint32_t pixFront, unsigned int M, unsigned int N);
-
 
161
typedef double (dist_func) (uint32_t pix1, uint32_t pix2);
-
 
162
 
-
 
163
 
-
 
164
typedef struct scaler_s
-
 
165
{
-
 
166
   int factor;
-
 
167
   void (*blend_line_shallow) (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad);
-
 
168
   void (*blend_line_steep) (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad);
-
 
169
   void (*blend_line_steep_and_shallow) (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad);
-
 
170
   void (*blend_line_diagonal) (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad);
-
 
171
   void (*blend_corner) (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad);
-
 
172
} scaler_t;
-
 
173
 
-
 
174
 
-
 
175
/////////////////////////////////
-
 
176
// shallow line scaling functions
-
 
177
 
-
 
178
static void blend_line_shallow_2x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
179
{
-
 
180
   alphagrad (outmatrix_ref (out, 2 - 1, 0), col, 1, 4);
-
 
181
   alphagrad (outmatrix_ref (out, 2 - 1, 1), col, 3, 4);
-
 
182
}
-
 
183
static void blend_line_shallow_3x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
184
{
-
 
185
   alphagrad (outmatrix_ref (out, 3 - 1, 0), col, 1, 4);
-
 
186
   alphagrad (outmatrix_ref (out, 3 - 2, 2), col, 1, 4);
-
 
187
   alphagrad (outmatrix_ref (out, 3 - 1, 1), col, 3, 4);
-
 
188
   *outmatrix_ref (out, 3 - 1, 2) = col;
-
 
189
}
-
 
190
static void blend_line_shallow_4x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
191
{
-
 
192
   alphagrad (outmatrix_ref (out, 4 - 1, 0), col, 1, 4);
-
 
193
   alphagrad (outmatrix_ref (out, 4 - 2, 2), col, 1, 4);
-
 
194
   alphagrad (outmatrix_ref (out, 4 - 1, 1), col, 3, 4);
-
 
195
   alphagrad (outmatrix_ref (out, 4 - 2, 3), col, 3, 4);
-
 
196
   *outmatrix_ref (out, 4 - 1, 2) = col;
-
 
197
   *outmatrix_ref (out, 4 - 1, 3) = col;
-
 
198
}
-
 
199
static void blend_line_shallow_5x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
200
{
-
 
201
   alphagrad (outmatrix_ref (out, 5 - 1, 0), col, 1, 4);
-
 
202
   alphagrad (outmatrix_ref (out, 5 - 2, 2), col, 1, 4);
-
 
203
   alphagrad (outmatrix_ref (out, 5 - 3, 4), col, 1, 4);
-
 
204
   alphagrad (outmatrix_ref (out, 5 - 1, 1), col, 3, 4);
-
 
205
   alphagrad (outmatrix_ref (out, 5 - 2, 3), col, 3, 4);
-
 
206
   *outmatrix_ref (out, 5 - 1, 2) = col;
-
 
207
   *outmatrix_ref (out, 5 - 1, 3) = col;
-
 
208
   *outmatrix_ref (out, 5 - 1, 4) = col;
-
 
209
   *outmatrix_ref (out, 5 - 2, 4) = col;
-
 
210
}
-
 
211
static void blend_line_shallow_6x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
212
{
-
 
213
   alphagrad (outmatrix_ref (out, 6 - 1, 0), col, 1, 4);
-
 
214
   alphagrad (outmatrix_ref (out, 6 - 2, 2), col, 1, 4);
-
 
215
   alphagrad (outmatrix_ref (out, 6 - 3, 4), col, 1, 4);
-
 
216
   alphagrad (outmatrix_ref (out, 6 - 1, 1), col, 3, 4);
-
 
217
   alphagrad (outmatrix_ref (out, 6 - 2, 3), col, 3, 4);
-
 
218
   alphagrad (outmatrix_ref (out, 6 - 3, 5), col, 3, 4);
-
 
219
   *outmatrix_ref (out, 6 - 1, 2) = col;
-
 
220
   *outmatrix_ref (out, 6 - 1, 3) = col;
-
 
221
   *outmatrix_ref (out, 6 - 1, 4) = col;
-
 
222
   *outmatrix_ref (out, 6 - 1, 5) = col;
-
 
223
   *outmatrix_ref (out, 6 - 2, 4) = col;
-
 
224
   *outmatrix_ref (out, 6 - 2, 5) = col;
-
 
225
}
-
 
226
 
-
 
227
///////////////////////////////
-
 
228
// steep line scaling functions
-
 
229
 
-
 
230
static void blend_line_steep_2x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
231
{
-
 
232
   alphagrad (outmatrix_ref (out, 0, 2 - 1), col, 1, 4);
-
 
233
   alphagrad (outmatrix_ref (out, 1, 2 - 1), col, 3, 4);
-
 
234
}
-
 
235
static void blend_line_steep_3x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
236
{
-
 
237
   alphagrad (outmatrix_ref (out, 0, 3 - 1), col, 1, 4);
-
 
238
   alphagrad (outmatrix_ref (out, 2, 3 - 2), col, 1, 4);
-
 
239
   alphagrad (outmatrix_ref (out, 1, 3 - 1), col, 3, 4);
-
 
240
   *outmatrix_ref (out, 2, 3 - 1) = col;
-
 
241
}
-
 
242
static void blend_line_steep_4x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
243
{
-
 
244
   alphagrad (outmatrix_ref (out, 0, 4 - 1), col, 1, 4);
-
 
245
   alphagrad (outmatrix_ref (out, 2, 4 - 2), col, 1, 4);
-
 
246
   alphagrad (outmatrix_ref (out, 1, 4 - 1), col, 3, 4);
-
 
247
   alphagrad (outmatrix_ref (out, 3, 4 - 2), col, 3, 4);
-
 
248
   *outmatrix_ref (out, 2, 4 - 1) = col;
-
 
249
   *outmatrix_ref (out, 3, 4 - 1) = col;
-
 
250
}
-
 
251
static void blend_line_steep_5x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
252
{
-
 
253
   alphagrad (outmatrix_ref (out, 0, 5 - 1), col, 1, 4);
-
 
254
   alphagrad (outmatrix_ref (out, 2, 5 - 2), col, 1, 4);
-
 
255
   alphagrad (outmatrix_ref (out, 4, 5 - 3), col, 1, 4);
-
 
256
   alphagrad (outmatrix_ref (out, 1, 5 - 1), col, 3, 4);
-
 
257
   alphagrad (outmatrix_ref (out, 3, 5 - 2), col, 3, 4);
-
 
258
   *outmatrix_ref (out, 2, 5 - 1) = col;
-
 
259
   *outmatrix_ref (out, 3, 5 - 1) = col;
-
 
260
   *outmatrix_ref (out, 4, 5 - 1) = col;
-
 
261
   *outmatrix_ref (out, 4, 5 - 2) = col;
-
 
262
}
-
 
263
static void blend_line_steep_6x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
264
{
-
 
265
   alphagrad (outmatrix_ref (out, 0, 6 - 1), col, 1, 4);
-
 
266
   alphagrad (outmatrix_ref (out, 2, 6 - 2), col, 1, 4);
-
 
267
   alphagrad (outmatrix_ref (out, 4, 6 - 3), col, 1, 4);
-
 
268
   alphagrad (outmatrix_ref (out, 1, 6 - 1), col, 3, 4);
-
 
269
   alphagrad (outmatrix_ref (out, 3, 6 - 2), col, 3, 4);
-
 
270
   alphagrad (outmatrix_ref (out, 5, 6 - 3), col, 3, 4);
-
 
271
   *outmatrix_ref (out, 2, 6 - 1) = col;
-
 
272
   *outmatrix_ref (out, 3, 6 - 1) = col;
-
 
273
   *outmatrix_ref (out, 4, 6 - 1) = col;
-
 
274
   *outmatrix_ref (out, 5, 6 - 1) = col;
-
 
275
   *outmatrix_ref (out, 4, 6 - 2) = col;
-
 
276
   *outmatrix_ref (out, 5, 6 - 2) = col;
-
 
277
}
-
 
278
 
-
 
279
///////////////////////////////////////////
-
 
280
// steep and shallow line scaling functions
-
 
281
 
-
 
282
static void blend_line_steep_and_shallow_2x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
283
{
-
 
284
   alphagrad (outmatrix_ref (out, 1, 0), col, 1, 4);
-
 
285
   alphagrad (outmatrix_ref (out, 0, 1), col, 1, 4);
-
 
286
   alphagrad (outmatrix_ref (out, 1, 1), col, 5, 6); //[!] fixes 7/8 used in xBR
-
 
287
}
-
 
288
static void blend_line_steep_and_shallow_3x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
289
{
-
 
290
   alphagrad (outmatrix_ref (out, 2, 0), col, 1, 4);
-
 
291
   alphagrad (outmatrix_ref (out, 0, 2), col, 1, 4);
-
 
292
   alphagrad (outmatrix_ref (out, 2, 1), col, 3, 4);
-
 
293
   alphagrad (outmatrix_ref (out, 1, 2), col, 3, 4);
-
 
294
   *outmatrix_ref (out, 2, 2) = col;
-
 
295
}
-
 
296
static void blend_line_steep_and_shallow_4x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
297
{
-
 
298
   alphagrad (outmatrix_ref (out, 3, 1), col, 3, 4);
-
 
299
   alphagrad (outmatrix_ref (out, 1, 3), col, 3, 4);
-
 
300
   alphagrad (outmatrix_ref (out, 3, 0), col, 1, 4);
-
 
301
   alphagrad (outmatrix_ref (out, 0, 3), col, 1, 4);
-
 
302
   alphagrad (outmatrix_ref (out, 2, 2), col, 1, 3); //[!] fixes 1/4 used in xBR
-
 
303
   *outmatrix_ref (out, 3, 3) = col;
-
 
304
   *outmatrix_ref (out, 3, 2) = col;
-
 
305
   *outmatrix_ref (out, 2, 3) = col;
-
 
306
}
-
 
307
static void blend_line_steep_and_shallow_5x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
308
{
-
 
309
   alphagrad (outmatrix_ref (out, 0, 5 - 1), col, 1, 4);
-
 
310
   alphagrad (outmatrix_ref (out, 2, 5 - 2), col, 1, 4);
-
 
311
   alphagrad (outmatrix_ref (out, 1, 5 - 1), col, 3, 4);
-
 
312
   alphagrad (outmatrix_ref (out, 5 - 1, 0), col, 1, 4);
-
 
313
   alphagrad (outmatrix_ref (out, 5 - 2, 2), col, 1, 4);
-
 
314
   alphagrad (outmatrix_ref (out, 5 - 1, 1), col, 3, 4);
-
 
315
   alphagrad (outmatrix_ref (out, 3, 3), col, 2, 3);
-
 
316
   *outmatrix_ref (out, 2, 5 - 1) = col;
-
 
317
   *outmatrix_ref (out, 3, 5 - 1) = col;
-
 
318
   *outmatrix_ref (out, 4, 5 - 1) = col;
-
 
319
   *outmatrix_ref (out, 5 - 1, 2) = col;
-
 
320
   *outmatrix_ref (out, 5 - 1, 3) = col;
-
 
321
}
-
 
322
static void blend_line_steep_and_shallow_6x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
323
{
-
 
324
   alphagrad (outmatrix_ref (out, 0, 6 - 1), col, 1, 4);
-
 
325
   alphagrad (outmatrix_ref (out, 2, 6 - 2), col, 1, 4);
-
 
326
   alphagrad (outmatrix_ref (out, 1, 6 - 1), col, 3, 4);
-
 
327
   alphagrad (outmatrix_ref (out, 3, 6 - 2), col, 3, 4);
-
 
328
   alphagrad (outmatrix_ref (out, 6 - 1, 0), col, 1, 4);
-
 
329
   alphagrad (outmatrix_ref (out, 6 - 2, 2), col, 1, 4);
-
 
330
   alphagrad (outmatrix_ref (out, 6 - 1, 1), col, 3, 4);
-
 
331
   alphagrad (outmatrix_ref (out, 6 - 2, 3), col, 3, 4);
-
 
332
   *outmatrix_ref (out, 2, 6 - 1) = col;
-
 
333
   *outmatrix_ref (out, 3, 6 - 1) = col;
-
 
334
   *outmatrix_ref (out, 4, 6 - 1) = col;
-
 
335
   *outmatrix_ref (out, 5, 6 - 1) = col;
-
 
336
   *outmatrix_ref (out, 4, 6 - 2) = col;
-
 
337
   *outmatrix_ref (out, 5, 6 - 2) = col;
-
 
338
   *outmatrix_ref (out, 6 - 1, 2) = col;
-
 
339
   *outmatrix_ref (out, 6 - 1, 3) = col;
-
 
340
}
-
 
341
 
-
 
342
//////////////////////////////////
-
 
343
// diagonal line scaling functions
-
 
344
 
-
 
345
static void blend_line_diagonal_2x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
346
{
-
 
347
   alphagrad (outmatrix_ref (out, 1, 1), col, 1, 2);
-
 
348
}
-
 
349
static void blend_line_diagonal_3x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
350
{
-
 
351
   alphagrad (outmatrix_ref (out, 1, 2), col, 1, 8); //conflict with other rotations for this odd scale
-
 
352
   alphagrad (outmatrix_ref (out, 2, 1), col, 1, 8);
-
 
353
   alphagrad (outmatrix_ref (out, 2, 2), col, 7, 8); //
-
 
354
}
-
 
355
static void blend_line_diagonal_4x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
356
{
-
 
357
   alphagrad (outmatrix_ref (out, 4 - 1, 4 / 2), col, 1, 2);
-
 
358
   alphagrad (outmatrix_ref (out, 4 - 2, 4 / 2 + 1), col, 1, 2);
-
 
359
   *outmatrix_ref (out, 4 - 1, 4 - 1) = col;
-
 
360
}
-
 
361
static void blend_line_diagonal_5x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
362
{
-
 
363
   alphagrad (outmatrix_ref (out, 5 - 1, 5 / 2 + 0), col, 1, 8); //conflict with other rotations for this odd scale
-
 
364
   alphagrad (outmatrix_ref (out, 5 - 2, 5 / 2 + 1), col, 1, 8);
-
 
365
   alphagrad (outmatrix_ref (out, 5 - 3, 5 / 2 + 2), col, 1, 8); //
-
 
366
   alphagrad (outmatrix_ref (out, 4, 3), col, 7, 8);
-
 
367
   alphagrad (outmatrix_ref (out, 3, 4), col, 7, 8);
-
 
368
   *outmatrix_ref (out, 4, 4) = col;
-
 
369
}
-
 
370
static void blend_line_diagonal_6x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
371
{
-
 
372
   alphagrad (outmatrix_ref (out, 6 - 1, 6 / 2 + 0), col, 1, 2);
-
 
373
   alphagrad (outmatrix_ref (out, 6 - 2, 6 / 2 + 1), col, 1, 2);
-
 
374
   alphagrad (outmatrix_ref (out, 6 - 3, 6 / 2 + 2), col, 1, 2);
-
 
375
   *outmatrix_ref (out, 6 - 2, 6 - 1) = col;
-
 
376
   *outmatrix_ref (out, 6 - 1, 6 - 1) = col;
-
 
377
   *outmatrix_ref (out, 6 - 1, 6 - 2) = col;
-
 
378
}
-
 
379
 
-
 
380
///////////////////////////
-
 
381
// corner scaling functions
-
 
382
 
-
 
383
static void blend_corner_2x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
384
{
-
 
385
   //model a round corner
-
 
386
   alphagrad (outmatrix_ref (out, 1, 1), col, 21, 100); //exact: 1 - pi/4 = 0.2146018366
-
 
387
}
-
 
388
static void blend_corner_3x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
389
{
-
 
390
   //model a round corner
-
 
391
   alphagrad (outmatrix_ref (out, 2, 2), col, 45, 100); //exact: 0.4545939598
-
 
392
   //alphagrad (outmatrix_ref (out, 2, 1), col, 7, 256); //0.02826017254 -> negligible + avoid conflicts with other rotations for this odd scale
-
 
393
   //alphagrad (outmatrix_ref (out, 1, 2), col, 7, 256); //0.02826017254
-
 
394
}
-
 
395
static void blend_corner_4x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
396
{
-
 
397
   //model a round corner
-
 
398
   alphagrad (outmatrix_ref (out, 3, 3), col, 68, 100); //exact: 0.6848532563
-
 
399
   alphagrad (outmatrix_ref (out, 3, 2), col, 9, 100); //0.08677704501
-
 
400
   alphagrad (outmatrix_ref (out, 2, 3), col, 9, 100); //0.08677704501
-
 
401
}
-
 
402
static void blend_corner_5x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
403
{
-
 
404
   // model a round corner
-
 
405
   alphagrad (outmatrix_ref (out, 4, 4), col, 86, 100); //exact: 0.8631434088
-
 
406
   alphagrad (outmatrix_ref (out, 4, 3), col, 23, 100); //0.2306749731
-
 
407
   alphagrad (outmatrix_ref (out, 3, 4), col, 23, 100); //0.2306749731
-
 
408
   //alphagrad (outmatrix_ref (out, 4, 2), col, 1, 64); //0.01676812367 -> negligible + avoid conflicts with other rotations for this odd scale
-
 
409
   //alphagrad (outmatrix_ref (out, 2, 4), col, 1, 64); //0.01676812367
-
 
410
}
-
 
411
static void blend_corner_6x (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
412
{
-
 
413
   //model a round corner
-
 
414
   alphagrad (outmatrix_ref (out, 5, 5), col, 97, 100); //exact: 0.9711013910
-
 
415
   alphagrad (outmatrix_ref (out, 4, 5), col, 42, 100); //0.4236372243
-
 
416
   alphagrad (outmatrix_ref (out, 5, 4), col, 42, 100); //0.4236372243
-
 
417
   alphagrad (outmatrix_ref (out, 5, 3), col, 6, 100); //0.05652034508
-
 
418
   alphagrad (outmatrix_ref (out, 3, 5), col, 6, 100); //0.05652034508
-
 
419
}
-
 
420
 
-
 
421
/////////////////////////////////////
-
 
422
// scaler objects for various factors
-
 
423
 
-
 
424
static const scaler_t scalers[] =
-
 
425
{
-
 
426
   { 2, blend_line_shallow_2x, blend_line_steep_2x, blend_line_steep_and_shallow_2x, blend_line_diagonal_2x, blend_corner_2x },
-
 
427
   { 3, blend_line_shallow_3x, blend_line_steep_3x, blend_line_steep_and_shallow_3x, blend_line_diagonal_3x, blend_corner_3x },
-
 
428
   { 4, blend_line_shallow_4x, blend_line_steep_4x, blend_line_steep_and_shallow_4x, blend_line_diagonal_4x, blend_corner_4x },
-
 
429
   { 5, blend_line_shallow_5x, blend_line_steep_5x, blend_line_steep_and_shallow_5x, blend_line_diagonal_5x, blend_corner_5x },
-
 
430
   { 6, blend_line_shallow_6x, blend_line_steep_6x, blend_line_steep_and_shallow_6x, blend_line_diagonal_6x, blend_corner_6x },
-
 
431
};
172
 
432
 
173
 
433
 
174
static FORCE_INLINE void preProcessCorners (blendresult_t *result, const kernel_4x4_t *ker, dist_func dist)
434
static FORCE_INLINE void preProcessCorners (blendresult_t *result, const kernel_4x4_t *ker, dist_func dist)
175
{
435
{
176
   // detect blend direction
436
   // detect blend direction
Line 216... Line 476...
216
   }
476
   }
217
   return;
477
   return;
218
}
478
}
219
 
479
 
220
// compress four blend types into a single byte
480
// compress four blend types into a single byte
221
static inline BlendType getTopL (unsigned char b) { return (BlendType) (0x3 & (b >> 0)); }
481
#define getTopL(b)    ((BlendType) (0x3 & ((unsigned char) (b) >> 0)))
222
static inline BlendType getTopR (unsigned char b) { return (BlendType) (0x3 & (b >> 2)); }
482
#define getTopR(b)    ((BlendType) (0x3 & ((unsigned char) (b) >> 2)))
223
static inline BlendType getBottomR (unsigned char b) { return (BlendType) (0x3 & (b >> 4)); }
483
#define getBottomR(b) ((BlendType) (0x3 & ((unsigned char) (b) >> 4)))
224
static inline BlendType getBottomL (unsigned char b) { return (BlendType) (0x3 & (b >> 6)); }
484
#define getBottomL(b) ((BlendType) (0x3 & ((unsigned char) (b) >> 6)))
225
 
485
 
226
static inline void setTopL (unsigned char& b, BlendType bt) { b |= bt; } //buffer is assumed to be initialized before preprocessing!
486
static inline void setTopL (unsigned char& b, BlendType bt) { b |= (((BlendType) (bt)) << 0); } //buffer is assumed to be initialized before preprocessing!
227
static inline void setTopR (unsigned char& b, BlendType bt) { b |= (bt << 2); }
487
static inline void setTopR (unsigned char& b, BlendType bt) { b |= (((BlendType) (bt)) << 2); }
228
static inline void setBottomR (unsigned char& b, BlendType bt) { b |= (bt << 4); }
488
static inline void setBottomR (unsigned char& b, BlendType bt) { b |= (((BlendType) (bt)) << 4); }
229
static inline void setBottomL (unsigned char& b, BlendType bt) { b |= (bt << 6); }
489
static inline void setBottomL (unsigned char& b, BlendType bt) { b |= (((BlendType) (bt)) << 6); }
230
 
490
 
231
 
491
 
232
namespace
-
 
-
 
492
FORCE_INLINE void blend_pixel (const scaler_t *scaler, const kernel_3x3_t *ker, uint32_t *target, int trgWidth, unsigned char blendInfo, alphagrad_func alphagrad, dist_func dist, int rotDeg) //result of preprocessing all four corners of pixel "e"
233
{
493
{
-
 
494
   // input kernel area naming convention:
-
 
495
   // -------------
-
 
496
   // | A | B | C |
-
 
497
   // ----|---|---|
-
 
498
   // | D | E | F | //input pixel is at position E
-
 
499
   // ----|---|---|
-
 
500
   // | G | H | I |
-
 
501
   // -------------
234
 
502
 
-
 
503
   uint32_t
-
 
504
      a, b, c,
-
 
505
      d, e, f,
-
 
506
      g, h, i;
-
 
507
   unsigned char blend;
235
 
508
 
-
 
509
   if      (rotDeg == 270) { a = ker->c; b = ker->f; c = ker->i; d = ker->b; e = ker->e; f = ker->h; g = ker->a; h = ker->d; i = ker->g; blend = ((blendInfo << 6) | (blendInfo >> 2)) & 0xff; }
-
 
510
   else if (rotDeg == 180) { a = ker->i; b = ker->h; c = ker->g; d = ker->f; e = ker->e; f = ker->d; g = ker->c; h = ker->b; i = ker->a; blend = ((blendInfo << 4) | (blendInfo >> 4)) & 0xff; }
-
 
511
   else if (rotDeg == 90)  { a = ker->g; b = ker->d; c = ker->a; d = ker->h; e = ker->e; f = ker->b; g = ker->i; h = ker->f; i = ker->c; blend = ((blendInfo << 2) | (blendInfo >> 6)) & 0xff; }
-
 
512
   else                    { a = ker->a; b = ker->b; c = ker->c; d = ker->d; e = ker->e; f = ker->f; g = ker->g; h = ker->h; i = ker->i; blend = ((blendInfo << 0) | (blendInfo >> 8)) & 0xff; }
236
 
513
 
237
 
-
 
238
   template <class Scaler>
-
 
239
   FORCE_INLINE void blendPixel (const int scale_factor, const kernel_3x3_t *ker, uint32_t *target, int trgWidth, unsigned char blendInfo, alphagrad_func alphagrad, dist_func dist, RotationDegree rotDeg) //result of preprocessing all four corners of pixel "e"
514
   if (getBottomR (blend) >= BLEND_NORMAL)
240
   {
515
   {
241
      // input kernel area naming convention:
-
 
242
      // -------------
516
      outmatrix_t out;
243
      // | A | B | C |
517
      uint32_t px;
244
      // ----|---|---|
-
 
245
      // | D | E | F | //input pixel is at position E
-
 
246
      // ----|---|---|
-
 
247
      // | G | H | I |
518
      bool doLineBlend;
248
      // -------------
-
 
249
 
519
 
250
      uint32_t
520
      if (getBottomR (blend) >= BLEND_DOMINANT)
251
         a, b, c,
521
         doLineBlend = true;
-
 
522
      else if (getTopR (blend) != BLEND_NONE && (dist (e, g) >= XBRZ_CFG_EQUAL_COLOR_TOLERANCE)) //but support double-blending for 90° corners
-
 
523
         doLineBlend = false; // make sure there is no second blending in an adjacent rotation for this pixel: handles insular pixels, mario eyes
-
 
524
      else if (getBottomL (blend) != BLEND_NONE && (dist (e, c) >= XBRZ_CFG_EQUAL_COLOR_TOLERANCE))
-
 
525
         doLineBlend = false; // make sure there is no second blending in an adjacent rotation for this pixel: handles insular pixels, mario eyes
-
 
526
      else if ((dist (e, i) >= XBRZ_CFG_EQUAL_COLOR_TOLERANCE)
-
 
527
         && (dist (g, h) < XBRZ_CFG_EQUAL_COLOR_TOLERANCE)
-
 
528
         && (dist (h, i) < XBRZ_CFG_EQUAL_COLOR_TOLERANCE)
252
         d, e, f,
529
         && (dist (i, f) < XBRZ_CFG_EQUAL_COLOR_TOLERANCE)
-
 
530
         && (dist (f, c) < XBRZ_CFG_EQUAL_COLOR_TOLERANCE))
-
 
531
         doLineBlend = false; // no full blending for L-shapes; blend corner only (handles "mario mushroom eyes")
253
         g, h, i;
532
      else
254
      unsigned char blend;
533
         doLineBlend = true;
255
 
534
 
256
      if      (rotDeg == ROT_270) { a = ker->c; b = ker->f; c = ker->i; d = ker->b; e = ker->e; f = ker->h; g = ker->a; h = ker->d; i = ker->g; blend = ((blendInfo << 6) | (blendInfo >> 2)) & 0xff; }
-
 
257
      else if (rotDeg == ROT_180) { a = ker->i; b = ker->h; c = ker->g; d = ker->f; e = ker->e; f = ker->d; g = ker->c; h = ker->b; i = ker->a; blend = ((blendInfo << 4) | (blendInfo >> 4)) & 0xff; }
535
      outmatrix_create (&out, scaler->factor, target, trgWidth, rotDeg);
258
      else if (rotDeg == ROT_90)  { a = ker->g; b = ker->d; c = ker->a; d = ker->h; e = ker->e; f = ker->b; g = ker->i; h = ker->f; i = ker->c; blend = ((blendInfo << 2) | (blendInfo >> 6)) & 0xff; }
536
      px = (dist (e, f) <= dist (e, h) ? f : h); //choose most similar color
259
      else                        { a = ker->a; b = ker->b; c = ker->c; d = ker->d; e = ker->e; f = ker->f; g = ker->g; h = ker->h; i = ker->i; blend = ((blendInfo << 0) | (blendInfo >> 8)) & 0xff; }
-
 
260
 
537
 
261
      if (getBottomR (blend) >= BLEND_NORMAL)
538
      if (doLineBlend)
262
      {
539
      {
-
 
540
         const double fg = dist (f, g); //test sample: 70% of values max(fg, hc) / min(fg, hc) are between 1.1 and 3.7 with median being 1.9
263
         outmatrix_t out;
541
         const double hc = dist (h, c); //
264
         uint32_t px;
542
         const bool haveShallowLine = (XBRZ_CFG_STEEP_DIRECTION_THRESHOLD * fg <= hc) && (e != g) && (d != g);
265
         bool doLineBlend;
543
         const bool haveSteepLine   = (XBRZ_CFG_STEEP_DIRECTION_THRESHOLD * hc <= fg) && (e != c) && (b != c);
266
 
544
 
267
         if (getBottomR (blend) >= BLEND_DOMINANT)
545
         if (haveShallowLine)
268
            doLineBlend = true;
546
         {
269
         else if (getTopR (blend) != BLEND_NONE && (dist (e, g) >= XBRZ_CFG_EQUAL_COLOR_TOLERANCE)) //but support double-blending for 90° corners
-
 
270
            doLineBlend = false; // make sure there is no second blending in an adjacent rotation for this pixel: handles insular pixels, mario eyes
-
 
271
         else if (getBottomL (blend) != BLEND_NONE && (dist (e, c) >= XBRZ_CFG_EQUAL_COLOR_TOLERANCE))
-
 
272
            doLineBlend = false; // make sure there is no second blending in an adjacent rotation for this pixel: handles insular pixels, mario eyes
-
 
273
         else if ((dist (e, i) >= XBRZ_CFG_EQUAL_COLOR_TOLERANCE)
547
            if (haveSteepLine)
274
            && (dist (g, h) < XBRZ_CFG_EQUAL_COLOR_TOLERANCE)
548
               scaler->blend_line_steep_and_shallow (px, &out, alphagrad);
275
            && (dist (h, i) < XBRZ_CFG_EQUAL_COLOR_TOLERANCE)
549
            else
276
            && (dist (i, f) < XBRZ_CFG_EQUAL_COLOR_TOLERANCE)
550
               scaler->blend_line_shallow (px, &out, alphagrad);
277
            && (dist (f, c) < XBRZ_CFG_EQUAL_COLOR_TOLERANCE))
551
         }
278
            doLineBlend = false; // no full blending for L-shapes; blend corner only (handles "mario mushroom eyes")
-
 
279
         else
552
         else
280
            doLineBlend = true;
-
 
281
 
-
 
282
         outmatrix_create (&out, scale_factor, target, trgWidth, rotDeg);
-
 
283
         px = (dist (e, f) <= dist (e, h) ? f : h); //choose most similar color
-
 
284
 
-
 
285
         if (doLineBlend)
-
 
286
         {
553
         {
287
            const double fg = dist (f, g); //test sample: 70% of values max(fg, hc) / min(fg, hc) are between 1.1 and 3.7 with median being 1.9
-
 
288
            const double hc = dist (h, c); //
-
 
289
            const bool haveShallowLine = (XBRZ_CFG_STEEP_DIRECTION_THRESHOLD * fg <= hc) && (e != g) && (d != g);
-
 
290
            const bool haveSteepLine   = (XBRZ_CFG_STEEP_DIRECTION_THRESHOLD * hc <= fg) && (e != c) && (b != c);
-
 
291
 
-
 
292
            if (haveShallowLine)
-
 
293
            {
-
 
294
               if (haveSteepLine)
554
            if (haveSteepLine)
295
                  Scaler::blendLineSteepAndShallow (px, &out, alphagrad);
-
 
296
               else
-
 
297
                  Scaler::blendLineShallow (px, &out, alphagrad);
555
               scaler->blend_line_steep (px, &out, alphagrad);
298
            }
-
 
299
            else
556
            else
300
            {
-
 
301
               if (haveSteepLine)
-
 
302
                  Scaler::blendLineSteep (px, &out, alphagrad);
-
 
303
               else
-
 
304
                  Scaler::blendLineDiagonal (px, &out, alphagrad);
557
               scaler->blend_line_diagonal (px, &out, alphagrad);
305
            }
-
 
306
         }
558
         }
307
         else
-
 
308
            Scaler::blendCorner (px, &out, alphagrad);
-
 
309
      }
559
      }
-
 
560
      else
-
 
561
         scaler->blend_corner (px, &out, alphagrad);
310
   }
562
   }
-
 
563
}
311
 
564
 
312
 
565
 
313
   template <class Scaler> //scaler policy: see "Scaler2x" reference implementation
-
 
314
   void scaleImage (const uint32_t *src, uint32_t *trg, int srcWidth, int srcHeight, int yFirst, int yLast, alphagrad_func alphagrad, dist_func dist)
566
void scale_image (const scaler_t *scaler, const uint32_t *src, uint32_t *trg, int srcWidth, int srcHeight, int yFirst, int yLast, alphagrad_func alphagrad, dist_func dist)
315
   {
567
{
316
      yFirst = MAX (yFirst, 0);
568
   yFirst = MAX (yFirst, 0);
317
      yLast = MIN (yLast, srcHeight);
569
   yLast = MIN (yLast, srcHeight);
318
      if (yFirst >= yLast || srcWidth <= 0)
570
   if (yFirst >= yLast || srcWidth <= 0)
319
         return;
571
      return;
320
 
572
 
321
      const int trgWidth = srcWidth * Scaler::scale;
573
   const int trgWidth = srcWidth * scaler->factor;
322
 
574
 
323
      //"use" space at the end of the image as temporary buffer for "on the fly preprocessing": we even could use larger area of
575
   //"use" space at the end of the image as temporary buffer for "on the fly preprocessing": we even could use larger area of
324
      //"sizeof(uint32_t) * srcWidth * (yLast - yFirst)" bytes without risk of accidental overwriting before accessing
576
   //"sizeof(uint32_t) * srcWidth * (yLast - yFirst)" bytes without risk of accidental overwriting before accessing
325
      const int bufferSize = srcWidth;
577
   const int bufferSize = srcWidth;
326
      unsigned char* preProcBuffer = reinterpret_cast<unsigned char*>(trg + yLast * Scaler::scale * trgWidth) - bufferSize;
578
   unsigned char *preProcBuffer = (unsigned char *) (trg + yLast * scaler->factor * trgWidth) - bufferSize;
327
      memset (preProcBuffer, 0, bufferSize);
579
   memset (preProcBuffer, 0, bufferSize);
328
      static_assert(BLEND_NONE == 0, "");
580
   static_assert(BLEND_NONE == 0, "");
329
 
581
 
330
      //initialize preprocessing buffer for first row of current stripe: detect upper left and right corner blending
582
   //initialize preprocessing buffer for first row of current stripe: detect upper left and right corner blending
331
      //this cannot be optimized for adjacent processing stripes; we must not allow for a memory race condition!
583
   //this cannot be optimized for adjacent processing stripes; we must not allow for a memory race condition!
332
      if (yFirst > 0)
584
   if (yFirst > 0)
333
      {
585
   {
334
         const int y = yFirst - 1;
586
      const int y = yFirst - 1;
335
 
587
 
336
         const uint32_t* s_m1 = src + srcWidth * MAX (y - 1, 0);
588
      const uint32_t* s_m1 = src + srcWidth * MAX (y - 1, 0);
337
         const uint32_t* s_0 = src + srcWidth * y; //center line
589
      const uint32_t* s_0 = src + srcWidth * y; //center line
338
         const uint32_t* s_p1 = src + srcWidth * MIN (y + 1, srcHeight - 1);
590
      const uint32_t* s_p1 = src + srcWidth * MIN (y + 1, srcHeight - 1);
339
         const uint32_t* s_p2 = src + srcWidth * MIN (y + 2, srcHeight - 1);
591
      const uint32_t* s_p2 = src + srcWidth * MIN (y + 2, srcHeight - 1);
340
 
-
 
341
         for (int x = 0; x < srcWidth; ++x)
-
 
342
         {
-
 
343
            blendresult_t res;
-
 
344
            const int x_m1 = MAX (x - 1, 0);
-
 
345
            const int x_p1 = MIN (x + 1, srcWidth - 1);
-
 
346
            const int x_p2 = MIN (x + 2, srcWidth - 1);
-
 
347
 
-
 
348
            kernel_4x4_t ker; //perf: initialization is negligible
-
 
349
            ker.a = s_m1[x_m1]; //read sequentially from memory as far as possible
-
 
350
            ker.b = s_m1[x];
-
 
351
            ker.c = s_m1[x_p1];
-
 
352
            ker.d = s_m1[x_p2];
-
 
353
 
-
 
354
            ker.e = s_0[x_m1];
-
 
355
            ker.f = s_0[x];
-
 
356
            ker.g = s_0[x_p1];
-
 
357
            ker.h = s_0[x_p2];
-
 
358
 
-
 
359
            ker.i = s_p1[x_m1];
-
 
360
            ker.j = s_p1[x];
-
 
361
            ker.k = s_p1[x_p1];
-
 
362
            ker.l = s_p1[x_p2];
-
 
363
 
-
 
364
            ker.m = s_p2[x_m1];
-
 
365
            ker.n = s_p2[x];
-
 
366
            ker.o = s_p2[x_p1];
-
 
367
            ker.p = s_p2[x_p2];
-
 
368
 
-
 
369
            preProcessCorners (&res, &ker, dist);
-
 
370
            /*
-
 
371
            preprocessing blend result:
-
 
372
            ---------
-
 
373
            | F | G |   //evalute corner between F, G, J, K
-
 
374
            ----|---|   //input pixel is at position F
-
 
375
            | J | K |
-
 
376
            ---------
-
 
377
            */
-
 
378
            setTopR (preProcBuffer[x], res.blend_j);
-
 
379
 
-
 
380
            if (x + 1 < bufferSize)
-
 
381
               setTopL (preProcBuffer[x + 1], res.blend_k);
-
 
382
         }
-
 
383
      }
-
 
384
      //------------------------------------------------------------------------------------
-
 
385
 
592
 
386
      for (int y = yFirst; y < yLast; ++y)
593
      for (int x = 0; x < srcWidth; ++x)
387
      {
594
      {
-
 
595
         blendresult_t res;
-
 
596
         const int x_m1 = MAX (x - 1, 0);
-
 
597
         const int x_p1 = MIN (x + 1, srcWidth - 1);
388
         uint32_t *out = trg + Scaler::scale * y * trgWidth; //consider MT "striped" access
598
         const int x_p2 = MIN (x + 2, srcWidth - 1);
389
 
599
 
390
         const uint32_t* s_m1 = src + srcWidth * MAX (y - 1, 0);
600
         kernel_4x4_t ker; //perf: initialization is negligible
391
         const uint32_t* s_0 = src + srcWidth * y; //center line
601
         ker.a = s_m1[x_m1]; //read sequentially from memory as far as possible
-
 
602
         ker.b = s_m1[x];
392
         const uint32_t* s_p1 = src + srcWidth * MIN (y + 1, srcHeight - 1);
603
         ker.c = s_m1[x_p1];
393
         const uint32_t* s_p2 = src + srcWidth * MIN (y + 2, srcHeight - 1);
604
         ker.d = s_m1[x_p2];
394
 
605
 
395
         unsigned char blend_xy1 = 0; //corner blending for current (x, y + 1) position
606
         ker.e = s_0[x_m1];
-
 
607
         ker.f = s_0[x];
-
 
608
         ker.g = s_0[x_p1];
-
 
609
         ker.h = s_0[x_p2];
396
 
610
 
397
         for (int x = 0; x < srcWidth; ++x, out += Scaler::scale)
611
         ker.i = s_p1[x_m1];
398
         {
612
         ker.j = s_p1[x];
399
            //all those bounds checks have only insignificant impact on performance!
-
 
400
            const int x_m1 = MAX (x - 1, 0); //perf: prefer array indexing to additional pointers!
-
 
401
            const int x_p1 = MIN (x + 1, srcWidth - 1);
613
         ker.k = s_p1[x_p1];
402
            const int x_p2 = MIN (x + 2, srcWidth - 1);
614
         ker.l = s_p1[x_p2];
403
            kernel_4x4_t ker4; //perf: initialization is negligible
-
 
404
 
615
 
405
            ker4.a = s_m1[x_m1]; //read sequentially from memory as far as possible
616
         ker.m = s_p2[x_m1];
406
            ker4.b = s_m1[x];
617
         ker.n = s_p2[x];
407
            ker4.c = s_m1[x_p1];
618
         ker.o = s_p2[x_p1];
408
            ker4.d = s_m1[x_p2];
619
         ker.p = s_p2[x_p2];
409
 
620
 
-
 
621
         preProcessCorners (&res, &ker, dist);
-
 
622
         /*
410
            ker4.e = s_0[x_m1];
623
         preprocessing blend result:
-
 
624
         ---------
-
 
625
         | F | G |   //evalute corner between F, G, J, K
-
 
626
         ----|---|   //input pixel is at position F
411
            ker4.f = s_0[x];
627
         | J | K |
412
            ker4.g = s_0[x_p1];
628
         ---------
-
 
629
         */
413
            ker4.h = s_0[x_p2];
630
         setTopR (preProcBuffer[x], res.blend_j);
414
 
631
 
415
            ker4.i = s_p1[x_m1];
-
 
416
            ker4.j = s_p1[x];
-
 
417
            ker4.k = s_p1[x_p1];
-
 
418
            ker4.l = s_p1[x_p2];
632
         if (x + 1 < bufferSize)
419
 
-
 
420
            ker4.m = s_p2[x_m1];
-
 
421
            ker4.n = s_p2[x];
-
 
422
            ker4.o = s_p2[x_p1];
-
 
423
            ker4.p = s_p2[x_p2];
-
 
424
 
-
 
425
            //evaluate the four corners on bottom-right of current pixel
-
 
426
            unsigned char blend_xy = 0; //for current (x, y) position
-
 
427
            {
-
 
428
               blendresult_t res;
-
 
429
               preProcessCorners (&res, &ker4, dist);
-
 
430
               /*
-
 
431
               preprocessing blend result:
-
 
432
               ---------
-
 
433
               | F | G |   //evalute corner between F, G, J, K
-
 
434
               ----|---|   //current input pixel is at position F
-
 
435
               | J | K |
-
 
436
               ---------
-
 
437
               */
-
 
438
               blend_xy = preProcBuffer[x];
-
 
439
               setBottomR (blend_xy, res.blend_f); //all four corners of (x, y) have been determined at this point due to processing sequence!
-
 
440
 
-
 
441
               setTopR (blend_xy1, res.blend_j); //set 2nd known corner for (x, y + 1)
-
 
442
               preProcBuffer[x] = blend_xy1; //store on current buffer position for use on next row
-
 
443
 
-
 
444
               blend_xy1 = 0;
-
 
445
               setTopL (blend_xy1, res.blend_k); //set 1st known corner for (x + 1, y + 1) and buffer for use on next column
-
 
446
 
-
 
447
               if (x + 1 < bufferSize) //set 3rd known corner for (x + 1, y)
-
 
448
                  setBottomL (preProcBuffer[x + 1], res.blend_g);
633
            setTopL (preProcBuffer[x + 1], res.blend_k);
449
            }
-
 
450
 
-
 
451
            //fill block of size scale * scale with the given color
-
 
452
            {
-
 
453
               uint32_t *blk = out;
-
 
454
               for (int _blk_y = 0; _blk_y < Scaler::scale; ++_blk_y, blk = (uint32_t *) BYTE_ADVANCE (blk, trgWidth * sizeof (uint32_t)))
-
 
455
                  for (int _blk_x = 0; _blk_x < Scaler::scale; ++_blk_x)
-
 
456
                     blk[_blk_x] = ker4.f;
-
 
457
            }
-
 
458
            //place *after* preprocessing step, to not overwrite the results while processing the the last pixel!
-
 
459
 
-
 
460
            //blend four corners of current pixel
-
 
461
            if (blend_xy != 0) //good 5% perf-improvement
-
 
462
            {
-
 
463
               kernel_3x3_t ker3; //perf: initialization is negligible
-
 
464
 
-
 
465
               ker3.a = ker4.a;
-
 
466
               ker3.b = ker4.b;
-
 
467
               ker3.c = ker4.c;
-
 
468
 
-
 
469
               ker3.d = ker4.e;
-
 
470
               ker3.e = ker4.f;
-
 
471
               ker3.f = ker4.g;
-
 
472
 
-
 
473
               ker3.g = ker4.i;
-
 
474
               ker3.h = ker4.j;
-
 
475
               ker3.i = ker4.k;
-
 
476
 
-
 
477
               blendPixel<Scaler> (Scaler::scale, &ker3, out, trgWidth, blend_xy, alphagrad, dist, ROT_0);
-
 
478
               blendPixel<Scaler> (Scaler::scale, &ker3, out, trgWidth, blend_xy, alphagrad, dist, ROT_90);
-
 
479
               blendPixel<Scaler> (Scaler::scale, &ker3, out, trgWidth, blend_xy, alphagrad, dist, ROT_180);
-
 
480
               blendPixel<Scaler> (Scaler::scale, &ker3, out, trgWidth, blend_xy, alphagrad, dist, ROT_270);
-
 
481
            }
-
 
482
         }
-
 
483
      }
634
      }
484
   }
635
   }
485
 
-
 
486
 
-
 
487
   //------------------------------------------------------------------------------------
636
   //------------------------------------------------------------------------------------
488
   struct Scaler2x
-
 
489
   {
-
 
490
      static const int scale = 2;
-
 
491
 
637
 
492
 
-
 
493
      static void blendLineShallow (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
494
      {
-
 
495
         alphagrad (outmatrix_ref (out, scale - 1, 0), col, 1, 4);
-
 
496
         alphagrad (outmatrix_ref (out, scale - 1, 1), col, 3, 4);
-
 
497
      }
-
 
498
 
-
 
499
      static void blendLineSteep (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
500
      {
-
 
501
         alphagrad (outmatrix_ref (out, 0, scale - 1), col, 1, 4);
-
 
502
         alphagrad (outmatrix_ref (out, 1, scale - 1), col, 3, 4);
-
 
503
      }
-
 
504
 
-
 
505
      static void blendLineSteepAndShallow (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
506
      {
-
 
507
         alphagrad (outmatrix_ref (out, 1, 0), col, 1, 4);
-
 
508
         alphagrad (outmatrix_ref (out, 0, 1), col, 1, 4);
-
 
509
         alphagrad (outmatrix_ref (out, 1, 1), col, 5, 6); //[!] fixes 7/8 used in xBR
-
 
510
      }
-
 
511
 
-
 
512
      static void blendLineDiagonal (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
513
      {
-
 
514
         alphagrad (outmatrix_ref (out, 1, 1), col, 1, 2);
-
 
515
      }
-
 
516
 
-
 
517
      static void blendCorner (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
518
      {
-
 
519
         //model a round corner
638
   for (int y = yFirst; y < yLast; ++y)
520
         alphagrad (outmatrix_ref (out, 1, 1), col, 21, 100); //exact: 1 - pi/4 = 0.2146018366
-
 
521
      }
-
 
522
   };
-
 
523
 
-
 
524
 
-
 
525
   struct Scaler3x
-
 
526
   {
639
   {
527
      static const int scale = 3;
640
      uint32_t *out = trg + scaler->factor * y * trgWidth; //consider MT "striped" access
528
 
641
 
-
 
642
      const uint32_t* s_m1 = src + srcWidth * MAX (y - 1, 0);
-
 
643
      const uint32_t* s_0 = src + srcWidth * y; //center line
-
 
644
      const uint32_t* s_p1 = src + srcWidth * MIN (y + 1, srcHeight - 1);
-
 
645
      const uint32_t* s_p2 = src + srcWidth * MIN (y + 2, srcHeight - 1);
529
 
646
 
530
      static void blendLineShallow (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
647
      unsigned char blend_xy1 = 0; //corner blending for current (x, y + 1) position
531
      {
-
 
532
         alphagrad (outmatrix_ref (out, scale - 1, 0), col, 1, 4);
-
 
533
         alphagrad (outmatrix_ref (out, scale - 2, 2), col, 1, 4);
-
 
534
         alphagrad (outmatrix_ref (out, scale - 1, 1), col, 3, 4);
-
 
535
         *outmatrix_ref (out, scale - 1, 2) = col;
-
 
536
      }
-
 
537
 
648
 
538
      static void blendLineSteep (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
649
      for (int x = 0; x < srcWidth; ++x, out += scaler->factor)
539
      {
650
      {
540
         alphagrad (outmatrix_ref (out, 0, scale - 1), col, 1, 4);
651
         //all those bounds checks have only insignificant impact on performance!
541
         alphagrad (outmatrix_ref (out, 2, scale - 2), col, 1, 4);
652
         const int x_m1 = MAX (x - 1, 0); //perf: prefer array indexing to additional pointers!
542
         alphagrad (outmatrix_ref (out, 1, scale - 1), col, 3, 4);
653
         const int x_p1 = MIN (x + 1, srcWidth - 1);
543
         *outmatrix_ref (out, 2, scale - 1) = col;
654
         const int x_p2 = MIN (x + 2, srcWidth - 1);
544
      }
655
         kernel_4x4_t ker4; //perf: initialization is negligible
545
 
656
 
546
      static void blendLineSteepAndShallow (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
547
      {
-
 
548
         alphagrad (outmatrix_ref (out, 2, 0), col, 1, 4);
657
         ker4.a = s_m1[x_m1]; //read sequentially from memory as far as possible
549
         alphagrad (outmatrix_ref (out, 0, 2), col, 1, 4);
658
         ker4.b = s_m1[x];
550
         alphagrad (outmatrix_ref (out, 2, 1), col, 3, 4);
-
 
551
         alphagrad (outmatrix_ref (out, 1, 2), col, 3, 4);
659
         ker4.c = s_m1[x_p1];
552
         *outmatrix_ref (out, 2, 2) = col;
660
         ker4.d = s_m1[x_p2];
553
      }
-
 
554
 
661
 
555
      static void blendLineDiagonal (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
556
      {
662
         ker4.e = s_0[x_m1];
557
         alphagrad (outmatrix_ref (out, 1, 2), col, 1, 8); //conflict with other rotations for this odd scale
-
 
558
         alphagrad (outmatrix_ref (out, 2, 1), col, 1, 8);
663
         ker4.f = s_0[x];
559
         alphagrad (outmatrix_ref (out, 2, 2), col, 7, 8); //
664
         ker4.g = s_0[x_p1];
560
      }
665
         ker4.h = s_0[x_p2];
561
 
666
 
562
      static void blendCorner (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
667
         ker4.i = s_p1[x_m1];
563
      {
668
         ker4.j = s_p1[x];
564
         //model a round corner
669
         ker4.k = s_p1[x_p1];
565
         alphagrad (outmatrix_ref (out, 2, 2), col, 45, 100); //exact: 0.4545939598
-
 
566
         //alphagrad (outmatrix_ref (out, 2, 1), col, 7, 256); //0.02826017254 -> negligible + avoid conflicts with other rotations for this odd scale
-
 
567
         //alphagrad (outmatrix_ref (out, 1, 2), col, 7, 256); //0.02826017254
-
 
568
      }
670
         ker4.l = s_p1[x_p2];
569
   };
-
 
570
 
671
 
-
 
672
         ker4.m = s_p2[x_m1];
-
 
673
         ker4.n = s_p2[x];
-
 
674
         ker4.o = s_p2[x_p1];
-
 
675
         ker4.p = s_p2[x_p2];
571
 
676
 
-
 
677
         //evaluate the four corners on bottom-right of current pixel
-
 
678
         unsigned char blend_xy = 0; //for current (x, y) position
-
 
679
         {
-
 
680
            blendresult_t res;
-
 
681
            preProcessCorners (&res, &ker4, dist);
572
   struct Scaler4x
682
            /*
-
 
683
            preprocessing blend result:
-
 
684
            ---------
-
 
685
            | F | G |   //evalute corner between F, G, J, K
-
 
686
            ----|---|   //current input pixel is at position F
-
 
687
            | J | K |
-
 
688
            ---------
573
   {
689
            */
574
      static const int scale = 4;
690
            blend_xy = preProcBuffer[x];
-
 
691
            setBottomR (blend_xy, res.blend_f); //all four corners of (x, y) have been determined at this point due to processing sequence!
575
 
692
 
-
 
693
            setTopR (blend_xy1, res.blend_j); //set 2nd known corner for (x, y + 1)
-
 
694
            preProcBuffer[x] = blend_xy1; //store on current buffer position for use on next row
576
 
695
 
577
      static void blendLineShallow (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
578
      {
-
 
579
         alphagrad (outmatrix_ref (out, scale - 1, 0), col, 1, 4);
-
 
580
         alphagrad (outmatrix_ref (out, scale - 2, 2), col, 1, 4);
-
 
581
         alphagrad (outmatrix_ref (out, scale - 1, 1), col, 3, 4);
-
 
582
         alphagrad (outmatrix_ref (out, scale - 2, 3), col, 3, 4);
-
 
583
         *outmatrix_ref (out, scale - 1, 2) = col;
696
            blend_xy1 = 0;
584
         *outmatrix_ref (out, scale - 1, 3) = col;
697
            setTopL (blend_xy1, res.blend_k); //set 1st known corner for (x + 1, y + 1) and buffer for use on next column
585
      }
-
 
586
 
698
 
587
      static void blendLineSteep (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
588
      {
-
 
589
         alphagrad (outmatrix_ref (out, 0, scale - 1), col, 1, 4);
-
 
590
         alphagrad (outmatrix_ref (out, 2, scale - 2), col, 1, 4);
699
            if (x + 1 < bufferSize) //set 3rd known corner for (x + 1, y)
591
         alphagrad (outmatrix_ref (out, 1, scale - 1), col, 3, 4);
700
               setBottomL (preProcBuffer[x + 1], res.blend_g);
592
         alphagrad (outmatrix_ref (out, 3, scale - 2), col, 3, 4);
-
 
593
         *outmatrix_ref (out, 2, scale - 1) = col;
-
 
594
         *outmatrix_ref (out, 3, scale - 1) = col;
-
 
595
      }
701
         }
596
 
702
 
597
      static void blendLineSteepAndShallow (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
703
         //fill block of size scale * scale with the given color
598
      {
704
         {
599
         alphagrad (outmatrix_ref (out, 3, 1), col, 3, 4);
-
 
600
         alphagrad (outmatrix_ref (out, 1, 3), col, 3, 4);
-
 
601
         alphagrad (outmatrix_ref (out, 3, 0), col, 1, 4);
705
            uint32_t *blk = out;
602
         alphagrad (outmatrix_ref (out, 0, 3), col, 1, 4);
-
 
603
         alphagrad (outmatrix_ref (out, 2, 2), col, 1, 3); //[!] fixes 1/4 used in xBR
706
            for (int _blk_y = 0; _blk_y < scaler->factor; ++_blk_y, blk = (uint32_t *) BYTE_ADVANCE (blk, trgWidth * sizeof (uint32_t)))
604
         *outmatrix_ref (out, 3, 3) = col;
707
               for (int _blk_x = 0; _blk_x < scaler->factor; ++_blk_x)
605
         *outmatrix_ref (out, 3, 2) = col;
-
 
606
         *outmatrix_ref (out, 2, 3) = col;
708
                  blk[_blk_x] = ker4.f;
607
      }
709
         }
-
 
710
         //place *after* preprocessing step, to not overwrite the results while processing the the last pixel!
608
 
711
 
609
      static void blendLineDiagonal (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
610
      {
-
 
611
         alphagrad (outmatrix_ref (out, scale - 1, scale / 2), col, 1, 2);
712
         //blend four corners of current pixel
612
         alphagrad (outmatrix_ref (out, scale - 2, scale / 2 + 1), col, 1, 2);
-
 
613
         *outmatrix_ref (out, scale - 1, scale - 1) = col;
713
         if (blend_xy != 0) //good 5% perf-improvement
614
      }
714
         {
-
 
715
            kernel_3x3_t ker3; //perf: initialization is negligible
615
 
716
 
616
      static void blendCorner (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
617
      {
-
 
618
         //model a round corner
717
            ker3.a = ker4.a;
619
         alphagrad (outmatrix_ref (out, 3, 3), col, 68, 100); //exact: 0.6848532563
-
 
620
         alphagrad (outmatrix_ref (out, 3, 2), col, 9, 100); //0.08677704501
718
            ker3.b = ker4.b;
621
         alphagrad (outmatrix_ref (out, 2, 3), col, 9, 100); //0.08677704501
719
            ker3.c = ker4.c;
622
      }
-
 
623
   };
-
 
624
 
720
 
-
 
721
            ker3.d = ker4.e;
-
 
722
            ker3.e = ker4.f;
-
 
723
            ker3.f = ker4.g;
625
 
724
 
626
   struct Scaler5x
725
            ker3.g = ker4.i;
627
   {
726
            ker3.h = ker4.j;
628
      static const int scale = 5;
727
            ker3.i = ker4.k;
629
 
728
 
630
 
-
 
631
      static void blendLineShallow (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
729
            blend_pixel (scaler, &ker3, out, trgWidth, blend_xy, alphagrad, dist, 0);
632
      {
-
 
633
         alphagrad (outmatrix_ref (out, scale - 1, 0), col, 1, 4);
730
            blend_pixel (scaler, &ker3, out, trgWidth, blend_xy, alphagrad, dist, 90);
634
         alphagrad (outmatrix_ref (out, scale - 2, 2), col, 1, 4);
-
 
635
         alphagrad (outmatrix_ref (out, scale - 3, 4), col, 1, 4);
-
 
636
         alphagrad (outmatrix_ref (out, scale - 1, 1), col, 3, 4);
731
            blend_pixel (scaler, &ker3, out, trgWidth, blend_xy, alphagrad, dist, 180);
637
         alphagrad (outmatrix_ref (out, scale - 2, 3), col, 3, 4);
732
            blend_pixel (scaler, &ker3, out, trgWidth, blend_xy, alphagrad, dist, 270);
638
         *outmatrix_ref (out, scale - 1, 2) = col;
-
 
639
         *outmatrix_ref (out, scale - 1, 3) = col;
-
 
640
         *outmatrix_ref (out, scale - 1, 4) = col;
-
 
641
         *outmatrix_ref (out, scale - 2, 4) = col;
733
         }
642
      }
734
      }
643
 
-
 
644
      static void blendLineSteep (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
645
      {
-
 
646
         alphagrad (outmatrix_ref (out, 0, scale - 1), col, 1, 4);
-
 
647
         alphagrad (outmatrix_ref (out, 2, scale - 2), col, 1, 4);
-
 
648
         alphagrad (outmatrix_ref (out, 4, scale - 3), col, 1, 4);
-
 
649
         alphagrad (outmatrix_ref (out, 1, scale - 1), col, 3, 4);
-
 
650
         alphagrad (outmatrix_ref (out, 3, scale - 2), col, 3, 4);
-
 
651
         *outmatrix_ref (out, 2, scale - 1) = col;
-
 
652
         *outmatrix_ref (out, 3, scale - 1) = col;
-
 
653
         *outmatrix_ref (out, 4, scale - 1) = col;
-
 
654
         *outmatrix_ref (out, 4, scale - 2) = col;
-
 
655
      }
-
 
656
 
-
 
657
      static void blendLineSteepAndShallow (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
658
      {
-
 
659
         alphagrad (outmatrix_ref (out, 0, scale - 1), col, 1, 4);
-
 
660
         alphagrad (outmatrix_ref (out, 2, scale - 2), col, 1, 4);
-
 
661
         alphagrad (outmatrix_ref (out, 1, scale - 1), col, 3, 4);
-
 
662
         alphagrad (outmatrix_ref (out, scale - 1, 0), col, 1, 4);
-
 
663
         alphagrad (outmatrix_ref (out, scale - 2, 2), col, 1, 4);
-
 
664
         alphagrad (outmatrix_ref (out, scale - 1, 1), col, 3, 4);
-
 
665
         alphagrad (outmatrix_ref (out, 3, 3), col, 2, 3);
-
 
666
         *outmatrix_ref (out, 2, scale - 1) = col;
-
 
667
         *outmatrix_ref (out, 3, scale - 1) = col;
-
 
668
         *outmatrix_ref (out, 4, scale - 1) = col;
-
 
669
         *outmatrix_ref (out, scale - 1, 2) = col;
-
 
670
         *outmatrix_ref (out, scale - 1, 3) = col;
-
 
671
      }
-
 
672
 
-
 
673
      static void blendLineDiagonal (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
674
      {
-
 
675
         alphagrad (outmatrix_ref (out, scale - 1, scale / 2 + 0), col, 1, 8); //conflict with other rotations for this odd scale
-
 
676
         alphagrad (outmatrix_ref (out, scale - 2, scale / 2 + 1), col, 1, 8);
-
 
677
         alphagrad (outmatrix_ref (out, scale - 3, scale / 2 + 2), col, 1, 8); //
-
 
678
         alphagrad (outmatrix_ref (out, 4, 3), col, 7, 8);
-
 
679
         alphagrad (outmatrix_ref (out, 3, 4), col, 7, 8);
-
 
680
         *outmatrix_ref (out, 4, 4) = col;
-
 
681
      }
-
 
682
 
-
 
683
      static void blendCorner (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
684
      {
-
 
685
         // model a round corner
-
 
686
         alphagrad (outmatrix_ref (out, 4, 4), col, 86, 100); //exact: 0.8631434088
-
 
687
         alphagrad (outmatrix_ref (out, 4, 3), col, 23, 100); //0.2306749731
-
 
688
         alphagrad (outmatrix_ref (out, 3, 4), col, 23, 100); //0.2306749731
-
 
689
         //alphagrad (outmatrix_ref (out, 4, 2), col, 1, 64); //0.01676812367 -> negligible + avoid conflicts with other rotations for this odd scale
-
 
690
         //alphagrad (outmatrix_ref (out, 2, 4), col, 1, 64); //0.01676812367
-
 
691
      }
-
 
692
   };
-
 
693
 
-
 
694
 
-
 
695
   struct Scaler6x
-
 
696
   {
-
 
697
      static const int scale = 6;
-
 
698
 
-
 
699
 
-
 
700
      static void blendLineShallow (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
701
      {
-
 
702
         alphagrad (outmatrix_ref (out, scale - 1, 0), col, 1, 4);
-
 
703
         alphagrad (outmatrix_ref (out, scale - 2, 2), col, 1, 4);
-
 
704
         alphagrad (outmatrix_ref (out, scale - 3, 4), col, 1, 4);
-
 
705
         alphagrad (outmatrix_ref (out, scale - 1, 1), col, 3, 4);
-
 
706
         alphagrad (outmatrix_ref (out, scale - 2, 3), col, 3, 4);
-
 
707
         alphagrad (outmatrix_ref (out, scale - 3, 5), col, 3, 4);
-
 
708
 
-
 
709
         *outmatrix_ref (out, scale - 1, 2) = col;
-
 
710
         *outmatrix_ref (out, scale - 1, 3) = col;
-
 
711
         *outmatrix_ref (out, scale - 1, 4) = col;
-
 
712
         *outmatrix_ref (out, scale - 1, 5) = col;
-
 
713
         *outmatrix_ref (out, scale - 2, 4) = col;
-
 
714
         *outmatrix_ref (out, scale - 2, 5) = col;
-
 
715
      }
-
 
716
 
-
 
717
      static void blendLineSteep (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
718
      {
-
 
719
         alphagrad (outmatrix_ref (out, 0, scale - 1), col, 1, 4);
-
 
720
         alphagrad (outmatrix_ref (out, 2, scale - 2), col, 1, 4);
-
 
721
         alphagrad (outmatrix_ref (out, 4, scale - 3), col, 1, 4);
-
 
722
         alphagrad (outmatrix_ref (out, 1, scale - 1), col, 3, 4);
-
 
723
         alphagrad (outmatrix_ref (out, 3, scale - 2), col, 3, 4);
-
 
724
         alphagrad (outmatrix_ref (out, 5, scale - 3), col, 3, 4);
-
 
725
         *outmatrix_ref (out, 2, scale - 1) = col;
-
 
726
         *outmatrix_ref (out, 3, scale - 1) = col;
-
 
727
         *outmatrix_ref (out, 4, scale - 1) = col;
-
 
728
         *outmatrix_ref (out, 5, scale - 1) = col;
-
 
729
         *outmatrix_ref (out, 4, scale - 2) = col;
-
 
730
         *outmatrix_ref (out, 5, scale - 2) = col;
-
 
731
      }
-
 
732
 
-
 
733
      static void blendLineSteepAndShallow (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
734
      {
-
 
735
         alphagrad (outmatrix_ref (out, 0, scale - 1), col, 1, 4);
-
 
736
         alphagrad (outmatrix_ref (out, 2, scale - 2), col, 1, 4);
-
 
737
         alphagrad (outmatrix_ref (out, 1, scale - 1), col, 3, 4);
-
 
738
         alphagrad (outmatrix_ref (out, 3, scale - 2), col, 3, 4);
-
 
739
         alphagrad (outmatrix_ref (out, scale - 1, 0), col, 1, 4);
-
 
740
         alphagrad (outmatrix_ref (out, scale - 2, 2), col, 1, 4);
-
 
741
         alphagrad (outmatrix_ref (out, scale - 1, 1), col, 3, 4);
-
 
742
         alphagrad (outmatrix_ref (out, scale - 2, 3), col, 3, 4);
-
 
743
         *outmatrix_ref (out, 2, scale - 1) = col;
-
 
744
         *outmatrix_ref (out, 3, scale - 1) = col;
-
 
745
         *outmatrix_ref (out, 4, scale - 1) = col;
-
 
746
         *outmatrix_ref (out, 5, scale - 1) = col;
-
 
747
         *outmatrix_ref (out, 4, scale - 2) = col;
-
 
748
         *outmatrix_ref (out, 5, scale - 2) = col;
-
 
749
         *outmatrix_ref (out, scale - 1, 2) = col;
-
 
750
         *outmatrix_ref (out, scale - 1, 3) = col;
-
 
751
      }
-
 
752
 
-
 
753
      static void blendLineDiagonal (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
754
      {
-
 
755
         alphagrad (outmatrix_ref (out, scale - 1, scale / 2 + 0), col, 1, 2);
-
 
756
         alphagrad (outmatrix_ref (out, scale - 2, scale / 2 + 1), col, 1, 2);
-
 
757
         alphagrad (outmatrix_ref (out, scale - 3, scale / 2 + 2), col, 1, 2);
-
 
758
         *outmatrix_ref (out, scale - 2, scale - 1) = col;
-
 
759
         *outmatrix_ref (out, scale - 1, scale - 1) = col;
-
 
760
         *outmatrix_ref (out, scale - 1, scale - 2) = col;
-
 
761
      }
-
 
762
 
-
 
763
      static void blendCorner (uint32_t col, outmatrix_t *out, alphagrad_func alphagrad)
-
 
764
      {
-
 
765
         //model a round corner
-
 
766
         alphagrad (outmatrix_ref (out, 5, 5), col, 97, 100); //exact: 0.9711013910
-
 
767
         alphagrad (outmatrix_ref (out, 4, 5), col, 42, 100); //0.4236372243
-
 
768
         alphagrad (outmatrix_ref (out, 5, 4), col, 42, 100); //0.4236372243
-
 
769
         alphagrad (outmatrix_ref (out, 5, 3), col, 6, 100); //0.05652034508
-
 
770
         alphagrad (outmatrix_ref (out, 3, 5), col, 6, 100); //0.05652034508
-
 
771
      }
-
 
772
   };
735
   }
773
 
-
 
774
   //------------------------------------------------------------------------------------
-
 
775
}
736
}
776
 
-
 
777
 
737
 
778
 
738
 
779
static double dist24 (uint32_t pix1, uint32_t pix2)
739
static double dist24 (uint32_t pix1, uint32_t pix2)
780
{
740
{
781
   //30% perf boost compared to plain distYCbCr()!
741
   //30% perf boost compared to plain distYCbCr()!
Line 949... Line 909...
949
}
909
}
950
 
910
 
951
 
911
 
952
EXTERN_C void xbrz_scale24 (size_t factor, const uint32_t *src, uint32_t *trg, int srcWidth, int srcHeight)
912
EXTERN_C void xbrz_scale24 (size_t factor, const uint32_t *src, uint32_t *trg, int srcWidth, int srcHeight)
953
{
913
{
954
   if (factor == 2) return scaleImage<Scaler2x> (src, trg, srcWidth, srcHeight, 0, srcHeight, alphagrad24, dist24);
914
   if (factor < 7)
955
   else if (factor == 3) return scaleImage<Scaler3x> (src, trg, srcWidth, srcHeight, 0, srcHeight, alphagrad24, dist24);
-
 
956
   else if (factor == 4) return scaleImage<Scaler4x> (src, trg, srcWidth, srcHeight, 0, srcHeight, alphagrad24, dist24);
-
 
957
   else if (factor == 5) return scaleImage<Scaler5x> (src, trg, srcWidth, srcHeight, 0, srcHeight, alphagrad24, dist24);
915
      return scale_image (&scalers[factor - 2], src, trg, srcWidth, srcHeight, 0, srcHeight, alphagrad24, dist24);
958
   else if (factor == 6) return scaleImage<Scaler6x> (src, trg, srcWidth, srcHeight, 0, srcHeight, alphagrad24, dist24);
-
 
959
}
916
}
960
 
917
 
961
 
918
 
962
EXTERN_C void xbrz_scale32 (size_t factor, const uint32_t *src, uint32_t *trg, int srcWidth, int srcHeight)
919
EXTERN_C void xbrz_scale32 (size_t factor, const uint32_t *src, uint32_t *trg, int srcWidth, int srcHeight)
963
{
920
{
964
   if (factor == 2) return scaleImage<Scaler2x> (src, trg, srcWidth, srcHeight, 0, srcHeight, alphagrad32, dist32);
921
   if (factor < 7)
965
   else if (factor == 3) return scaleImage<Scaler3x> (src, trg, srcWidth, srcHeight, 0, srcHeight, alphagrad32, dist32);
-
 
966
   else if (factor == 4) return scaleImage<Scaler4x> (src, trg, srcWidth, srcHeight, 0, srcHeight, alphagrad32, dist32);
-
 
967
   else if (factor == 5) return scaleImage<Scaler5x> (src, trg, srcWidth, srcHeight, 0, srcHeight, alphagrad32, dist32);
922
      return scale_image (&scalers[factor - 2], src, trg, srcWidth, srcHeight, 0, srcHeight, alphagrad32, dist32);
968
   else if (factor == 6) return scaleImage<Scaler6x> (src, trg, srcWidth, srcHeight, 0, srcHeight, alphagrad32, dist32);
-
 
969
}
923
}