5
5
#include " android/bitmap.h"
6
6
#include " libyuv/convert_argb.h"
7
7
#include < vector>
8
- #include < float.h>
9
- #include < arm_fp16.h>
10
8
#include " jni_exception.h"
11
9
#include " scaler.h"
12
10
#include < android/log.h>
@@ -28,6 +26,30 @@ int androidOSVersion() {
28
26
return android_get_device_api_level ();
29
27
}
30
28
29
+ void
30
+ copyRGBA16 (std::shared_ptr<uint8_t > &source, int srcStride, uint8_t *destination, int dstStride,
31
+ int width, int height) {
32
+ auto src = reinterpret_cast <uint8_t *>(source.get ());
33
+ auto dst = reinterpret_cast <uint8_t *>(destination);
34
+
35
+ for (int y = 0 ; y < height; ++y) {
36
+
37
+ auto srcPtr = reinterpret_cast <uint16_t *>(src);
38
+ auto dstPtr = reinterpret_cast <uint16_t *>(dst);
39
+
40
+ for (int x = 0 ; x < width; ++x) {
41
+ auto srcPtr64 = reinterpret_cast <uint64_t *>(srcPtr);
42
+ auto dstPtr64 = reinterpret_cast <uint64_t *>(dstPtr);
43
+ dstPtr64[0 ] = srcPtr64[0 ];
44
+ srcPtr += 4 ;
45
+ dstPtr += 4 ;
46
+ }
47
+
48
+ src += srcStride;
49
+ dst += dstStride;
50
+ }
51
+ }
52
+
31
53
struct heif_error writeHeifData (struct heif_context *ctx,
32
54
const void *data,
33
55
size_t size,
@@ -131,8 +153,8 @@ jbyteArray encodeBitmap(JNIEnv *env, jobject thiz,
131
153
uint8_t *imgData = heif_image_get_plane (image, heif_channel_interleaved, &stride);
132
154
if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
133
155
libyuv::ARGBCopy (sourceData.data (), (int ) info.stride ,
134
- imgData,
135
- stride, (int ) info.width , (int ) info.height );
156
+ imgData,
157
+ stride, (int ) info.width , (int ) info.height );
136
158
} else if (info.format == ANDROID_BITMAP_FORMAT_RGB_565) {
137
159
libyuv::RGB565ToARGB (sourceData.data (), (int ) info.stride , imgData,
138
160
stride, (int ) info.width , (int ) info.height );
@@ -167,7 +189,7 @@ jbyteArray encodeBitmap(JNIEnv *env, jobject thiz,
167
189
std::shared_ptr<char > dstARGB (
168
190
static_cast <char *>(malloc (info.width * info.height * 4 * sizeof (uint16_t ))),
169
191
[](char *f) { free (f); });
170
- auto * srcData = reinterpret_cast <uint8_t *>(sourceData.data ());
192
+ auto srcData = reinterpret_cast <uint8_t *>(sourceData.data ());
171
193
uint16_t tmpR;
172
194
uint16_t tmpG;
173
195
uint16_t tmpB;
@@ -177,16 +199,14 @@ jbyteArray encodeBitmap(JNIEnv *env, jobject thiz,
177
199
int dstStride = (int ) info.width * 4 * (int ) sizeof (uint16_t );
178
200
179
201
for (int y = 0 ; y < info.height ; ++y) {
180
-
181
202
auto srcPtr = reinterpret_cast <uint16_t *>(srcData);
182
203
auto dstPtr = reinterpret_cast <uint16_t *>(data64Ptr);
183
-
184
204
for (int x = 0 ; x < info.width ; ++x) {
185
205
auto alpha = half_to_float (srcPtr[3 ]);
186
- tmpR = (uint16_t ) ( half_to_float (srcPtr[0 ]) / scale);
187
- tmpG = (uint16_t ) ( half_to_float (srcPtr[1 ]) / scale);
188
- tmpB = (uint16_t ) ( half_to_float (srcPtr[2 ]) / scale);
189
- tmpA = (uint16_t ) ( alpha / scale);
206
+ tmpR = (uint16_t ) fmin ( fmax (( half_to_float (srcPtr[0 ]) / scale), 0 ), 1023 );
207
+ tmpG = (uint16_t ) fmin ( fmax (( half_to_float (srcPtr[1 ]) / scale), 0 ), 1023 );
208
+ tmpB = (uint16_t ) fmin ( fmax (( half_to_float (srcPtr[2 ]) / scale), 0 ), 1023 );
209
+ tmpA = (uint16_t ) fmin ( fmax (( alpha / scale), 0 ), 1023 );
190
210
191
211
dstPtr[0 ] = tmpR;
192
212
dstPtr[1 ] = tmpG;
@@ -214,25 +234,37 @@ jbyteArray encodeBitmap(JNIEnv *env, jobject thiz,
214
234
std::shared_ptr<char > dstARGB (
215
235
static_cast <char *>(malloc (info.width * info.height * 4 * sizeof (uint8_t ))),
216
236
[](char *f) { free (f); });
217
- auto * srcData = reinterpret_cast <float16_t *>(sourceData.data ());
237
+ auto srcData = reinterpret_cast <uint8_t *>(sourceData.data ());
218
238
char tmpR;
219
239
char tmpG;
220
240
char tmpB;
221
241
char tmpA;
222
- auto *data64Ptr = reinterpret_cast <uint32_t *>(dstARGB.get ());
223
- const float maxColors = (float ) pow (2.0 , 8 ) - 1 ;
224
- for (int i = 0 , k = 0 ; i < std::min (info.stride * info.height ,
225
- info.width * info.height * 4 ); i += 4 , k += 1 ) {
226
- tmpR = (char ) (srcData[i] * maxColors);
227
- tmpG = (char ) (srcData[i + 1 ] * maxColors);
228
- tmpB = (char ) (srcData[i + 2 ] * maxColors);
229
- tmpA = (char ) (srcData[i + 3 ] * maxColors);
230
- uint32_t color =
231
- ((uint32_t ) tmpA & 0xff ) << 24 | ((uint32_t ) tmpB & 0xff ) << 16 |
232
- ((uint32_t ) tmpG & 0xff ) << 8 | ((uint32_t ) tmpR & 0xff );
233
- data64Ptr[k] = color;
242
+ const float scale = 1 .0f / float ((1 << bitDepth) - 1 );
243
+ int dstStride = (int ) info.width * 4 * (int ) sizeof (uint8_t );
244
+ auto data64Ptr = reinterpret_cast <uint8_t *>(dstARGB.get ());
245
+ for (int y = 0 ; y < info.height ; ++y) {
246
+ auto srcPtr = reinterpret_cast <uint16_t *>(srcData);
247
+ auto dstPtr = reinterpret_cast <uint8_t *>(data64Ptr);
248
+ for (int x = 0 ; x < info.width ; ++x) {
249
+ auto alpha = half_to_float (srcPtr[3 ]);
250
+ tmpR = (uint8_t ) fmin (fmax ((half_to_float (srcPtr[0 ]) / scale), 0 ), 255 );
251
+ tmpG = (uint8_t ) fmin (fmax ((half_to_float (srcPtr[1 ]) / scale), 0 ), 255 );
252
+ tmpB = (uint8_t ) fmin (fmax ((half_to_float (srcPtr[2 ]) / scale), 0 ), 255 );
253
+ tmpA = (uint8_t ) fmin (fmax ((alpha / scale), 0 ), 255 );
254
+
255
+ dstPtr[0 ] = tmpR;
256
+ dstPtr[1 ] = tmpG;
257
+ dstPtr[2 ] = tmpB;
258
+ dstPtr[3 ] = tmpA;
259
+
260
+ srcPtr += 4 ;
261
+ dstPtr += 4 ;
262
+ }
263
+
264
+ srcData += info.stride ;
265
+ data64Ptr += dstStride;
234
266
}
235
- auto * dataPtr = reinterpret_cast <void *>(dstARGB.get ());
267
+ auto dataPtr = reinterpret_cast <void *>(dstARGB.get ());
236
268
auto srcY = (char *) dataPtr;
237
269
auto dstY = (char *) imgData;
238
270
const auto sourceStride = info.width * 4 * sizeof (uint8_t );
@@ -683,8 +715,8 @@ Java_com_radzivon_bartoshyk_avif_coder_HeifCoder_decodeImpl(JNIEnv *env, jobject
683
715
heif_image_release (img);
684
716
}
685
717
686
- std::shared_ptr<char > dstARGB (static_cast <char *>(malloc (stride * imageHeight)),
687
- [](char *f) { free (f); });
718
+ std::shared_ptr<uint8_t > dstARGB (static_cast <uint8_t *>(malloc (stride * imageHeight)),
719
+ [](uint8_t *f) { free (f); });
688
720
689
721
if (useBitmapHalf16Floats) {
690
722
const float scale = 1 .0f / float ((1 << bitDepth) - 1 );
@@ -752,13 +784,27 @@ Java_com_radzivon_bartoshyk_avif_coder_HeifCoder_decodeImpl(JNIEnv *env, jobject
752
784
jobject bitmapObj = env->CallStaticObjectMethod (bitmapClass, createBitmapMethodID,
753
785
imageWidth, imageHeight, rgba8888Obj);
754
786
787
+ AndroidBitmapInfo info;
788
+ if (AndroidBitmap_getInfo (env, bitmapObj, &info) < 0 ) {
789
+ throwPixelsException (env);
790
+ return static_cast <jbyteArray>(nullptr );
791
+ }
792
+
755
793
void *addr;
756
794
if (AndroidBitmap_lockPixels (env, bitmapObj, &addr) != 0 ) {
757
795
throwPixelsException (env);
758
796
return static_cast <jobject>(nullptr );
759
797
}
760
798
761
- std::copy (dstARGB.get (), dstARGB.get () + stride * imageHeight, (char *) addr);
799
+ if (useBitmapHalf16Floats) {
800
+ copyRGBA16 (dstARGB, stride, reinterpret_cast <uint8_t *>(addr), (int ) info.stride ,
801
+ (int ) info.width ,
802
+ (int ) info.height );
803
+ } else {
804
+ libyuv::ARGBCopy (reinterpret_cast <uint8_t *>(dstARGB.get ()), stride,
805
+ reinterpret_cast <uint8_t *>(addr), (int ) info.stride , (int ) info.width ,
806
+ (int ) info.height );
807
+ }
762
808
763
809
if (AndroidBitmap_unlockPixels (env, bitmapObj) != 0 ) {
764
810
throwPixelsException (env);
0 commit comments