1818#include < math.h>
1919#include < limits>
2020#include " attenuate_alpha.h"
21+ #include " halfFloats.h"
2122
2223struct AvifMemEncoder {
2324 std::vector<char > buffer;
@@ -83,12 +84,17 @@ jbyteArray encodeBitmap(JNIEnv *env, jobject thiz,
8384 return static_cast <jbyteArray>(nullptr );
8485 }
8586
87+
8688 void *addr;
8789 if (AndroidBitmap_lockPixels (env, bitmap, &addr) != 0 ) {
8890 throwPixelsException (env);
8991 return static_cast <jbyteArray>(nullptr );
9092 }
9193
94+ std::vector<uint8_t > sourceData (info.height * info.stride );
95+ std::copy (reinterpret_cast <uint8_t *>(addr),
96+ reinterpret_cast <uint8_t *>(addr) + info.height * info.stride , sourceData.data ());
97+
9298 heif_image *image;
9399 heif_chroma chroma = heif_chroma_interleaved_RGBA;
94100 if (info.format == ANDROID_BITMAP_FORMAT_RGBA_F16 &&
@@ -124,10 +130,10 @@ jbyteArray encodeBitmap(JNIEnv *env, jobject thiz,
124130 int stride;
125131 uint8_t *imgData = heif_image_get_plane (image, heif_channel_interleaved, &stride);
126132 if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
127- libyuv::ARGBCopy (reinterpret_cast < const uint8_t *>(addr ), (int ) info.stride , imgData,
133+ libyuv::ARGBCopy (sourceData. data ( ), (int ) info.stride , imgData,
128134 stride, (int ) info.width , (int ) info.height );
129135 } else if (info.format == ANDROID_BITMAP_FORMAT_RGB_565) {
130- libyuv::RGB565ToARGB (reinterpret_cast < const uint8_t *>(addr ), (int ) info.stride , imgData,
136+ libyuv::RGB565ToARGB (sourceData. data ( ), (int ) info.stride , imgData,
131137 stride, (int ) info.width , (int ) info.height );
132138 for (int i = 0 ; i < stride / 4 * info.height ; i += 4 ) {
133139 imgData[i] = imgData[i + 1 ]; // R
@@ -138,14 +144,14 @@ jbyteArray encodeBitmap(JNIEnv *env, jobject thiz,
138144 } else if (info.format == ANDROID_BITMAP_FORMAT_RGBA_1010102) {
139145 if (heifCompressionFormat == heif_compression_HEVC) {
140146 auto dstY = (char *) imgData;
141- auto srcY = (char *) addr ;
147+ auto srcY = (char *) sourceData. data () ;
142148 for (int y = 0 ; y < info.height ; ++y) {
143149 memcpy (dstY, srcY, info.width * 4 * sizeof (uint32_t ));
144150 srcY += info.width * sizeof (uint64_t );
145151 dstY += stride;
146152 }
147153 } else {
148- libyuv::AR30ToARGB (static_cast < const uint8_t *>(addr ), (int ) info.stride , imgData,
154+ libyuv::AR30ToARGB (sourceData. data ( ), (int ) info.stride , imgData,
149155 stride, (int ) info.width ,
150156 (int ) info.height );
151157 for (int i = 0 ; i < stride / 4 * info.height ; i += 4 ) {
@@ -160,39 +166,53 @@ jbyteArray encodeBitmap(JNIEnv *env, jobject thiz,
160166 std::shared_ptr<char > dstARGB (
161167 static_cast <char *>(malloc (info.width * info.height * 4 * sizeof (uint16_t ))),
162168 [](char *f) { free (f); });
163- auto *srcData = static_cast < float16_t *>(addr );
169+ auto *srcData = reinterpret_cast < uint8_t *>(sourceData. data () );
164170 uint16_t tmpR;
165171 uint16_t tmpG;
166172 uint16_t tmpB;
167173 uint16_t tmpA;
168- auto *data64Ptr = reinterpret_cast <uint64_t *>(dstARGB.get ());
169- const float maxColors = (float ) pow (2.0 , bitDepth) - 1 ;
170- for (int i = 0 , k = 0 ; i < std::min (info.stride * info.height ,
171- info.width * info.height * 4 ); i += 4 , k += 1 ) {
172- tmpR = (uint16_t ) (srcData[i] * maxColors);
173- tmpG = (uint16_t ) (srcData[i + 1 ] * maxColors);
174- tmpB = (uint16_t ) (srcData[i + 2 ] * maxColors);
175- tmpA = (uint16_t ) (srcData[i + 3 ] * maxColors);
176- uint64_t color =
177- ((uint64_t ) tmpA & 0xffff ) << 48 | ((uint64_t ) tmpB & 0xffff ) << 32 |
178- ((uint64_t ) tmpG & 0xffff ) << 16 | ((uint64_t ) tmpR & 0xffff );
179- data64Ptr[k] = color;
174+ auto data64Ptr = reinterpret_cast <uint8_t *>(dstARGB.get ());
175+ const float scale = 1 .0f / float ((1 << bitDepth) - 1 );
176+ int dstStride = (int ) info.width * 4 * (int ) sizeof (uint16_t );
177+
178+ for (int y = 0 ; y < info.height ; ++y) {
179+
180+ auto srcPtr = reinterpret_cast <uint16_t *>(srcData);
181+ auto dstPtr = reinterpret_cast <uint64_t *>(data64Ptr);
182+
183+ for (int x = 0 ; x < info.width ; ++x) {
184+ auto alpha = half_to_float (srcPtr[3 ]);
185+ tmpR = (uint16_t ) (half_to_float (srcPtr[0 ]) / scale / (alpha != 0 ? alpha : 1 ));
186+ tmpG = (uint16_t ) (half_to_float (srcPtr[1 ]) / scale / (alpha != 0 ? alpha : 1 ));
187+ tmpB = (uint16_t ) (half_to_float (srcPtr[2 ]) / scale / (alpha != 0 ? alpha : 1 ));
188+ tmpA = (uint16_t ) (alpha / scale);
189+ uint64_t color =
190+ ((uint64_t ) tmpA & 0xffff ) << 48 | ((uint64_t ) tmpB & 0xffff ) << 32 |
191+ ((uint64_t ) tmpG & 0xffff ) << 16 | ((uint64_t ) tmpR & 0xffff );
192+ dstPtr[0 ] = color;
193+
194+ srcPtr += 4 ;
195+ dstPtr += 1 ;
196+ }
197+
198+ srcData += info.stride ;
199+ data64Ptr += dstStride;
180200 }
181- auto * dataPtr = reinterpret_cast <void *>(dstARGB.get ());
201+ auto dataPtr = reinterpret_cast <void *>(dstARGB.get ());
182202 auto srcY = (char *) dataPtr;
183203 auto dstY = (char *) imgData;
184204 const auto sourceStride = info.width * 4 * sizeof (uint16_t );
185205 for (int y = 0 ; y < info.height ; ++y) {
186206 memcpy (dstY, srcY, sourceStride);
187- srcY += sourceStride ;
207+ srcY += dstStride ;
188208 dstY += stride;
189209 }
190210 dstARGB.reset ();
191211 } else {
192212 std::shared_ptr<char > dstARGB (
193213 static_cast <char *>(malloc (info.width * info.height * 4 * sizeof (uint8_t ))),
194214 [](char *f) { free (f); });
195- auto *srcData = static_cast <float16_t *>(addr );
215+ auto *srcData = reinterpret_cast <float16_t *>(sourceData. data () );
196216 char tmpR;
197217 char tmpG;
198218 char tmpB;
0 commit comments