4848#include " colorspace/HDRTransferAdapter.h"
4949#include " imagebits/RGBAlpha.h"
5050#include " imagebits/Rgb565.h"
51+ #include " DataSpaceToNCLX.hpp"
5152
5253using namespace std ;
5354
@@ -72,7 +73,7 @@ struct heif_error writeHeifData(struct heif_context *ctx,
7273
7374jbyteArray encodeBitmap (JNIEnv *env, jobject thiz,
7475 jobject bitmap, heif_compression_format heifCompressionFormat,
75- int quality) {
76+ int quality, int dataSpace ) {
7677 std::shared_ptr<heif_context> ctx (heif_context_alloc (),
7778 [](heif_context *c) { heif_context_free (c); });
7879 if (!ctx) {
@@ -135,15 +136,31 @@ jbyteArray encodeBitmap(JNIEnv *env, jobject thiz,
135136 heifCompressionFormat == heif_compression_AV1)) {
136137 chroma = heif_chroma_interleaved_RRGGBBAA_LE;
137138 }
138- result = heif_image_create ((int ) info.width , (int ) info.height , heif_colorspace_RGB,
139- chroma, &image);
139+
140+ result = heif_image_create ((int ) info.width , (int ) info.height ,
141+ heif_colorspace_RGB, chroma, &image);
140142 if (result.code != heif_error_Ok) {
141143 std::string choke (result.message );
142144 std::string str = " Can't create encoded image with exception: " + choke;
143145 throwException (env, str);
144146 return static_cast <jbyteArray>(nullptr );
145147 }
146148
149+ std::shared_ptr<heif_color_profile_nclx> profile (heif_nclx_color_profile_alloc (), [](auto x) {
150+ heif_nclx_color_profile_free (x);
151+ });
152+
153+ bool nclxResult = coder::nclxFromDataSpace (dataSpace, profile.get ());
154+ if (nclxResult) {
155+ result = heif_image_set_nclx_color_profile (image, profile.get ());
156+ if (result.code != heif_error_Ok) {
157+ std::string choke (result.message );
158+ std::string str = " Can't set required color profiel: " + choke;
159+ throwException (env, str);
160+ return static_cast <jbyteArray>(nullptr );
161+ }
162+ }
163+
147164 int bitDepth = 8 ;
148165 if (info.format == ANDROID_BITMAP_FORMAT_RGB_565) {
149166 bitDepth = 8 ;
@@ -174,21 +191,24 @@ jbyteArray encodeBitmap(JNIEnv *env, jobject thiz,
174191 imgData, stride, (int ) info.width , (int ) info.height , 8 , 255 );
175192 } else if (info.format == ANDROID_BITMAP_FORMAT_RGBA_1010102) {
176193 if (heifCompressionFormat == heif_compression_HEVC) {
177- RGBA1010102ToU8 (reinterpret_cast <uint8_t *>(sourceData.data ()), (int ) info.stride ,
178- reinterpret_cast <uint8_t *>(imgData), stride, (int ) info.width ,
179- (int ) info.height );
194+ coder::RGBA1010102ToUnsigned (reinterpret_cast <const uint8_t *>(sourceData.data ()),
195+ (int ) info.stride ,
196+ reinterpret_cast <uint8_t *>(imgData), stride,
197+ (int ) info.width , (int ) info.height , 8 );
198+ heif_image_set_premultiplied_alpha (image, true );
180199 } else {
181- RGBA1010102ToU16 (reinterpret_cast <uint8_t *>(sourceData.data ()), (int ) info.stride ,
182- reinterpret_cast <uint16_t *>(imgData), stride, (int ) info.width ,
183- (int ) info.height );
200+ coder::RGBA1010102ToUnsigned (reinterpret_cast <uint8_t *>(sourceData.data ()),
201+ (int ) info.stride ,
202+ reinterpret_cast <uint16_t *>(imgData), stride,
203+ (int ) info.width , (int ) info.height , 10 );
184204 }
185205 } else if (info.format == ANDROID_BITMAP_FORMAT_RGBA_F16) {
186206 if (heifCompressionFormat == heif_compression_AV1) {
187207 coder::RGBAF16BitToNBitU16 (reinterpret_cast <const uint16_t *>(sourceData.data ()),
188- (int ) info.stride ,
189- reinterpret_cast <uint16_t *>(imgData), stride,
190- (int ) info.width ,
191- (int ) info.height , 10 );
208+ (int ) info.stride ,
209+ reinterpret_cast <uint16_t *>(imgData), stride,
210+ (int ) info.width ,
211+ (int ) info.height , 10 );
192212 } else {
193213 coder::RGBAF16BitToNBitU8 (reinterpret_cast <const uint16_t *>(sourceData.data ()),
194214 (int ) info.stride ,
@@ -205,59 +225,11 @@ jbyteArray encodeBitmap(JNIEnv *env, jobject thiz,
205225 });
206226 options->version = 5 ;
207227 options->image_orientation = heif_orientation_normal;
208- // options->output_nclx_profile = nullptr;
209- // options->save_two_colr_boxes_when_ICC_and_nclx_available = false;
210228
211229 result = heif_context_encode_image (ctx.get (), image, encoder.get (), options.get (), &handle);
212230 options.reset ();
213231 if (handle && result.code == heif_error_Ok) {
214232 heif_context_set_primary_image (ctx.get (), handle);
215- //
216- // std::time_t currentTime = std::time(nullptr);
217- // std::tm *timeInfo = std::localtime(¤tTime);
218- //
219- // // Format the date and time
220- // char formattedTime[20]; // Buffer for the formatted time
221- // std::strftime(formattedTime, sizeof(formattedTime), "%Y:%m:%d %H:%M:%S", timeInfo);
222- // std::string dateTime(formattedTime);
223- //
224- // std::string format(heifCompressionFormat == heif_compression_AV1 ? "AVIF" : "HEIC");
225- //
226- // std::string xmpMetadata = "<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>"
227- // "<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='XMP Core 5.5.0'>"
228- // "<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>"
229- // "<rdf:Description rdf:about='' xmlns:dc='http://purl.org/dc/elements/1.1/'>"
230- // "<dc:title>Generated image by avif-coder</dc:title>"
231- // "<dc:creator>avif-coder</dc:creator>"
232- // "<dc:description>A image was created by avif-coder (https://github.com/awxkee/avif-coder)</dc:description>"
233- // "<dc:date>" + dateTime + "</dc:date>\n"
234- // "<dc:publisher>https://github.com/awxkee/avif-coder>"
235- // "<dc:format>" + format + "</dc:format>"
236- // "</rdf:Description>"
237- // "<rdf:Description rdf:about='' xmlns:exif='http://ns.adobe.com/exif/1.0/'>\n"
238- // "<exif:ColorSpace>sRGB</exif:ColorSpace>\n"
239- // "<exif:ColorProfile>sRGB IEC61966-2.1</exif:ColorProfile>\n"
240- // "</rdf:Description>\n"
241- // "<rdf:Description rdf:about='' xmlns:xmp='http://ns.adobe.com/xap/1.0/'>\n"
242- // "<xmp:CreatorTool>avif-coder (https://github.com/awxkee/avif-coder)</xmp:CreatorTool>\n"
243- // "<xmp:ModifyDate>" +
244- // dateTime +
245- // "</xmp:ModifyDate>\n"
246- // "</rdf:Description>\n"
247- // "</rdf:RDF>"
248- // "</x:xmpmeta>"
249- // "<?xpacket end='w'?>";
250- //
251- // result = heif_context_add_XMP_metadata(ctx.get(), handle,
252- // reinterpret_cast<const void *>(xmpMetadata.data()),
253- // static_cast<int>(xmpMetadata.size()));
254- // if (result.code != heif_error_Ok) {
255- // heif_image_handle_release(handle);
256- // heif_image_release(image);
257- // throwCantEncodeImageException(env, result.message);
258- // return static_cast<jbyteArray>(nullptr);
259- // }
260-
261233 heif_image_handle_release (handle);
262234 }
263235 heif_image_release (image);
@@ -293,9 +265,10 @@ jbyteArray encodeBitmap(JNIEnv *env, jobject thiz,
293265extern " C"
294266JNIEXPORT jbyteArray JNICALL
295267Java_com_radzivon_bartoshyk_avif_coder_HeifCoder_encodeAvifImpl (JNIEnv *env, jobject thiz,
296- jobject bitmap, jint quality) {
268+ jobject bitmap, jint quality,
269+ jint dataSpace) {
297270 try {
298- return encodeBitmap (env, thiz, bitmap, heif_compression_AV1, quality);
271+ return encodeBitmap (env, thiz, bitmap, heif_compression_AV1, quality, dataSpace );
299272 } catch (std::bad_alloc &err) {
300273 std::string exception = " Not enough memory to encode this image" ;
301274 throwException (env, exception);
@@ -306,9 +279,10 @@ Java_com_radzivon_bartoshyk_avif_coder_HeifCoder_encodeAvifImpl(JNIEnv *env, job
306279extern " C"
307280JNIEXPORT jbyteArray JNICALL
308281Java_com_radzivon_bartoshyk_avif_coder_HeifCoder_encodeHeicImpl (JNIEnv *env, jobject thiz,
309- jobject bitmap, jint quality) {
282+ jobject bitmap, jint quality,
283+ jint dataSpace) {
310284 try {
311- return encodeBitmap (env, thiz, bitmap, heif_compression_HEVC, quality);
285+ return encodeBitmap (env, thiz, bitmap, heif_compression_HEVC, quality, dataSpace );
312286 } catch (std::bad_alloc &err) {
313287 std::string exception = " Not enough memory to encode this image" ;
314288 throwException (env, exception);
0 commit comments