55#include " android/bitmap.h"
66#include " libyuv/convert_argb.h"
77#include < vector>
8- #include < float.h>
9- #include < arm_fp16.h>
108#include " jni_exception.h"
119#include " scaler.h"
1210#include < android/log.h>
@@ -28,6 +26,30 @@ int androidOSVersion() {
2826 return android_get_device_api_level ();
2927}
3028
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+
3153struct heif_error writeHeifData (struct heif_context *ctx,
3254 const void *data,
3355 size_t size,
@@ -131,8 +153,8 @@ jbyteArray encodeBitmap(JNIEnv *env, jobject thiz,
131153 uint8_t *imgData = heif_image_get_plane (image, heif_channel_interleaved, &stride);
132154 if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
133155 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 );
136158 } else if (info.format == ANDROID_BITMAP_FORMAT_RGB_565) {
137159 libyuv::RGB565ToARGB (sourceData.data (), (int ) info.stride , imgData,
138160 stride, (int ) info.width , (int ) info.height );
@@ -167,7 +189,7 @@ jbyteArray encodeBitmap(JNIEnv *env, jobject thiz,
167189 std::shared_ptr<char > dstARGB (
168190 static_cast <char *>(malloc (info.width * info.height * 4 * sizeof (uint16_t ))),
169191 [](char *f) { free (f); });
170- auto * srcData = reinterpret_cast <uint8_t *>(sourceData.data ());
192+ auto srcData = reinterpret_cast <uint8_t *>(sourceData.data ());
171193 uint16_t tmpR;
172194 uint16_t tmpG;
173195 uint16_t tmpB;
@@ -177,16 +199,14 @@ jbyteArray encodeBitmap(JNIEnv *env, jobject thiz,
177199 int dstStride = (int ) info.width * 4 * (int ) sizeof (uint16_t );
178200
179201 for (int y = 0 ; y < info.height ; ++y) {
180-
181202 auto srcPtr = reinterpret_cast <uint16_t *>(srcData);
182203 auto dstPtr = reinterpret_cast <uint16_t *>(data64Ptr);
183-
184204 for (int x = 0 ; x < info.width ; ++x) {
185205 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 );
190210
191211 dstPtr[0 ] = tmpR;
192212 dstPtr[1 ] = tmpG;
@@ -214,25 +234,37 @@ jbyteArray encodeBitmap(JNIEnv *env, jobject thiz,
214234 std::shared_ptr<char > dstARGB (
215235 static_cast <char *>(malloc (info.width * info.height * 4 * sizeof (uint8_t ))),
216236 [](char *f) { free (f); });
217- auto * srcData = reinterpret_cast <float16_t *>(sourceData.data ());
237+ auto srcData = reinterpret_cast <uint8_t *>(sourceData.data ());
218238 char tmpR;
219239 char tmpG;
220240 char tmpB;
221241 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;
234266 }
235- auto * dataPtr = reinterpret_cast <void *>(dstARGB.get ());
267+ auto dataPtr = reinterpret_cast <void *>(dstARGB.get ());
236268 auto srcY = (char *) dataPtr;
237269 auto dstY = (char *) imgData;
238270 const auto sourceStride = info.width * 4 * sizeof (uint8_t );
@@ -683,8 +715,8 @@ Java_com_radzivon_bartoshyk_avif_coder_HeifCoder_decodeImpl(JNIEnv *env, jobject
683715 heif_image_release (img);
684716 }
685717
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); });
688720
689721 if (useBitmapHalf16Floats) {
690722 const float scale = 1 .0f / float ((1 << bitDepth) - 1 );
@@ -752,13 +784,27 @@ Java_com_radzivon_bartoshyk_avif_coder_HeifCoder_decodeImpl(JNIEnv *env, jobject
752784 jobject bitmapObj = env->CallStaticObjectMethod (bitmapClass, createBitmapMethodID,
753785 imageWidth, imageHeight, rgba8888Obj);
754786
787+ AndroidBitmapInfo info;
788+ if (AndroidBitmap_getInfo (env, bitmapObj, &info) < 0 ) {
789+ throwPixelsException (env);
790+ return static_cast <jbyteArray>(nullptr );
791+ }
792+
755793 void *addr;
756794 if (AndroidBitmap_lockPixels (env, bitmapObj, &addr) != 0 ) {
757795 throwPixelsException (env);
758796 return static_cast <jobject>(nullptr );
759797 }
760798
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+ }
762808
763809 if (AndroidBitmap_unlockPixels (env, bitmapObj) != 0 ) {
764810 throwPixelsException (env);
0 commit comments