1. 最邻近插值
对于通过反向变换得到的一个浮点坐标,对其进行简单的取整(或加上0.5后取整),得到一个整数型坐标,这个整数型坐标对应的像素值就是目的像素的像素值,最邻近插值简单且直观,运算速度快,但得到的图像质量不高。
2. 双线性插值
对于一个目的像素,设坐标通过反向变换得到的浮点坐标为(i+u,j+v),其中i、j均为非负整数,u、v为[0,1)区间的浮点数,则这个像素得值 f(i+u,j+v) 可由原图像中坐标为 (i,j)、(i+1,j)、(i,j+1)、(i+1,j+1)所对应的周围四个像素的值决定,即
f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)
其中f(i,j)表示源图像(i,j)处的像素值,以此类推。
双线性内插值法计算量大,但缩放后图像质量高,不会出现像素值不连续的的情况。由于双线性插值具有低通滤波器的性质,使高频分量受损,所以可能会使图像轮廓在一定程度上变得模糊。
3. 图像缩放
假设图像 x 轴方向缩放比例为 fx,y 轴方向缩放比例为 fy,则新图中的点(x,y)与原图中点(x0,y0)的转换关系为
x0 = x / fx,
y0 = y / fy,
即新图(x,y)处的像素就是原图(x0,y0)处的像素,但x0 与 y0 为浮点数,需使用插值算法,求出实际像素数据。
4. 图像旋转
先确定二维直角坐标系为 x 轴正方向向右,y 轴正方向向像下。绕原点旋转 a 弧度,逆时针方向 a 大于 0,顺时针方向 a 小于 0 。在原图和新图中都建立此坐标系,原点在图像中心。则原图中的点(x0,y0)旋转 a 弧度后,得到新图中的点(x1,y1):
x1 = cos(a) * x0 + sin(a) * y0
y1 = cos(a) * y0 – sin(a) * x0
实际旋转中要注意坐标系的转换。
求新图的大小,可以将原图中的四个角点,都旋转 a 弧度,得到新的四个点,在此四个点中找到最大最小的 x 及 y 坐标,从而求出新图大小。
5.图像平移
坐标平移一下即可,不再赘述。
6.界面
界面采用 MFC MDI 框架,使用菜单加对话框的交互方式,不太追求用户体验,只求展示原理。
插值算法独立为一个函数,内部又有其它函数调用,导致效率低。
所有图像处理算法,只针对 真彩色和灰度图,对于其它带调色板的图像,算法将其视为灰度图处理,故而结果不可预料。
当初为了可移植性,算法中所有浮点数操作及科学计算使用宏,以求在需要时自定义数据类型模拟浮点数,这导致代码繁琐。

界面

放大4倍最邻近插值

放大4倍双线性插值

1
/**//*
2
ProcessInterpolationZ.h
3
4
Copyright (C) 2011, coreBugZJ, all rights reserved.
5
6
图像插值算法。
7
*/
8
9
10
#ifndef __PROCESSINTERPOLATION_Z_H_INCLUDED__
11
#define __PROCESSINTERPOLATION_Z_H_INCLUDED__
12
13
14
#include "TypeZ.h"
15
#include "ClassImageZ.h"
16
17
18
/**//* 插值算法 */
19
/**//* 最邻近插值 Nearest Neighbor Interpolation */
20
#define ITP_NEAREST_NEIGHBOR_Z 10
21
/**//* 双线性插值 Bilinear Interpolation */
22
#define ITP_BILINEAR_Z 20
23
24
25
/**//* 为了效率 */
26
/**//* 只是简单的检查了指针是否为 NULL,未检查图像是否合法 */
27
/**//* 通过图像指针直接访问了图像数据 */
28
/**//* 最终还是调用了 ImageZ 的函数,导致效率不高 */
29
PublicFuncZ R32 interpolateZ( cImageZ img, F64 fx, F64 fy, U32 itp, PixelZ *pixel );
30
31
32
#endif /* __PROCESSINTERPOLATION_Z_H_INCLUDED__ */
33
1
/**//*
2
ProcessInterpolationZ.c
3
4
Copyright (C) 2011, coreBugZJ, all rights reserved.
5
6
图像插值算法。
7
*/
8
9
10
#include "stdafx.h"
11
#include "ProcessInterpolationZ.h"
12
13
14
PublicFuncZ R32 interpolateZ( cImageZ img, F64 fx, F64 fy, U32 itp, PixelZ *pixel )
{
15
I32 ix, iy;
16
U32 x, y;
17
18
if ( (NULL == img) || (NULL == pixel) )
{
19
return RERR;
20
}
21
22
MOV_I32_F64_Z(ix,fx);
23
if ( 0 > ix )
{
24
return RERR;
25
}
26
x = ix;
27
if ( x >= img->width )
{
28
return RERR;
29
}
30
31
MOV_I32_F64_Z(iy,fy);
32
if ( 0 > iy )
{
33
return RERR;
34
}
35
y = iy;
36
if ( y >= img->height )
{
37
return RERR;
38
}
39
40
switch ( itp )
{
41
case ITP_NEAREST_NEIGHBOR_Z :
42
return getImagePixelZ( img, x, y, pixel );
43
44
case ITP_BILINEAR_Z :
45
{
46
F64 nx, ny, dx, dy, t1, ts;
47
U32 x1, y1;
48
PixelZ p00, p01, p10, p11;
49
I32 ti;
50
51
MOV_F64_I32_Z(t1,((I32)1));
52
53
ix = x;
54
MOV_F64_I32_Z(nx,ix);
55
SUB_F64_Z(dx,fx,nx);
56
SUB_F64_Z(nx,t1,dx);
57
58
iy = y;
59
MOV_F64_I32_Z(ny,iy);
60
SUB_F64_Z(dy,fy,ny);
61
SUB_F64_Z(ny,t1,dy);
62
63
x1 = x + 1;
64
if ( x1 >= img->width )
{
65
x1 = img->width - 1;
66
}
67
68
y1 = y + 1;
69
if ( y1 >= img->height )
{
70
y1 = img->height - 1;
71
}
72
73
if ( ( ROK != getImagePixelZ( img, x, y, &p00 ) ) ||
74
( ROK != getImagePixelZ( img, x, y1, &p01 ) ) ||
75
( ROK != getImagePixelZ( img, x1, y, &p10 ) ) ||
76
( ROK != getImagePixelZ( img, x1, y1, &p11 ) )
77
)
{
78
return RERR;
79
}
80
81
#define BL_IN(uuu,xxx,yyy) do { \
82
ti = (uuu); \
83
MOV_F64_I32_Z(t1,ti); \
84
MUL_F64_Z(t1,t1,(xxx)); \
85
MUL_F64_Z(t1,t1,(yyy)); \
86
ADD_F64_Z(ts,ts,t1);\
87
} while ( 0 )
88
#define BL_HELP(us,u00,u01,u10,u11) do { \
89
MOV_F64_I32_Z(ts,((I32)0)); \
90
BL_IN( (u00), nx, ny ); \
91
BL_IN( (u01), nx, dy ); \
92
BL_IN( (u10), dx, ny ); \
93
BL_IN( (u11), dx, dy ); \
94
MOV_I32_F64_Z(ti,ts); \
95
(us) = (U08)ti; \
96
}while ( 0 )
97
98
if ( isImagePaletteUsedZ(img) )
{
99
BL_HELP( pixel->index, p00.index, p01.index, p10.index, p11.index );
100
}
101
else
{
102
BL_HELP( pixel->color.r, p00.color.r, p01.color.r, p10.color.r, p11.color.r );
103
BL_HELP( pixel->color.g, p00.color.g, p01.color.g, p10.color.g, p11.color.g );
104
BL_HELP( pixel->color.b, p00.color.b, p01.color.b, p10.color.b, p11.color.b );
105
BL_HELP( pixel->color.a, p00.color.a, p01.color.a, p10.color.a, p11.color.a );
106
}
107
#undef BL_HELP
108
#undef BL_IN
109
} /**//* case */
110
return ROK;
111
}
112
113
return RERR;
114
}
115
1
/**//*
2
ProcessGeometryZ.h
3
4
Copyright (C) 2011, coreBugZJ, all rights reserved.
5
6
几何变换(镜像,转置,扩大,剪裁,缩放,旋转等)。
7
*/
8
9
10
#ifndef __PROCESSGEOMETRY_Z_H_INCLUDED__
11
#define __PROCESSGEOMETRY_Z_H_INCLUDED__
12
13
14
#include "TypeZ.h"
15
#include "ClassImageZ.h"
16
17
18
/**//* 镜像变换 */
19
PublicFuncZ R32 mirrorImageZ( ImageZ img, B32 horz );
20
PublicFuncZ ImageZ createImageMirrorZ( cImageZ src, B32 horz );
21
/**//* 转置 */
22
PublicFuncZ ImageZ createImageTransposeZ( cImageZ src );
23
PublicFuncZ R32 transposeImageZ( ImageZ img );
24
/**//* 扩张 */
25
PublicFuncZ ImageZ createImageExpandZ( cImageZ src, U32 left, U32 top, U32 right, U32 bottom, const PixelZ *pBk );
26
PublicFuncZ R32 expandImageZ( ImageZ img, U32 left, U32 top, U32 right, U32 bottom, const PixelZ *pBk );
27
/**//* 剪裁 */
28
PublicFuncZ ImageZ createImageCropZ( cImageZ src, U32 left, U32 top, U32 width, U32 height );
29
PublicFuncZ R32 cropImageZ( ImageZ img, U32 left, U32 top, U32 width, U32 height );
30
/**//* 缩放 */
31
/**//* 水平缩放为原来的 xf 倍 */
32
/**//* 垂直缩放为原来的 yf 倍 */
33
PublicFuncZ ImageZ createImageZoomZ( cImageZ src, F64 xf, F64 yf, U32 itp );
34
PublicFuncZ R32 zoomImageZ( ImageZ img, F64 xf, F64 yf, U32 itp );
35
/**//* 旋转 90 度,单位 角度 */
36
/**//* clockwise 为 TRUE 则顺时针旋转,FALSE 逆时针旋转 */
37
PublicFuncZ ImageZ createImageRotate90degreeZ( cImageZ src, B32 clockwise );
38
PublicFuncZ R32 rotateImage90degreeZ( ImageZ img, B32 clockwise );
39
/**//* 旋转任意角,单位 弧度 */
40
/**//* rad 若 > 0 则逆时针旋转,若 < 0 则顺时针旋转 */
41
/**//* 旋转之后会扩大图像,新区域填充 (*pBk) */
42
PublicFuncZ ImageZ createImageRotateZ( cImageZ src, F64 rad, U32 itp, const PixelZ *pBk );
43
PublicFuncZ R32 rotateImageZ( ImageZ img, F64 rad, U32 itp, const PixelZ *pBk );
44
45
46
#endif /* __PROCESSGEOMETRY_Z_H_INCLUDED__ */
47
1
/**//*
2
ProcessGeometryZ.c
3
4
Copyright (C) 2011, coreBugZJ, all rights reserved.
5
6
几何变换(镜像,转置,扩大,剪裁,缩放,旋转等)。
7
*/
8
9
10
#include "stdafx.h"
11
#include "ProcessGeometryZ.h"
12
#include "ProcessInterpolationZ.h"
13
#include "MathZ.h"
14
15
16
PublicFuncZ R32 mirrorImageZ( ImageZ img, B32 horz )
{
17
U32 x0, x1, y0, y1, x, y, width, height;
18
PixelZ p0, p1;
19
20
if ( !isImageValidZ(img) )
{
21
return RERR;
22
}
23
width = getImageWidthZ( img );
24
height = getImageHeightZ( img );
25
26
if ( horz )
{
27
x0 = 0;
28
x1 = width - 1;
29
while ( x0 < x1 )
{
30
for( y = 0; y < height; ++y )
{
31
if ( (ROK != getImagePixelZ( img, x0, y, &p0 )) ||
32
(ROK != getImagePixelZ( img, x1, y, &p1 )) ||
33
(ROK != putImagePixelZ( img, x0, y, &p1 )) ||
34
(ROK != putImagePixelZ( img, x1, y, &p0 ))
35
)
{
36
return RERR;
37
}
38
}
39
++x0;
40
--x1;
41
}
42
}
43
else
{
44
y0 = 0;
45
y1 = height - 1;
46
while ( y0 < y1 )
{
47
for ( x = 0; x < width; ++x )
{
48
if ( (ROK != getImagePixelZ( img, x, y0, &p0 )) ||
49
(ROK != getImagePixelZ( img, x, y1, &p1 )) ||
50
(ROK != putImagePixelZ( img, x, y0, &p1 )) ||
51
(ROK != putImagePixelZ( img, x, y1, &p0 ))
52
)
{
53
return RERR;
54
}
55
}
56
++y0;
57
--y1;
58
}
59
}
60
61
return ROK;
62
}
63
64
PublicFuncZ ImageZ createImageMirrorZ( cImageZ src, B32 horz )
{
65
ImageZ img = createImageFromImageZ( src );
66
if ( !isImageValidZ(img) )
{
67
return NULL;
68
}
69
if ( ROK != mirrorImageZ( img, horz ) )
{
70
destroyImageZ( img );
71
return NULL;
72
}
73
return img;
74
}
75
76
PublicFuncZ ImageZ createImageTransposeZ( cImageZ src )
{
77
U32 width, height, x, y;
78
ImageZ img;
79
PixelZ pixel;
80
81
if ( !isImageValidZ(src) )
{
82
return NULL;
83
}
84
width = getImageHeightZ( src );
85
height = getImageWidthZ( src );
86
87
img = createImageZ( width, height, getImageColorNumZ(src) );
88
if ( !isImageValidZ(img) )
{
89
return NULL;
90
}
91
92
if ( ROK != copyImagePaletteZ( img, src ) )
{
93
destroyImageZ( img );
94
return NULL;
95
}
96
97
for ( y = 0; y < height; ++y )
{
98
for ( x = 0; x < width; ++x )
{
99
if ( (ROK != getImagePixelZ( src, y, x, &pixel )) ||
100
(ROK != putImagePixelZ( img, x, y, &pixel ))
101
)
{
102
destroyImageZ( img );
103
return NULL;
104
}
105
}
106
}
107
108
return img;
109
}
110
111
PublicFuncZ R32 transposeImageZ( ImageZ img )
{
112
ImageZ tmp = createImageTransposeZ( img );
113
if ( !isImageValidZ(tmp) )
{
114
return RERR;
115
}
116
if ( ROK != swapImageZ( tmp, img ) )
{
117
destroyImageZ( tmp );
118
return RERR;
119
}
120
destroyImageZ( tmp );
121
return ROK;
122
}
123
124
PublicFuncZ ImageZ createImageExpandZ( cImageZ src, U32 left, U32 top, U32 right, U32 bottom, const PixelZ *pBk )
{
125
ImageZ img;
126
U32 width, height, colorNum, srcWidth, srcHeight;
127
U32 x, y;
128
PixelZ pixel;
129
130
if ( (!isImageValidZ(src)) || (pBk == NULL) )
{
131
return NULL;
132
}
133
colorNum = getImageColorNumZ( src );
134
srcWidth = getImageWidthZ( src );
135
srcHeight = getImageHeightZ( src );
136
width = srcWidth + left + right;
137
height = srcHeight + top + bottom;
138
if ( (colorNum > 0) && (pBk->index >= colorNum) )
{
139
return NULL;
140
}
141
142
img = createImageZ( width, height, colorNum );
143
if ( !isImageValidZ(img) )
{
144
return NULL;
145
}
146
147
if ( ROK != copyImagePaletteZ( img, src ) )
{
148
destroyImageZ( img );
149
return NULL;
150
}
151
152
for ( y = 0; y < srcHeight; ++y )
{
153
for ( x = 0; x < left; ++x )
{
154
if ( ROK != putImagePixelZ( img, x, top+y, pBk ) )
{
155
destroyImageZ( img );
156
return NULL;
157
}
158
}
159
for ( x = 0; x < srcWidth; ++x )
{
160
if ( (ROK != getImagePixelZ( src, x, y, &pixel )) ||
161
(ROK != putImagePixelZ( img, left+x, top+y, &pixel ))
162
)
{
163
destroyImageZ( img );
164
return NULL;
165
}
166
}
167
for ( x = 0; x < right; ++x )
{
168
if ( ROK != putImagePixelZ( img, left+srcWidth+x, top+y, pBk ) )
{
169
destroyImageZ( img );
170
return NULL;
171
}
172
}
173
}
174
for ( x = 0; x < width; ++x )
{
175
for ( y = 0; y < top; ++y )
{
176
if ( ROK != putImagePixelZ( img, x, y, pBk ) )
{
177
destroyImageZ( img );
178
return NULL;
179
}
180
}
181
for ( y = 0; y < bottom; ++y )
{
182
if ( ROK != putImagePixelZ( img, x, top+srcHeight+y, pBk ) )
{
183
destroyImageZ( img );
184
return NULL;
185
}
186
}
187
}
188
189
return img;
190
}
191
192
PublicFuncZ R32 expandImageZ( ImageZ img, U32 left, U32 top, U32 right, U32 bottom, const PixelZ *pBk )
{
193
ImageZ tmp = createImageExpandZ( img, left, top, right, bottom, pBk );
194
if ( !isImageValidZ(tmp) )
{
195
return RERR;
196
}
197
if ( ROK != swapImageZ( tmp, img ) )
{
198
destroyImageZ( tmp );
199
return RERR;
200
}
201
destroyImageZ( tmp );
202
return ROK;
203
}
204
205
PublicFuncZ ImageZ createImageCropZ( cImageZ src, U32 left, U32 top, U32 width, U32 height )
{
206
ImageZ img;
207
U32 srcWidth, srcHeight, colorNum, x, y;
208
PixelZ pixel;
209
210
if ( !isImageValidZ(src) )
{
211
return NULL;
212
}
213
srcWidth = getImageWidthZ( src );
214
srcHeight = getImageHeightZ( src );
215
colorNum = getImageColorNumZ( src );
216
if ( (left >= srcWidth) || (top >= srcHeight) )
{
217
return NULL;
218
}
219
if ( left + width > srcWidth )
{
220
width = srcWidth - left;
221
}
222
if ( top + height > srcHeight )
{
223
height = srcHeight - top;
224
}
225
226
img = createImageZ( width, height, colorNum );
227
if ( !isImageValidZ(img) )
{
228
return NULL;
229
}
230
231
if ( ROK != copyImagePaletteZ( img, src ) )
{
232
destroyImageZ( img );
233
return NULL;
234
}
235
236
for ( y = 0; y < height; ++y )
{
237
for ( x = 0; x < width; ++x )
{
238
if ( (ROK != getImagePixelZ( src, left+x, top+y, &pixel )) ||
239
(ROK != putImagePixelZ( img, x, y, &pixel ))
240
)
{
241
destroyImageZ( img );
242
return NULL;
243
}
244
}
245
}
246
247
return img;
248
}
249
250
PublicFuncZ R32 cropImageZ( ImageZ img, U32 left, U32 top, U32 width, U32 height )
{
251
ImageZ tmp = createImageCropZ( img, left, top, width, height );
252
if ( !isImageValidZ(tmp) )
{
253
return RERR;
254
}
255
if ( ROK != swapImageZ( tmp, img ) )
{
256
destroyImageZ( tmp );
257
return RERR;
258
}
259
destroyImageZ( tmp );
260
return ROK;
261
}
262
263
PublicFuncZ ImageZ createImageZoomZ( cImageZ src, F64 xf, F64 yf, U32 itp )
{
264
ImageZ img;
265
U32 srcWidth, srcHeight, colorNum, width, height;
266
U32 x, y;
267
PixelZ pixel;
268
F64 tf, fx, fy;
269
270
if ( !isImageValidZ(src) )
{
271
return NULL;
272
}
273
srcWidth = getImageWidthZ( src );
274
srcHeight = getImageHeightZ( src );
275
colorNum = getImageColorNumZ( src );
276
277
MOV_F64_U32_Z(tf,srcWidth);
278
MUL_F64_Z(tf,tf,xf);
279
MOV_U32_F64_Z(width,tf);
280
MOV_F64_U32_Z(tf,srcHeight);
281
MUL_F64_Z(tf,tf,yf);
282
MOV_U32_F64_Z(height,tf);
283
284
if ( (width < 1) || (height < 1) )
{
285
return NULL;
286
}
287
288
img = createImageZ( width, height, colorNum );
289
if ( !isImageValidZ(img) )
{
290
return NULL;
291
}
292
293
if ( ROK != copyImagePaletteZ( img, src ) )
{
294
destroyImageZ( img );
295
return NULL;
296
}
297
298
for ( y = 0; y < height; ++y )
{
299
MOV_F64_U32_Z(tf,y);
300
DIV_F64_Z(fy,tf,yf);
301
for ( x = 0; x < width; ++x )
{
302
MOV_F64_U32_Z(tf,x);
303
DIV_F64_Z(fx,tf,xf);
304
if ( (ROK != interpolateZ(src, fx, fy, itp, &pixel)) ||
305
(ROK != putImagePixelZ(img,x,y,&pixel))
306
)
{
307
destroyImageZ( img );
308
return NULL;
309
}
310
}
311
}
312
313
return img;
314
}
315
316
PublicFuncZ R32 zoomImageZ( ImageZ img, F64 xf, F64 yf, U32 itp )
{
317
ImageZ tmp = createImageZoomZ( img, xf, yf, itp );
318
if ( !isImageValidZ(tmp) )
{
319
return RERR;
320
}
321
if ( ROK != swapImageZ( tmp, img ) )
{
322
destroyImageZ( tmp );
323
return RERR;
324
}
325
destroyImageZ( tmp );
326
return ROK;
327
}
328
329
PublicFuncZ ImageZ createImageRotate90degreeZ( cImageZ src, B32 clockwise )
{
330
ImageZ img;
331
U32 width, height, colorNum, x, y;
332
PixelZ pixel;
333
334
if ( !isImageValidZ(src) )
{
335
return NULL;
336
}
337
338
width = getImageHeightZ( src );
339
height = getImageWidthZ( src );
340
colorNum = getImageColorNumZ( src );
341
342
img = createImageZ( width, height, colorNum );
343
if ( !isImageValidZ(img) )
{
344
return NULL;
345
}
346
347
if ( ROK != copyImagePaletteZ( img, src ) )
{
348
destroyImageZ( img );
349
return NULL;
350
}
351
352
if ( clockwise )
{
353
for ( y = 0; y < height; ++y )
{
354
for ( x = 0; x < width; ++x )
{
355
if ( (ROK != getImagePixelZ( src, y, width-1-x, &pixel )) ||
356
(ROK != putImagePixelZ( img, x, y, &pixel ))
357
)
{
358
destroyImageZ( img );
359
return NULL;
360
}
361
}
362
}
363
}
364
else
{
365
for ( y = 0; y < height; ++y )
{
366
for ( x = 0; x < width; ++x )
{
367
if ( (ROK != getImagePixelZ( src, height-1-y, x, &pixel )) ||
368
(ROK != putImagePixelZ( img, x, y, &pixel ))
369
)
{
370
destroyImageZ( img );
371
return NULL;
372
}
373
}
374
}
375
}
376
377
return img;
378
}
379
380
PublicFuncZ R32 rotateImage90degreeZ( ImageZ img, B32 clockwise )
{
381
ImageZ tmp = createImageRotate90degreeZ( img, clockwise );
382
if ( !isImageValidZ(tmp) )
{
383
return RERR;
384
}
385
if ( ROK != swapImageZ( tmp, img ) )
{
386
destroyImageZ( tmp );
387
return RERR;
388
}
389
destroyImageZ( tmp );
390
return ROK;
391
}
392
393
PublicFuncZ ImageZ createImageRotateZ( cImageZ src, F64 rad, U32 itp, const PixelZ *pBk )
{
394
F64 fksin, fkcos, fi, fj, fx, fy, f1, f2;
395
U32 srcWidth, srcHeight, width, height, x, y, i;
396
#define CORNER 4
397
F64 cnrX[ CORNER ], cnrY[ CORNER ], newX[ CORNER ], newY[ CORNER ];
398
F64 minX, minY, maxX, maxY;
399
ImageZ img;
400
PixelZ pixel;
401
402
if ( (!isImageValidZ(src)) || (NULL == pBk) )
{
403
return NULL;
404
}
405
406
srcWidth = getImageWidthZ( src );
407
MOV_F64_U32_Z( f1, srcWidth );
408
DIV_F64_U32_Z( f1, f1, 2 );
409
NEG_F64_Z( f2, f1 );
410
MOV_F64_Z( cnrX[ 0 ], f2 );
411
MOV_F64_Z( cnrX[ 1 ], f2 );
412
MOV_F64_Z( cnrX[ 2 ], f1 );
413
MOV_F64_Z( cnrX[ 3 ], f1 );
414
415
srcHeight = getImageHeightZ( src );
416
MOV_F64_U32_Z( f1, srcHeight );
417
DIV_F64_U32_Z( f1, f1, 2 );
418
NEG_F64_Z( f2, f1 );
419
MOV_F64_Z( cnrY[ 0 ], f2 );
420
MOV_F64_Z( cnrY[ 1 ], f1 );
421
MOV_F64_Z( cnrY[ 2 ], f1 );
422
MOV_F64_Z( cnrY[ 3 ], f2 );
423
424
SIN_F64_Z( fksin, rad );
425
COS_F64_Z( fkcos, rad );
426
427
/**//* fz = fa * fb + fc * fd */
428
#define HELP_ADD( fz, fa, fb, fc, fd ) do { \
429
MUL_F64_Z( f1, (fa), (fb) ); \
430
MUL_F64_Z( f2, (fc), (fd) ); \
431
ADD_F64_Z( (fz), f1, f2 ); \
432
} while ( 0 )
433
/**//* fz = fa * fb - fc * fd */
434
#define HELP_SUB( fz, fa, fb, fc, fd ) do { \
435
MUL_F64_Z( f1, (fa), (fb) ); \
436
MUL_F64_Z( f2, (fc), (fd) ); \
437
SUB_F64_Z( (fz), f1, f2 ); \
438
} while ( 0 )
439
/**//* fz = max( fa, fb, fc, fd ) */
440
#define HELP_MAX( fz, fa, fb, fc, fd ) do { \
441
MAX_F64_Z( f1, (fa), (fb) ); \
442
MAX_F64_Z( f2, (fc), (fd) ); \
443
MAX_F64_Z( (fz), f1, f2 ); \
444
} while ( 0 )
445
/**//* fz = min( fa, fb, fc, fd ) */
446
#define HELP_MIN( fz, fa, fb, fc, fd ) do { \
447
MIN_F64_Z( f1, (fa), (fb) ); \
448
MIN_F64_Z( f2, (fc), (fd) ); \
449
MIN_F64_Z( (fz), f1, f2 ); \
450
} while ( 0 )
451
452
for ( i = 0; i < CORNER; ++i )
{
453
HELP_ADD( newX[ i ], fkcos, cnrX[ i ], fksin, cnrY[ i ] );
454
HELP_SUB( newY[ i ], fkcos, cnrY[ i ], fksin, cnrX[ i ] );
455
}
456
457
HELP_MAX( maxX, newX[ 0 ], newX[ 1 ], newX[ 2 ], newX[ 3 ] );
458
HELP_MIN( minX, newX[ 0 ], newX[ 1 ], newX[ 2 ], newX[ 3 ] );
459
HELP_MAX( maxY, newY[ 0 ], newY[ 1 ], newY[ 2 ], newY[ 3 ] );
460
HELP_MIN( minY, newY[ 0 ], newY[ 1 ], newY[ 2 ], newY[ 3 ] );
461
462
SUB_F64_Z( f1, maxX, minX );
463
MOV_U32_F64_Z( width, f1 );
464
SUB_F64_Z( f2, maxY, minY );
465
MOV_U32_F64_Z( height, f2 );
466
467
img = createImageZ( width, height, getImageColorNumZ(src) );
468
if ( !isImageValidZ( img ) )
{
469
return NULL;
470
}
471
if ( ROK != copyImagePaletteZ( img, src ) )
{
472
destroyImageZ( img );
473
return NULL;
474
}
475
476
for ( y = 0; y < height; ++y )
{
477
ADD_F64_U32_Z( fy, minY, y );
478
for ( x = 0; x < width; ++x )
{
479
ADD_F64_U32_Z( fx, minX, x );
480
HELP_SUB( fi, fkcos, fx, fksin, fy );
481
HELP_ADD( fj, fksin, fx, fkcos, fy );
482
ADD_F64_Z( fi, fi, cnrX[ 2 ] );
483
ADD_F64_Z( fj, fj, cnrY[ 2 ] );
484
if ( ROK == interpolateZ( src, fi, fj, itp, &pixel ) )
{
485
putImagePixelZ( img, x, y, &pixel );
486
}
487
else
{
488
putImagePixelZ( img, x, y, pBk );
489
}
490
}
491
}
492
493
#undef HELP_MIN
494
#undef HELP_MAX
495
#undef HELP_SUB
496
#undef HELP_ADD
497
#undef CORNER
498
499
return img;
500
}
501
502
PublicFuncZ R32 rotateImageZ( ImageZ img, F64 rad, U32 itp, const PixelZ *pBk )
{
503
ImageZ tmp = createImageRotateZ( img, rad, itp, pBk );
504
if ( !isImageValidZ(tmp) )
{
505
return RERR;
506
}
507
if ( ROK != swapImageZ( tmp, img ) )
{
508
destroyImageZ( tmp );
509
return RERR;
510
}
511
destroyImageZ( tmp );
512
return ROK;
513
}
514