Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ build
.idea
/app/release/output-metadata.json
libsparkyuv.a
jxlcoder/src/main/cpp/sparkyuv
jxlcoder/src/main/cpp/sparkyuv
third_party
/app/src/main/assets/
/app/release
.kotlin/
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("com.google.devtools.ksp")
id("org.jetbrains.kotlin.plugin.compose") version "2.2.0"
id("org.jetbrains.kotlin.plugin.compose") version "2.2.10"
}

android {
Expand Down
5 changes: 3 additions & 2 deletions app/src/main/java/com/awxkee/jxlcoder/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package com.awxkee.jxlcoder

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.ColorSpace
import android.graphics.Matrix
import android.graphics.drawable.Drawable
import android.hardware.DataSpace
import android.os.Build
import android.os.Bundle
import android.util.Log
Expand Down Expand Up @@ -127,9 +129,8 @@ class MainActivity : ComponentActivity() {
buffer4,
width = largeImageSize.width / 3,
height = largeImageSize.height / 3,
preferredColorConfig = PreferredColorConfig.RGBA_8888,
preferredColorConfig = PreferredColorConfig.RGBA_1010102,
com.awxkee.jxlcoder.ScaleMode.FIT,
toneMapper = JxlToneMapper.REC2408,
jxlResizeFilter = JxlResizeFilter.LANCZOS
)
lifecycleScope.launch {
Expand Down
8 changes: 4 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id("com.android.application") version "8.13.0" apply false
id("org.jetbrains.kotlin.android") version "2.2.0" apply false
id("com.android.library") version "8.13.0" apply false
id("com.google.devtools.ksp") version "2.2.0-2.0.2" apply false
id("com.android.application") version "9.0.0" apply false
id("org.jetbrains.kotlin.android") version "2.2.10" apply false
id("com.android.library") version "9.0.0" apply false
id("com.google.devtools.ksp") version "2.3.2" apply false
}
10 changes: 10 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,13 @@ android.nonTransitiveRClass=true

SONATYPE_HOST=CENTRAL_PORTAL
SONATYPE_AUTOMATIC_RELEASE=true
android.defaults.buildfeatures.resvalues=true
android.sdk.defaultTargetSdkToCompileSdkIfUnset=false
android.enableAppCompileTimeRClass=false
android.usesSdkInManifest.disallowed=false
android.uniquePackageNames=false
android.dependency.useConstraints=true
android.r8.strictFullModeForKeepRules=false
android.r8.optimizedResourceShrinking=false
android.builtInKotlin=false
android.newDsl=false
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Sun Aug 20 15:15:13 GET 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
6 changes: 3 additions & 3 deletions jxlcoder/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
JxlAnimatedDecoderCoordinator.cpp JxlAnimatedEncoderCoordinator.cpp
hwy/aligned_allocator.cc hwy/nanobenchmark.cc hwy/per_target.cc hwy/print.cc hwy/targets.cc
hwy/timer.cc JXLJpegInterop.cpp EasyGifReader.cpp JXLConventions.cpp
conversion/RgbChannels.cpp colorspaces/ColorMatrix.cpp colorspaces/LogarithmicToneMapper.cpp
conversion/RgbChannels.cpp colorspaces/ColorMatrix.cpp
colorspaces/Rec2408ToneMapper.cpp colorspaces/Trc.cpp
imagebit/CopyUnalignedRGBA.cpp imagebit/half.cpp imagebit/Rgb565.cpp imagebit/Rgb1010102.cpp
imagebit/Rgba8ToF16.cpp imagebit/Rgba16.cpp imagebit/RgbaF16bitNBitU8.cpp imagebit/RgbaF16bitToNBitU16.cpp
imagebit/RGBAlpha.cpp imagebit/RgbaU16toHF.cpp imagebit/ScanAlpha.cpp colorspaces/FilmicToneMapper.cpp
imagebit/RgbaToRgb.cpp colorspaces/AcesToneMapper.cpp
imagebit/RGBAlpha.cpp imagebit/RgbaU16toHF.cpp imagebit/ScanAlpha.cpp
imagebit/RgbaToRgb.cpp NativeColorSpace.cpp
)

set_target_properties(jxlcoder libweaver PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/${ANDROID_ABI}/libweaver.a)
Expand Down
80 changes: 54 additions & 26 deletions jxlcoder/src/main/cpp/JniDecoding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,17 @@
#include "colorspaces/ColorSpaceProfile.h"
#include "hwy/highway.h"
#include "imagebit/CopyUnalignedRGBA.h"
#include "NativeColorSpace.h"

jobject decodeSampledImageImpl(JNIEnv *env, std::vector<uint8_t> &imageData, jint scaledWidth,
jint scaledHeight,
jint javaPreferredColorConfig,
jint javaScaleMode, jint javaResizeFilter, jint javaToneMapper) {
jint javaScaleMode, jint javaResizeFilter) {
ScaleMode scaleMode;
PreferredColorConfig preferredColorConfig;
XSampler sampler;
CurveToneMapper toneMapper;
if (!checkDecodePreconditions(env, javaPreferredColorConfig, &preferredColorConfig,
javaScaleMode, &scaleMode, javaResizeFilter, &sampler,
javaToneMapper, &toneMapper)) {
javaScaleMode, &scaleMode, javaResizeFilter, &sampler)) {
return nullptr;
}

Expand Down Expand Up @@ -136,31 +135,33 @@ jobject decodeSampledImageImpl(JNIEnv *env, std::vector<uint8_t> &imageData, jin
}
}

bool toneMap = true;

if (preferEncoding && (colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_PQ ||
colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_HLG ||
colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_DCI ||
colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_709 ||
colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_GAMMA ||
colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_SRGB)
&& colorEncoding.color_space == JXL_COLOR_SPACE_RGB) {
&& colorEncoding.color_space == JXL_COLOR_SPACE_RGB && osVersion < 34) {
Eigen::Matrix3f sourceProfile;
TransferFunction transferFunction = TransferFunction::Srgb;
if (colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_HLG) {
transferFunction = TransferFunction::Hlg;
} else if (colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_DCI) {
toneMapper = TONE_SKIP;
toneMap = false;
transferFunction = TransferFunction::Smpte428;
} else if (colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_PQ) {
transferFunction = TransferFunction::Pq;
} else if (colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_GAMMA) {
toneMapper = TONE_SKIP;
toneMap = false;
// Make real gamma
transferFunction = TransferFunction::Gamma2p2;
} else if (colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_709) {
toneMapper = TONE_SKIP;
toneMap = false;
transferFunction = TransferFunction::Itur709;
} else if (colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_SRGB) {
toneMapper = TONE_SKIP;
toneMap = false;
transferFunction = TransferFunction::Srgb;
}

Expand Down Expand Up @@ -210,7 +211,7 @@ jobject decodeSampledImageImpl(JNIEnv *env, std::vector<uint8_t> &imageData, jin
matrix,
transferFunction,
TransferFunction::Srgb,
toneMapper,
toneMap,
coeffs,
intensityTarget);
} else {
Expand All @@ -221,7 +222,7 @@ jobject decodeSampledImageImpl(JNIEnv *env, std::vector<uint8_t> &imageData, jin
matrix,
transferFunction,
TransferFunction::Srgb,
toneMapper,
toneMap,
coeffs, intensityTarget);
}
}
Expand All @@ -232,15 +233,33 @@ jobject decodeSampledImageImpl(JNIEnv *env, std::vector<uint8_t> &imageData, jin
finalWidth, finalHeight, &stride, &useBitmapFloats,
&hwBuffer, alphaPremultiplied, hasAlphaInOrigin);

jobject colorSpace = nullptr;
if (androidOSVersion() >= 34) {
if (colorEncoding.primaries == JXL_PRIMARIES_2100 && colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_PQ) {
colorSpace = colorspace::getJNIColorSpace(env, NativeColorSpace::Pq2100);
} else if (colorEncoding.primaries == JXL_PRIMARIES_2100 && colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_HLG) {
colorSpace = colorspace::getJNIColorSpace(env, NativeColorSpace::Hlg2100);
} else if (colorEncoding.primaries == JXL_PRIMARIES_P3 && colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_SRGB) {
colorSpace = colorspace::getJNIColorSpace(env, NativeColorSpace::DisplayP3);
} else if (colorEncoding.primaries == JXL_PRIMARIES_SRGB && colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_LINEAR) {
colorSpace = colorspace::getJNIColorSpace(env, NativeColorSpace::LinearSrgb);
} else if (colorEncoding.primaries == JXL_PRIMARIES_P3 && colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_DCI) {
colorSpace = colorspace::getJNIColorSpace(env, NativeColorSpace::DciP3);
} else if (colorEncoding.primaries == JXL_PRIMARIES_SRGB && colorEncoding.transfer_function == JXL_TRANSFER_FUNCTION_709) {
colorSpace = colorspace::getJNIColorSpace(env, NativeColorSpace::Hlg2100);
} else {
colorSpace = colorspace::getJNIColorSpace(env, NativeColorSpace::DefaultSrgb);
}
}

if (bitmapPixelConfig == "HARDWARE") {
jclass bitmapClass = env->FindClass("android/graphics/Bitmap");
jmethodID createBitmapMethodID = env->GetStaticMethodID(bitmapClass,
"wrapHardwareBuffer",
"(Landroid/hardware/HardwareBuffer;Landroid/graphics/ColorSpace;)Landroid/graphics/Bitmap;");
jobject emptyObject = nullptr;
jobject bitmapObj = env->CallStaticObjectMethod(bitmapClass,
createBitmapMethodID,
hwBuffer, emptyObject);
hwBuffer, colorSpace);
return bitmapObj;
}

Expand All @@ -251,13 +270,24 @@ jobject decodeSampledImageImpl(JNIEnv *env, std::vector<uint8_t> &imageData, jin
jobject rgba8888Obj = env->GetStaticObjectField(bitmapConfig, rgba8888FieldID);

jclass bitmapClass = env->FindClass("android/graphics/Bitmap");
jmethodID createBitmapMethodID = env->GetStaticMethodID(bitmapClass,
"createBitmap",
"(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
jobject bitmapObj = env->CallStaticObjectMethod(bitmapClass, createBitmapMethodID,
static_cast<jint>(finalWidth),
static_cast<jint>(finalHeight),
rgba8888Obj);
jobject bitmapObj;
if (androidOSVersion() >= 34 && colorSpace) {
jmethodID createBitmapMethodID = env->GetStaticMethodID(bitmapClass,
"createBitmap",
"(IILandroid/graphics/Bitmap$Config;ZLandroid/graphics/ColorSpace;)Landroid/graphics/Bitmap;");
bitmapObj = env->CallStaticObjectMethod(bitmapClass, createBitmapMethodID,
static_cast<jint>(finalWidth),
static_cast<jint>(finalHeight),
rgba8888Obj, true, colorSpace);
} else {
jmethodID createBitmapMethodID = env->GetStaticMethodID(bitmapClass,
"createBitmap",
"(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
bitmapObj = env->CallStaticObjectMethod(bitmapClass, createBitmapMethodID,
static_cast<jint>(finalWidth),
static_cast<jint>(finalHeight),
rgba8888Obj);
}

AndroidBitmapInfo info;
if (AndroidBitmap_getInfo(env, bitmapObj, &info) < 0) {
Expand Down Expand Up @@ -307,16 +337,15 @@ Java_com_awxkee_jxlcoder_JxlCoder_decodeSampledImpl(JNIEnv *env, jobject thiz,
jint scaledHeight,
jint javaPreferredColorConfig,
jint javaScaleMode,
jint resizeSampler,
jint javaToneMapper) {
jint resizeSampler) {
try {
auto totalLength = env->GetArrayLength(byte_array);
std::vector<uint8_t> srcBuffer(totalLength);
env->GetByteArrayRegion(byte_array, 0, totalLength,
reinterpret_cast<jbyte *>(srcBuffer.data()));
return decodeSampledImageImpl(env, srcBuffer, scaledWidth, scaledHeight,
javaPreferredColorConfig, javaScaleMode,
resizeSampler, javaToneMapper);
resizeSampler);
} catch (std::bad_alloc &err) {
std::string errorString = "Not enough memory to decode this image";
throwException(env, errorString);
Expand All @@ -336,8 +365,7 @@ Java_com_awxkee_jxlcoder_JxlCoder_decodeByteBufferSampledImpl(JNIEnv *env, jobje
jint scaledHeight,
jint preferredColorConfig,
jint scaleMode,
jint resizeSampler,
jint javaToneMapper) {
jint resizeSampler) {
try {
auto bufferAddress = reinterpret_cast<uint8_t *>(env->GetDirectBufferAddress(byteBuffer));
int length = (int) env->GetDirectBufferCapacity(byteBuffer);
Expand All @@ -350,7 +378,7 @@ Java_com_awxkee_jxlcoder_JxlCoder_decodeByteBufferSampledImpl(JNIEnv *env, jobje
std::copy(bufferAddress, bufferAddress + length, srcBuffer.begin());
return decodeSampledImageImpl(env, srcBuffer, scaledWidth, scaledHeight,
preferredColorConfig, scaleMode,
resizeSampler, javaToneMapper);
resizeSampler);
} catch (std::bad_alloc &err) {
std::string errorString = "Not enough memory to decode this image";
throwException(env, errorString);
Expand Down
Loading