Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Color space #8

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ android {
dependencies {

implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0'
implementation 'com.google.android.material:material:1.12.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation project(path: ':libraw')
implementation "androidx.core:core-ktx:1.13.0"
implementation "androidx.core:core-ktx:1.13.1"
implementation 'androidx.preference:preference-ktx:1.2.1'
}
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
android:theme="@style/Theme.AndroidLibraw">
<activity
android:name=".MainActivity"
android:colorMode="wideColorGamut"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ class MainFragment : Fragment() {
val autoWhiteBalance = prefs.getBoolean("autoWhiteBalance", context.resources.getBoolean(R.bool.defaultAutoWhiteBalance))
libRaw.setCameraWhiteBalance(true)
libRaw.setAutoWhiteBalance(autoWhiteBalance)
val colorSpace = prefs.getString("colorSpace", context.resources.getString(R.string.defaultColorSpace))
libRaw.setOutputColorSpace(colorSpace!!.toInt())
val colorSpace = SettingsFragment.getColorSpaceId(context)
libRaw.setOutputColorSpace(colorSpace.toInt())
libRaw.use {
orientation = it.orientation
opts.inPreferredConfig = Bitmap.Config.ARGB_8888
Expand All @@ -157,8 +157,8 @@ class MainFragment : Fragment() {
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

//Dont' decode the second one, just get a bitmap
hdrBitmap = it.bitmap16
//Don't decode the second one, just get a bitmap
hdrBitmap = it.getBitmap(Bitmap.Config.RGBA_F16)
} else {
hdrBitmap = null
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,36 @@
package com.homesoft.photo.androidlibraw

import android.content.Context
import android.os.Build
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.ListPreference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager

class SettingsFragment : PreferenceFragmentCompat() {
private lateinit var colorSpacePref : ListPreference

override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences, rootKey)
colorSpacePref = findPreference(PREF_COLOR_SPACE)!!
updateColorSpace(getColorSpaceId(requireContext()))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
colorSpacePref.setOnPreferenceChangeListener {_, newValue ->
if (newValue is String) {
updateColorSpace(newValue)
}
true
}
} else {
colorSpacePref.isEnabled = false
}
}

private fun updateColorSpace(getColorSpaceId : String) {
val index = colorSpacePref.entryValues.indexOf(getColorSpaceId)
colorSpacePref.summary = if (index >= 0) {colorSpacePref.entries[index]} else {null}
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
Expand All @@ -18,4 +40,13 @@ class SettingsFragment : PreferenceFragmentCompat() {
it.title = getString(R.string.settings)
}
}

companion object {
const val PREF_COLOR_SPACE = "colorSpace"
fun getColorSpaceId(context: Context):String {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
val def = context.resources.getString(R.string.defaultColorSpace)
return prefs.getString(PREF_COLOR_SPACE, def) as String
}
}
}
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/baseline_settings_24.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="?attr/colorControlNormal" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">

<path android:fillColor="@android:color/white" android:pathData="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.8,11.69 4.8,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z"/>

</vector>
2 changes: 1 addition & 1 deletion app/src/main/res/menu/main_menu.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/open" android:title="@string/open" app:showAsAction="ifRoom" android:icon="@drawable/ic_baseline_folder_open_24"/>
<item android:id="@+id/settings" android:title="@string/settings" app:showAsAction="never"/>
<item android:id="@+id/settings" android:title="@string/settings" app:showAsAction="ifRoom" android:icon="@drawable/baseline_settings_24"/>
</menu>
19 changes: 18 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,26 @@
<string-array name="colorSpaceValues">
<item>0</item>
<item>1</item>
<item>2</item>
<!--item>3</item-->
<item>4</item>
<!--item>5</item-->
<!--item>6</item-->
<item>7</item>
<item>8</item>
</string-array>
<string-array name="colorSpaceNames">
<item>RAW</item>
<item>Disabled</item>
<item>sRGB</item>
<item>Adobe</item>
<!-- Not sure how to convert this as the data range is not [0-1]-->
<!--item>Wide RGB D65</item-->
<item>ProPhoto</item>
<!-- Not sure how to convert this as the data range is not [0-1]-->
<!--item>XYZ</item-->
<!-- Not sure how to convert this as the data range is not [0-1]-->
<!--item>ACES</item-->
<item>DCI-P3 D65</item>
<item>Rec. 2020</item>
</string-array>
</resources>
1 change: 1 addition & 0 deletions libraw/consumer-rules.pro
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
-keep class com.homesoft.photo.libraw.LibRaw {
long mNativeContext;
android.graphics.ColorSpace getColorSpace(int);
}
98 changes: 66 additions & 32 deletions libraw/src/main/cpp/AndroidLibRaw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,33 @@
#define O imgdata.params
#define C imgdata.color
#define IO libraw_internal_data.internal_output_params
#define SHORT2FLOAT 65535.0f;

#define SHORT2FLOAT 65535.0f
#define COLORS 3
#define PIXEL8_LOOP \
#define CURVE_SIZE 0x10000
#define CURVE8 \
unsigned char curve[CURVE_SIZE]; \
for (int i=0;i<CURVE_SIZE;i++) { \
curve[i] = imgdata.color.curve[i] >> 8; \
} \

#define CURVE16 \
__fp16 curve[CURVE_SIZE]; \
for (int i=0;i<CURVE_SIZE;i++) { \
curve[i] = imgdata.color.curve[i] / SHORT2FLOAT; \
} \

#define PIXEL_LOOP \
for (int c=0;c<COLORS;c++) { \
*ptr = imgdata.color.curve[imgdata.image[pixel][c]] >> 8; \
*ptr = curve[imgdata.image[pixel][c]]; \
ptr++; \
} \

#define PIXEL8A_LOOP PIXEL8_LOOP \
#define PIXEL8A_LOOP PIXEL_LOOP \
*ptr = 0xff; \
ptr++; \

#define PIXEL16_LOOP \
for (int c = 0; c < COLORS; c++) { \
*ptr = imgdata.color.curve[imgdata.image[pixel][c]] / SHORT2FLOAT; \
ptr++; \
} \
#define PIXEL16A_LOOP PIXEL_LOOP \
*ptr = 1.0; \
ptr++; \

Expand All @@ -43,7 +53,7 @@ AndroidLibRaw* getLibRaw(JNIEnv* env, jobject jLibRaw) {
AndroidLibRaw::AndroidLibRaw(unsigned int flags):LibRaw(flags) {
}

jobject AndroidLibRaw::doGetBitmap(JNIEnv* env, const char* configName, int32_t configType, const std::function<void (void*, int const)>& _copy) {
jobject AndroidLibRaw::doGetBitmap(JNIEnv* env, jobject bitmapConfig, const std::function<void (void*, int const)>& _copy) {
if (imgdata.idata.colors != COLORS) {
__android_log_print(ANDROID_LOG_ERROR,"libraw","expected 3 colors, got %i", P1.colors);
return nullptr;
Expand All @@ -55,7 +65,6 @@ jobject AndroidLibRaw::doGetBitmap(JNIEnv* env, const char* configName, int32_t
int width = imgdata.sizes.iwidth;
int height = imgdata.sizes.iheight;

jobject bitmapConfig = getConfigByName(env, configName);
jobject bitmap = createBitmap(env, bitmapConfig, width, height);
void* addrPtr;
AndroidBitmap_lockPixels(env,bitmap, &addrPtr);
Expand All @@ -64,22 +73,35 @@ jobject AndroidLibRaw::doGetBitmap(JNIEnv* env, const char* configName, int32_t
return bitmap;
}

jobject AndroidLibRaw::getBitmap(JNIEnv* env) {
return doGetBitmap(env, "ARGB_8888", ANDROID_BITMAP_FORMAT_RGBA_8888, [this](void* bitmapPtr, int const pixels) {
auto ptr = (unsigned char*)bitmapPtr;
for(int pixel=0; pixel < pixels;pixel++) {
PIXEL8A_LOOP
}
});
}

jobject AndroidLibRaw::getBitmap16(JNIEnv *env) {
return doGetBitmap(env, "RGBA_F16", ANDROID_BITMAP_FORMAT_RGBA_F16, [this](void* bitmapPtr, int const pixels) {
auto ptr = (__fp16 *) bitmapPtr;
for (int pixel = 0; pixel < pixels; pixel++) {
PIXEL16_LOOP
}
});
jobject AndroidLibRaw::getBitmap(JNIEnv* env, jobject bitmapConfig) {
auto bitmapConfigClass = env->GetObjectClass(bitmapConfig);
auto nameId = env->GetMethodID(bitmapConfigClass, "name", "()Ljava/lang/String;");
jstring jName = static_cast<jstring>(env->CallObjectMethod(bitmapConfig, nameId));
auto cName = env->GetStringUTFChars(jName, JNI_FALSE);
jobject bitmap;
if (strcmp("ARGB_8888", cName) == 0) {
bitmap = doGetBitmap(env, bitmapConfig, [this](void* bitmapPtr, int const pixels) {
auto ptr = (unsigned char*)bitmapPtr;
CURVE8
for(int pixel=0; pixel < pixels;pixel++) {
PIXEL8A_LOOP
}
});
} else if (strcmp("RGBA_F16", cName) == 0) {
bitmap = doGetBitmap(env, bitmapConfig, [this](void* bitmapPtr, int const pixels) {
auto ptr = (__fp16 *) bitmapPtr;
CURVE16
for (int pixel = 0; pixel < pixels; pixel++) {
PIXEL16A_LOOP
}
});
} else {
auto exceptionClass = env->FindClass("java/lang/IllegalArgumentException");
env->ThrowNew(exceptionClass, cName);
bitmap = nullptr;
}
env->ReleaseStringUTFChars(jName, cName);
return bitmap;
}

void AndroidLibRaw::buildColorCurve() {
Expand Down Expand Up @@ -125,9 +147,19 @@ jobject AndroidLibRaw::getConfigByName(JNIEnv* env, const char* name) {

jobject AndroidLibRaw::createBitmap(JNIEnv* env, jobject config, jint width, jint height) {
jclass clBitmap = env->FindClass("android/graphics/Bitmap");
jmethodID midCreateBitmap = env->GetStaticMethodID(clBitmap, "createBitmap",
"(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
return env->CallStaticObjectMethod(clBitmap, midCreateBitmap, width, height, config);
if (android_get_device_api_level() >= 26 && imgdata.params.output_color != 1) {
auto midCreateBitmap = env->GetStaticMethodID(clBitmap, "createBitmap",
"(IILandroid/graphics/Bitmap$Config;ZLandroid/graphics/ColorSpace;)Landroid/graphics/Bitmap;");
auto classLibRaw = env->FindClass("com/homesoft/photo/libraw/LibRaw");
auto midGetColorSpace = env->GetStaticMethodID(classLibRaw, "getColorSpace",
"(I)Landroid/graphics/ColorSpace;");
auto colorSpace = env->CallStaticObjectMethod(classLibRaw, midGetColorSpace, imgdata.params.output_color);
return env->CallStaticObjectMethod(clBitmap, midCreateBitmap, width, height, config, false, colorSpace);
} else {
jmethodID midCreateBitmap = env->GetStaticMethodID(clBitmap, "createBitmap",
"(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
return env->CallStaticObjectMethod(clBitmap, midCreateBitmap, width, height, config);
}
}

void AndroidLibRaw::setCaptureScaleMul(bool capture) {
Expand Down Expand Up @@ -182,11 +214,12 @@ int AndroidLibRaw::copyImage(uint32_t width, uint32_t height, uint32_t stride, u
if (format == AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM) {
auto skip = (stride - width) * 3;
auto ptr = static_cast<unsigned char *>(bufferPtr);
CURVE8
uint32_t pixel = 0;
while (pixel < pixels) {
auto rowEnd = pixel + width;
while (pixel < rowEnd) {
PIXEL8_LOOP
PIXEL_LOOP
pixel++;
}
ptr += skip;
Expand All @@ -195,11 +228,12 @@ int AndroidLibRaw::copyImage(uint32_t width, uint32_t height, uint32_t stride, u
} else if (format == AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT) {
auto skip = (stride - width) * 4;
auto ptr = static_cast<__fp16 *>(bufferPtr);
CURVE16
uint32_t pixel = 0;
while (pixel < pixels) {
auto rowEnd = pixel + width;
while (pixel < rowEnd) {
PIXEL16_LOOP
PIXEL16A_LOOP
pixel++;
}
ptr += skip;
Expand Down
7 changes: 3 additions & 4 deletions libraw/src/main/cpp/AndroidLibRaw.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,23 @@
class AndroidLibRaw: public LibRaw {
public:
AndroidLibRaw(unsigned int flags = LIBRAW_OPTIONS_NONE);
jobject getBitmap(JNIEnv* env);
jobject getBitmap16(JNIEnv* env);
jobject getBitmap(JNIEnv* env, jobject bitmapConfig);
jboolean drawSurface(JNIEnv* env, jobject surface);
int copyImage(uint32_t width, uint32_t height, uint32_t stride, uint32_t format, void *bufferPtr);
jobject getColorCurve(JNIEnv* env);
void setColorCurve(JNIEnv* env, jobject byteBuffer);
void setCaptureScaleMul(bool capture);
void buildColorCurve();
int dcrawProcessForced(JNIEnv* env, jobject colorCurve);
jobject createBitmap(JNIEnv *env, jobject config, jint width, jint height);
static jobject getConfigByName(JNIEnv* env, const char* name);
static jobject createBitmap(JNIEnv *env, jobject config, jint width, jint height);

protected:
void scale_colors_loop(float scale_mul[4]) override;

private:
float* mScaleMul = nullptr;
jobject doGetBitmap(JNIEnv* env, const char* configName, int32_t configType, const std::function<void (void* bitmapPtr, int const pixels)>& _copy);
jobject doGetBitmap(JNIEnv* env, jobject bitmapConfig, const std::function<void (void* bitmapPtr, int const pixels)>& _copy);

static void preScaleCallback(void *libRaw);
};
Expand Down
12 changes: 5 additions & 7 deletions libraw/src/main/cpp/anrdroidraw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ extern "C" JNIEXPORT void JNICALL Java_com_homesoft_photo_libraw_LibRaw_setCamer
extern "C" JNIEXPORT void JNICALL Java_com_homesoft_photo_libraw_LibRaw_setCancelFlag(JNIEnv* env, jobject jLibRaw){
getLibRaw(env, jLibRaw)->setCancelFlag();
}
extern "C" JNIEXPORT jint JNICALL Java_com_homesoft_photo_libraw_LibRaw_getOutputColorSpace(JNIEnv* env, jobject jLibRaw) {
return getLibRaw(env, jLibRaw)->imgdata.params.output_color;
}
extern "C" JNIEXPORT void JNICALL Java_com_homesoft_photo_libraw_LibRaw_setOutputColorSpace(JNIEnv* env, jobject jLibRaw,jint space){
getLibRaw(env, jLibRaw)->imgdata.params.output_color=space;
}
Expand Down Expand Up @@ -243,15 +246,10 @@ extern "C" JNIEXPORT jstring JNICALL Java_com_homesoft_photo_libraw_LibRaw_getCa
return result;
}

extern "C" JNIEXPORT jobject JNICALL Java_com_homesoft_photo_libraw_LibRaw_getBitmap(JNIEnv* env, jobject jLibRaw) {
auto libRaw = getLibRaw(env, jLibRaw);
return libRaw->getBitmap(env);
}
extern "C" JNIEXPORT jobject JNICALL Java_com_homesoft_photo_libraw_LibRaw_getBitmap16(JNIEnv* env, jobject jLibRaw) {
extern "C" JNIEXPORT jobject JNICALL Java_com_homesoft_photo_libraw_LibRaw_getMutableBitmap(JNIEnv* env, jobject jLibRaw, jobject bitmapConfig) {
auto libRaw = getLibRaw(env, jLibRaw);
return libRaw->getBitmap16(env);
return libRaw->getBitmap(env, bitmapConfig);
}

extern "C" JNIEXPORT jint JNICALL Java_com_homesoft_photo_libraw_LibRaw_drawSurface(JNIEnv* env, jobject jLibRaw, jobject surface) {
auto libRaw = getLibRaw(env, jLibRaw);
return libRaw->drawSurface(env, surface);
Expand Down
Loading