1 /*
2  * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 
27 /*
28  * FUNCTION
29  *      mlib_ImageZoom - image scaling with edge condition
30  *
31  * SYNOPSIS
32  *      mlib_status mlib_ImageZoom(mlib_image       *dst,
33  *                                 const mlib_image *src,
34  *                                 mlib_f32         zoomx,
35  *                                 mlib_f32         zoomy,
36  *                                 mlib_filter      filter,
37  *                                 mlib_edge        edge)
38  *
39  * ARGUMENTS
40  *      dst       Pointer to destination image
41  *      src       Pointer to source image
42  *      zoomx     X zoom factor.
43  *      zoomy     Y zoom factor.
44  *      filter    Type of resampling filter.
45  *      edge      Type of edge condition.
46  *
47  * DESCRIPTION
48  *  The center of the source image is mapped to the center of the
49  *  destination image.
50  *
51  *  The upper-left corner pixel of an image is located at (0.5, 0.5).
52  *
53  *  The resampling filter can be one of the following:
54  *    MLIB_NEAREST
55  *    MLIB_BILINEAR
56  *    MLIB_BICUBIC
57  *    MLIB_BICUBIC2
58  *
59  *  The edge condition can be one of the following:
60  *    MLIB_EDGE_DST_NO_WRITE  (default)
61  *    MLIB_EDGE_DST_FILL_ZERO
62  *    MLIB_EDGE_OP_NEAREST
63  *    MLIB_EDGE_SRC_EXTEND
64  *    MLIB_EDGE_SRC_PADDED
65  */
66 
67 #include <mlib_image.h>
68 #include <vis_proto.h>
69 
70 /***************************************************************/
71 
72 #define  _MLIB_VIS_VER_
73 #include <mlib_ImageZoom.h>
74 
75 /***************************************************************/
76 
77 #define  VARIABLE(FORMAT)                                       \
78   mlib_s32 j,                                                   \
79            dx = GetElemStruct(DX),                              \
80            dy = GetElemStruct(DY),                              \
81            x = GetElemSubStruct(current, srcX),                 \
82            y = GetElemSubStruct(current, srcY),                 \
83            src_stride = GetElemStruct(src_stride),              \
84            dst_stride = GetElemStruct(dst_stride),              \
85            width  = GetElemSubStruct(current, width),           \
86            height = GetElemSubStruct(current, height);          \
87   FORMAT  *sp = GetElemSubStruct(current, sp),                  \
88           *dp = GetElemSubStruct(current, dp)
89 
90 /***************************************************************/
91 
mlib_ImageZoom_U8_1_Nearest(mlib_work_image * param)92 mlib_status mlib_ImageZoom_U8_1_Nearest(mlib_work_image *param)
93 {
94   VARIABLE(mlib_u8);
95   mlib_u8  *dl = dp, *tsp;
96   mlib_s32 y0 = -1, dx7 = 7*dx, dx15 = 8*dx + dx7;
97 
98   tsp = sp;
99   y = GetElemSubStruct(current, srcY) & MLIB_MASK;
100 
101   for (j = 0; j < height; j++) {
102 
103     if ((y0 >> MLIB_SHIFT) == (y >> MLIB_SHIFT)) {
104       mlib_ImageCopy_na(dl - dst_stride, dl, width);
105     }
106     else {
107       mlib_u8 *dp = dl, *dend = dl + width;
108 
109       vis_write_gsr(7);
110       x = GetElemSubStruct(current, srcX) & MLIB_MASK;
111 
112       while (((mlib_addr)dp & 7) && (dp < dend)) {
113         *dp++ = tsp[x >> MLIB_SHIFT];
114         x += dx;
115       }
116 
117       x += dx7;
118 
119 #pragma pipeloop(0)
120       for (; dp <= dend - 8; dp += 8) {
121         mlib_d64 s0;
122 
123         s0 = vis_faligndata(vis_ld_u8_i(tsp, x >> MLIB_SHIFT), s0);
124         x -= dx;
125         s0 = vis_faligndata(vis_ld_u8_i(tsp, x >> MLIB_SHIFT), s0);
126         x -= dx;
127         s0 = vis_faligndata(vis_ld_u8_i(tsp, x >> MLIB_SHIFT), s0);
128         x -= dx;
129         s0 = vis_faligndata(vis_ld_u8_i(tsp, x >> MLIB_SHIFT), s0);
130         x -= dx;
131         s0 = vis_faligndata(vis_ld_u8_i(tsp, x >> MLIB_SHIFT), s0);
132         x -= dx;
133         s0 = vis_faligndata(vis_ld_u8_i(tsp, x >> MLIB_SHIFT), s0);
134         x -= dx;
135         s0 = vis_faligndata(vis_ld_u8_i(tsp, x >> MLIB_SHIFT), s0);
136         x -= dx;
137         s0 = vis_faligndata(vis_ld_u8_i(tsp, x >> MLIB_SHIFT), s0);
138         x += dx15;
139 
140         *(mlib_d64*)dp = s0;
141       }
142 
143       x -= dx7;
144 
145       while (dp < dend) {
146         *dp++ = tsp[x >> MLIB_SHIFT];
147         x += dx;
148       }
149     }
150 
151     y0 = y;
152     y += dy;
153     dl  = (void*)((mlib_u8*)dl + dst_stride);
154     tsp = (void*)((mlib_u8*)sp + (y >> MLIB_SHIFT) * src_stride);
155   }
156 
157   return MLIB_SUCCESS;
158 }
159 
160 /***************************************************************/
161 
mlib_ImageZoom_U8_3_Nearest(mlib_work_image * param)162 mlib_status mlib_ImageZoom_U8_3_Nearest(mlib_work_image *param)
163 {
164   VARIABLE(mlib_u8);
165   mlib_u8  *dl = dp, *tsp, *tt;
166   mlib_s32 cx, y0 = -1, dx7 = 7*dx, dx15 = 8*dx + dx7;
167 
168   tsp = sp;
169   y = GetElemSubStruct(current, srcY) & MLIB_MASK;
170 
171   for (j = 0; j < height; j++) {
172 
173     if ((y0 >> MLIB_SHIFT) == (y >> MLIB_SHIFT)) {
174       mlib_ImageCopy_na(dl - dst_stride, dl, 3*width);
175     }
176     else {
177       mlib_u8 *dp = dl, *dend = dl + 3*width;
178 
179       vis_write_gsr(7);
180       x = GetElemSubStruct(current, srcX) & MLIB_MASK;
181 
182       while (((mlib_addr)dp & 7) && (dp < dend)) {
183         cx = x >> MLIB_SHIFT;
184         tt = tsp + 2*cx + cx;
185         dp[0] = tt[0];
186         dp[1] = tt[1];
187         dp[2] = tt[2];
188         x += dx;
189         dp += 3;
190       }
191 
192       x += dx7;
193 
194 #pragma pipeloop(0)
195       for (; dp <= dend - 24; dp += 24) {
196         mlib_d64 s0, s1, s2;
197 
198         cx = x >> MLIB_SHIFT;
199         tt = tsp + 2*cx + cx;
200         x -= dx;
201         s2 = vis_faligndata(vis_ld_u8_i(tt, 2), s2);
202         s2 = vis_faligndata(vis_ld_u8_i(tt, 1), s2);
203         s2 = vis_faligndata(vis_ld_u8_i(tt, 0), s2);
204 
205         cx = x >> MLIB_SHIFT;
206         tt = tsp + 2*cx + cx;
207         x -= dx;
208         s2 = vis_faligndata(vis_ld_u8_i(tt, 2), s2);
209         s2 = vis_faligndata(vis_ld_u8_i(tt, 1), s2);
210         s2 = vis_faligndata(vis_ld_u8_i(tt, 0), s2);
211 
212         cx = x >> MLIB_SHIFT;
213         tt = tsp + 2*cx + cx;
214         x -= dx;
215         s2 = vis_faligndata(vis_ld_u8_i(tt, 2), s2);
216         s2 = vis_faligndata(vis_ld_u8_i(tt, 1), s2);
217         s1 = vis_faligndata(vis_ld_u8_i(tt, 0), s1);
218 
219         cx = x >> MLIB_SHIFT;
220         tt = tsp + 2*cx + cx;
221         x -= dx;
222         s1 = vis_faligndata(vis_ld_u8_i(tt, 2), s1);
223         s1 = vis_faligndata(vis_ld_u8_i(tt, 1), s1);
224         s1 = vis_faligndata(vis_ld_u8_i(tt, 0), s1);
225 
226         cx = x >> MLIB_SHIFT;
227         tt = tsp + 2*cx + cx;
228         x -= dx;
229         s1 = vis_faligndata(vis_ld_u8_i(tt, 2), s1);
230         s1 = vis_faligndata(vis_ld_u8_i(tt, 1), s1);
231         s1 = vis_faligndata(vis_ld_u8_i(tt, 0), s1);
232 
233         cx = x >> MLIB_SHIFT;
234         tt = tsp + 2*cx + cx;
235         x -= dx;
236         s1 = vis_faligndata(vis_ld_u8_i(tt, 2), s1);
237         s0 = vis_faligndata(vis_ld_u8_i(tt, 1), s0);
238         s0 = vis_faligndata(vis_ld_u8_i(tt, 0), s0);
239 
240         cx = x >> MLIB_SHIFT;
241         tt = tsp + 2*cx + cx;
242         x -= dx;
243         s0 = vis_faligndata(vis_ld_u8_i(tt, 2), s0);
244         s0 = vis_faligndata(vis_ld_u8_i(tt, 1), s0);
245         s0 = vis_faligndata(vis_ld_u8_i(tt, 0), s0);
246 
247         cx = x >> MLIB_SHIFT;
248         tt = tsp + 2*cx + cx;
249         x += dx15;
250         s0 = vis_faligndata(vis_ld_u8_i(tt, 2), s0);
251         s0 = vis_faligndata(vis_ld_u8_i(tt, 1), s0);
252         s0 = vis_faligndata(vis_ld_u8_i(tt, 0), s0);
253 
254         ((mlib_d64*)dp)[0] = s0;
255         ((mlib_d64*)dp)[1] = s1;
256         ((mlib_d64*)dp)[2] = s2;
257       }
258 
259       x -= dx7;
260 
261       while (dp < dend) {
262         cx = x >> MLIB_SHIFT;
263         tt = tsp + 2*cx + cx;
264         dp[0] = tt[0];
265         dp[1] = tt[1];
266         dp[2] = tt[2];
267         x += dx;
268         dp += 3;
269       }
270     }
271 
272     y0 = y;
273     y += dy;
274     dl  = (void*)((mlib_u8*)dl + dst_stride);
275     tsp = (void*)((mlib_u8*)sp + (y >> MLIB_SHIFT) * src_stride);
276   }
277 
278   return MLIB_SUCCESS;
279 }
280 
281 /***************************************************************/
282 
mlib_ImageZoom_S16_3_Nearest(mlib_work_image * param)283 mlib_status mlib_ImageZoom_S16_3_Nearest(mlib_work_image *param)
284 {
285   VARIABLE(mlib_s16);
286   mlib_s16 *dl = dp, *tsp, *tt;
287   mlib_s32 cx, y0 = -1, dx3 = 3*dx, dx7 = 4*dx + dx3;
288 
289   tsp = sp;
290   y = GetElemSubStruct(current, srcY) & MLIB_MASK;
291 
292   for (j = 0; j < height; j++) {
293 
294     if ((y0 >> MLIB_SHIFT) == (y >> MLIB_SHIFT)) {
295       mlib_ImageCopy_na((void*)((mlib_u8*)dl - dst_stride), (void*)dl, 6*width);
296     }
297     else {
298       mlib_s16 *dp = dl, *dend = dl + 3*width;
299 
300       vis_write_gsr(6);
301       x = GetElemSubStruct(current, srcX) & MLIB_MASK;
302 
303       while (((mlib_addr)dp & 7) && (dp < dend)) {
304         cx = x >> MLIB_SHIFT;
305         tt = tsp + 2*cx + cx;
306         dp[0] = tt[0];
307         dp[1] = tt[1];
308         dp[2] = tt[2];
309         x += dx;
310         dp += 3;
311       }
312 
313       x += dx3;
314 
315 #pragma pipeloop(0)
316       for (; dp <= dend - 12; dp += 12) {
317         mlib_d64 s0, s1, s2;
318 
319         cx = x >> MLIB_SHIFT;
320         tt = tsp + 2*cx + cx;
321         x -= dx;
322         s2 = vis_faligndata(vis_ld_u16_i(tt, 4), s2);
323         s2 = vis_faligndata(vis_ld_u16_i(tt, 2), s2);
324         s2 = vis_faligndata(vis_ld_u16_i(tt, 0), s2);
325 
326         cx = x >> MLIB_SHIFT;
327         tt = tsp + 2*cx + cx;
328         x -= dx;
329         s2 = vis_faligndata(vis_ld_u16_i(tt, 4), s2);
330         s1 = vis_faligndata(vis_ld_u16_i(tt, 2), s1);
331         s1 = vis_faligndata(vis_ld_u16_i(tt, 0), s1);
332 
333         cx = x >> MLIB_SHIFT;
334         tt = tsp + 2*cx + cx;
335         x -= dx;
336         s1 = vis_faligndata(vis_ld_u16_i(tt, 4), s1);
337         s1 = vis_faligndata(vis_ld_u16_i(tt, 2), s1);
338         s0 = vis_faligndata(vis_ld_u16_i(tt, 0), s0);
339 
340         cx = x >> MLIB_SHIFT;
341         tt = tsp + 2*cx + cx;
342         x += dx7;
343         s0 = vis_faligndata(vis_ld_u16_i(tt, 4), s0);
344         s0 = vis_faligndata(vis_ld_u16_i(tt, 2), s0);
345         s0 = vis_faligndata(vis_ld_u16_i(tt, 0), s0);
346 
347         ((mlib_d64*)dp)[0] = s0;
348         ((mlib_d64*)dp)[1] = s1;
349         ((mlib_d64*)dp)[2] = s2;
350       }
351 
352       x -= dx3;
353 
354       while (dp < dend) {
355         cx = x >> MLIB_SHIFT;
356         tt = tsp + 2*cx + cx;
357         dp[0] = tt[0];
358         dp[1] = tt[1];
359         dp[2] = tt[2];
360         x += dx;
361         dp += 3;
362       }
363     }
364 
365     y0 = y;
366     y += dy;
367     dl  = (void*)((mlib_u8*)dl + dst_stride);
368     tsp = (void*)((mlib_u8*)sp + (y >> MLIB_SHIFT) * src_stride);
369   }
370 
371   return MLIB_SUCCESS;
372 }
373 
374 /***************************************************************/
375 
mlib_ImageZoom_S16_1_Nearest(mlib_work_image * param)376 mlib_status mlib_ImageZoom_S16_1_Nearest(mlib_work_image *param)
377 {
378   VARIABLE(mlib_u16);
379   mlib_u16  *dl = dp, *tsp;
380   mlib_s32  y0 = -1, dx3 = 3*dx, dx7 = 4*dx + dx3;
381 
382   tsp = sp;
383   y = GetElemSubStruct(current, srcY) & MLIB_MASK;
384 
385   for (j = 0; j < height; j++) {
386 
387     if ((y0 >> MLIB_SHIFT) == (y >> MLIB_SHIFT)) {
388       mlib_ImageCopy_na((void*)((mlib_u8*)dl - dst_stride), (void*)dl, 2*width);
389     }
390     else {
391       mlib_u16 *dp = dl, *dend = dl + width;
392 
393       vis_write_gsr(6);
394       x = GetElemSubStruct(current, srcX) & MLIB_MASK;
395 
396       while (((mlib_addr)dp & 7) && (dp < dend)) {
397         *dp++ = tsp[x >> MLIB_SHIFT];
398         x += dx;
399       }
400 
401       x += dx3;
402 
403 #pragma pipeloop(0)
404       for (; dp <= dend - 4; dp += 4) {
405         mlib_d64 s0;
406 
407         s0 = vis_faligndata(vis_ld_u16_i(tsp, (x >> (MLIB_SHIFT - 1)) &~ 1), s0);
408         x -= dx;
409         s0 = vis_faligndata(vis_ld_u16_i(tsp, (x >> (MLIB_SHIFT - 1)) &~ 1), s0);
410         x -= dx;
411         s0 = vis_faligndata(vis_ld_u16_i(tsp, (x >> (MLIB_SHIFT - 1)) &~ 1), s0);
412         x -= dx;
413         s0 = vis_faligndata(vis_ld_u16_i(tsp, (x >> (MLIB_SHIFT - 1)) &~ 1), s0);
414         x += dx7;
415 
416         *(mlib_d64*)dp = s0;
417       }
418 
419       x -= dx3;
420 
421       while (dp < dend) {
422         *dp++ = tsp[x >> MLIB_SHIFT];
423         x += dx;
424       }
425     }
426 
427     y0 = y;
428     y += dy;
429     dl  = (void*)((mlib_u8*)dl + dst_stride);
430     tsp = (void*)((mlib_u8*)sp + (y >> MLIB_SHIFT) * src_stride);
431   }
432 
433   return MLIB_SUCCESS;
434 }
435 
436 /***************************************************************/
437