Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/native/libmlib_image/mlib_ImageConvKernelConvert.c
41149 views
1
/*
2
* Copyright (c) 2003, 2020, 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_ImageConvKernelConvert - Convert convolution kernel from
30
* floating point version to integer
31
* version.
32
*
33
* SYNOPSIS
34
* mlib_status mlib_ImageConvKernelConvert(mlib_s32 *ikernel,
35
* mlib_s32 *iscale,
36
* const mlib_d64 *fkernel,
37
* mlib_s32 m,
38
* mlib_s32 n,
39
* mlib_type type);
40
*
41
* ARGUMENT
42
* ikernel integer kernel
43
* iscale scaling factor of the integer kernel
44
* fkernel floating-point kernel
45
* m width of the convolution kernel
46
* n height of the convolution kernel
47
* type image type
48
*
49
* DESCRIPTION
50
* Convert a floating point convolution kernel to integer kernel
51
* with scaling factor. The result integer kernel and scaling factor
52
* can be used in convolution functions directly without overflow.
53
*
54
* RESTRICTION
55
* The type can be MLIB_BYTE, MLIB_SHORT, MLIB_USHORT or MLIB_INT.
56
*/
57
58
#include <stdlib.h>
59
#include "mlib_image.h"
60
#include "mlib_SysMath.h"
61
#include "mlib_ImageConv.h"
62
63
/***************************************************************/
64
65
#define CLAMP_S32(dst, src) { \
66
mlib_d64 s0 = (mlib_d64)(src); \
67
if (s0 > (mlib_d64)MLIB_S32_MAX) s0 = (mlib_d64)MLIB_S32_MAX; \
68
if (s0 < (mlib_d64)MLIB_S32_MIN) s0 = (mlib_d64)MLIB_S32_MIN; \
69
dst = (mlib_s32)s0; \
70
}
71
72
/***************************************************************/
73
JNIEXPORT
74
mlib_status mlib_ImageConvKernelConvert(mlib_s32 *ikernel,
75
mlib_s32 *iscale,
76
const mlib_d64 *fkernel,
77
mlib_s32 m,
78
mlib_s32 n,
79
mlib_type type)
80
{
81
mlib_d64 sum_pos, sum_neg, sum, norm, max, f;
82
mlib_s32 isum_pos, isum_neg, isum, test;
83
mlib_s32 i, scale, scale1, chk_flag;
84
85
if (ikernel == NULL || iscale == NULL || fkernel == NULL || m < 1 || n < 1) {
86
return MLIB_FAILURE;
87
}
88
89
if ((type == MLIB_BYTE) || (type == MLIB_SHORT) || (type == MLIB_USHORT)) {
90
91
if (type != MLIB_SHORT) { /* MLIB_BYTE, MLIB_USHORT */
92
sum_pos = 0;
93
sum_neg = 0;
94
95
for (i = 0; i < m * n; i++) {
96
if (fkernel[i] > 0)
97
sum_pos += fkernel[i];
98
else
99
sum_neg -= fkernel[i];
100
}
101
102
sum = (sum_pos > sum_neg) ? sum_pos : sum_neg;
103
scale = mlib_ilogb(sum);
104
scale++;
105
106
scale = 31 - scale;
107
}
108
else { /* MLIB_SHORT */
109
sum = 0;
110
max = 0;
111
112
for (i = 0; i < m * n; i++) {
113
f = mlib_fabs(fkernel[i]);
114
sum += f;
115
max = (max > f) ? max : f;
116
}
117
118
scale1 = mlib_ilogb(max) + 1;
119
scale = mlib_ilogb(sum);
120
scale = (scale > scale1) ? scale : scale1;
121
scale++;
122
123
scale = 32 - scale;
124
}
125
126
if (scale <= 16)
127
return MLIB_FAILURE;
128
if (scale > 31)
129
scale = 31;
130
131
*iscale = scale;
132
133
chk_flag = mlib_ImageConvVersion(m, n, scale, type);
134
135
if (!chk_flag) {
136
norm = (1u << scale);
137
for (i = 0; i < m * n; i++) {
138
CLAMP_S32(ikernel[i], fkernel[i] * norm);
139
}
140
141
return MLIB_SUCCESS;
142
}
143
144
/* try to round coefficients */
145
if (chk_flag == 3)
146
scale1 = 16; /* MMX */
147
else
148
scale1 = (type == MLIB_BYTE) ? 8 : 16;
149
norm = (1u << (scale - scale1));
150
151
for (i = 0; i < m * n; i++) {
152
if (fkernel[i] > 0)
153
ikernel[i] = (mlib_s32) (fkernel[i] * norm + 0.5);
154
else
155
ikernel[i] = (mlib_s32) (fkernel[i] * norm - 0.5);
156
}
157
158
isum_pos = 0;
159
isum_neg = 0;
160
test = 0;
161
162
for (i = 0; i < m * n; i++) {
163
if (ikernel[i] > 0)
164
isum_pos += ikernel[i];
165
else
166
isum_neg -= ikernel[i];
167
}
168
169
if (type == MLIB_BYTE || type == MLIB_USHORT) {
170
isum = (isum_pos > isum_neg) ? isum_pos : isum_neg;
171
172
if (isum >= (1 << (31 - scale1)))
173
test = 1;
174
}
175
else {
176
isum = isum_pos + isum_neg;
177
178
if (isum >= (1 << (32 - scale1)))
179
test = 1;
180
for (i = 0; i < m * n; i++) {
181
if (abs(ikernel[i]) >= (1 << (31 - scale1)))
182
test = 1;
183
}
184
}
185
186
if (test == 1) { /* rounding according scale1 cause overflow, truncate instead of round */
187
for (i = 0; i < m * n; i++)
188
ikernel[i] = (mlib_s32) (fkernel[i] * norm) << scale1;
189
}
190
else { /* rounding is Ok */
191
for (i = 0; i < m * n; i++)
192
ikernel[i] = ikernel[i] << scale1;
193
}
194
195
return MLIB_SUCCESS;
196
}
197
else if ((type == MLIB_INT) || (type == MLIB_BIT)) {
198
max = 0;
199
200
for (i = 0; i < m * n; i++) {
201
f = mlib_fabs(fkernel[i]);
202
max = (max > f) ? max : f;
203
}
204
205
scale = mlib_ilogb(max);
206
207
if (scale > 29)
208
return MLIB_FAILURE;
209
210
if (scale < -100)
211
scale = -100;
212
213
*iscale = 29 - scale;
214
scale = 29 - scale;
215
216
norm = 1.0;
217
while (scale > 30) {
218
norm *= (1 << 30);
219
scale -= 30;
220
}
221
222
norm *= (1 << scale);
223
224
for (i = 0; i < m * n; i++) {
225
if (fkernel[i] > 0) {
226
CLAMP_S32(ikernel[i], fkernel[i] * norm + 0.5);
227
}
228
else {
229
CLAMP_S32(ikernel[i], fkernel[i] * norm - 0.5);
230
}
231
}
232
233
return MLIB_SUCCESS;
234
}
235
else {
236
return MLIB_FAILURE;
237
}
238
}
239
240
/***************************************************************/
241
242