diff --git a/app/build.gradle b/app/build.gradle index 8a43f5d..fd933a6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,6 +34,9 @@ android { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } + debug { + jniDebuggable true + } } // sourceSets { diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt index 301a1cf..d000a60 100644 --- a/app/src/main/cpp/CMakeLists.txt +++ b/app/src/main/cpp/CMakeLists.txt @@ -21,6 +21,9 @@ ENDIF() project("mppreview") +include_directories(D:/Workspace/deps/hdrplus_libs/${ANDROID_ABI}/include) +link_directories(D:/Workspace/deps/hdrplus_libs/${ANDROID_ABI}/lib) + find_package(OpenCV REQUIRED core imgproc highgui photo) # find_package(OpenCV REQUIRED core imgproc) if(OpenCV_FOUND) @@ -84,6 +87,7 @@ target_link_libraries( # Specifies the target library. #ncnn + raw raw_r ${OpenCV_LIBS} ) diff --git a/app/src/main/cpp/MpPreview.cpp b/app/src/main/cpp/MpPreview.cpp index 0bdb516..0b1526e 100644 --- a/app/src/main/cpp/MpPreview.cpp +++ b/app/src/main/cpp/MpPreview.cpp @@ -28,7 +28,6 @@ namespace cv2 { using namespace cv; - Mat linearResponseNew(int channels) { Mat response = Mat(LDR_SIZE, 1, CV_MAKETYPE(CV_32F, channels)); @@ -131,11 +130,12 @@ namespace cv2 Mat weight_sum = Mat::zeros(size, CV_32F); ALOGD("HDR Merge 5"); -// #pragma omp parallel for num_threads(2) + for(size_t i = 0; i < images.size(); i++) { std::vector splitted; split(images[i], splitted); + ALOGD("HDR Merge 5 - 1"); Mat w = Mat::zeros(size, CV_32F); for(int c = 0; c < channels; c++) { LUT(splitted[c], weights, splitted[c]); @@ -143,14 +143,18 @@ namespace cv2 } w /= channels; + ALOGD("HDR Merge 5 - 2"); Mat response_img; LUT(images[i], log_response, response_img); split(response_img, splitted); + +// #pragma omp parallel for num_threads(channels) for(int c = 0; c < channels; c++) { //这里崩溃 result_split[c] += w.mul(splitted[c] - exp_values.at((int)i)); } weight_sum += w; + ALOGD("HDR Merge 5 - 3"); } ALOGD("HDR Merge 6"); @@ -506,7 +510,7 @@ bool makeHdr(std::vector& times, std::vector& paths, cv::Mat // Tonemap using Reinhard's method to obtain 24-bit color image // cout << "Tonemaping using Reinhard's method ... "; cv::Mat ldrReinhard; - cv::Ptr tonemapReinhard = cv2::createTonemapReinhardNew(1.5, 0, 0, 0); + cv::Ptr tonemapReinhard = cv::createTonemapReinhard(1.5, 0, 0, 0); tonemapReinhard->process(hdrDebevec, ldrReinhard); hdrDebevec.release(); @@ -540,7 +544,7 @@ bool makeHdr(std::vector& times, std::vector& images, cv::Mat& r // Merge images into an HDR linear image ALOGI("Merging images into one HDR image ... "); cv::Mat hdrDebevec; - cv::Ptr mergeDebevec = cv2::createMergeDebevecNew(); + cv::Ptr mergeDebevec = cv::createMergeDebevec(); mergeDebevec->process(images, hdrDebevec, times, responseDebevec); // Save HDR image. // imwrite((OUTPUT_DIR "hdrDebevec.hdr"), hdrDebevec); @@ -554,7 +558,7 @@ bool makeHdr(std::vector& times, std::vector& images, cv::Mat& r // Tonemap using Reinhard's method to obtain 24-bit color image ALOGI("Tonemaping using Reinhard's method ... "); cv::Mat ldrReinhard; - cv::Ptr tonemapReinhard = cv2::createTonemapReinhardNew(1.5, 0, 0, 0); + cv::Ptr tonemapReinhard = cv::createTonemapReinhard(1.5, 0, 0, 0); tonemapReinhard->process(hdrDebevec, ldrReinhard); hdrDebevec.release(); @@ -708,16 +712,28 @@ Java_com_xypower_mppreview_Camera2RawFragment_makeHdr3(JNIEnv *env, jclass clazz for (int idx = 0; idx < 2; idx++) { AndroidBitmapInfo bmpInfo = { 0 }; - AHardwareBuffer* hardwareBuffer = NULL; int result = AndroidBitmap_getInfo(env, bitmaps[idx], &bmpInfo); - result = AndroidBitmap_getHardwareBuffer(env, bitmaps[idx], &hardwareBuffer); - void* outVirtualAddress = NULL; - int32_t fence = -1; - result = AHardwareBuffer_lock(hardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, fence, NULL, &outVirtualAddress); - cv::Mat tmp(bmpInfo.height, bmpInfo.width, CV_8UC4, outVirtualAddress); - AHardwareBuffer_unlock(hardwareBuffer, &fence); - tmp.copyTo(images[idx]); + if ((ANDROID_BITMAP_FLAGS_IS_HARDWARE & bmpInfo.flags) == ANDROID_BITMAP_FLAGS_IS_HARDWARE) + { + AHardwareBuffer* hardwareBuffer = NULL; + result = AndroidBitmap_getHardwareBuffer(env, bitmaps[idx], &hardwareBuffer); + + void* outVirtualAddress = NULL; + int32_t fence = -1; + result = AHardwareBuffer_lock(hardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, fence, NULL, &outVirtualAddress); + cv::Mat tmp(bmpInfo.height, bmpInfo.width, CV_8UC4, outVirtualAddress); + AHardwareBuffer_unlock(hardwareBuffer, &fence); + tmp.copyTo(images[idx]); + } + else + { + void* outAddress = NULL; + result = AndroidBitmap_lockPixels(env, bitmaps[idx], &outAddress); + cv::Mat tmp(bmpInfo.height, bmpInfo.width, CV_8UC4, outAddress); + AndroidBitmap_unlockPixels(env, bitmaps[idx]); + tmp.copyTo(images[idx]); + } //convert RGB to BGR cv::cvtColor(images[idx], images[idx], cv::COLOR_RGB2BGR); @@ -746,5 +762,14 @@ Java_com_xypower_mppreview_Camera2RawFragment_makeHdr3(JNIEnv *env, jclass clazz return JNI_TRUE; } + // env->DeleteGlobalRef(img1); + // env->DeleteGlobalRef(img2); + return JNI_FALSE; +} +extern "C" +JNIEXPORT jboolean JNICALL +Java_com_xypower_mppreview_Camera2RawFragment_decodeDng(JNIEnv *env, jclass clazz, + jobject byte_buffer, jstring output_path) { + // TODO: implement decodeDng() } \ No newline at end of file diff --git a/app/src/main/java/com/xypower/mppreview/Camera2RawFragment.java b/app/src/main/java/com/xypower/mppreview/Camera2RawFragment.java index b37e4fa..ba3b2f1 100644 --- a/app/src/main/java/com/xypower/mppreview/Camera2RawFragment.java +++ b/app/src/main/java/com/xypower/mppreview/Camera2RawFragment.java @@ -135,6 +135,8 @@ public class Camera2RawFragment extends Fragment { public static native boolean makeHdr3(long exposureTime1, Bitmap img1, int length1, long exposureTime2, Bitmap img2, int length2, String outputPath); + // public static native boolean decodeDng(ByteBuffer byteBuffer, String outputPath); + private int mExposureComp = MainActivity.ExposureComp; private Long exposetime; @@ -653,9 +655,11 @@ public class Camera2RawFragment extends Fragment { } StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); // For still image captures, we use the largest available size. + Size[] outputSizes = map.getOutputSizes(ImageFormat.YUV_420_888); Size largestJpeg = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)), new CompareSizesByArea()); - Size largestRaw = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.RAW_SENSOR)), new CompareSizesByArea()); + outputSizes = map.getOutputSizes(ImageFormat.RAW_SENSOR); + Size largestRaw = Collections.max(Arrays.asList(outputSizes), new CompareSizesByArea()); // Size largestRaw = Arrays.asList(map.getOutputSizes(ImageFormat.RAW_SENSOR)).get(1); synchronized (mCameraStateLock) { @@ -885,7 +889,7 @@ public class Camera2RawFragment extends Fragment { // parameters.setPreviewFrameRate(10); Range[] fpsRanges = mCharacteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES); - Range fpsRange = new Range<>(5, 30); + Range fpsRange = new Range<>(10, 15); builder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange); // Enable auto-magical 3A run by camera device @@ -1110,15 +1114,19 @@ public class Camera2RawFragment extends Fragment { new Thread(new Runnable() { @Override public void run() { - // makeHdr3() - if (images.size() != 2) { return; } ImageSaver.ImageInfo img1 = images.get(0); ImageSaver.ImageInfo img2 = images.get(1); Log.d("开始Hdr处理", "strat"); - boolean b = makeHdr3(img1.exposureTime, img1.bitmap, img1.length, img2.exposureTime, img2.bitmap, img2.length, outputPath + "HDR_" + generateTimestamp() + ".jpg"); + String hdrOutputPath = outputPath + "HDR_" + generateTimestamp() + ".jpg"; + boolean b = makeHdr3(img1.exposureTime, img1.bitmap, img1.length, img2.exposureTime, img2.bitmap, img2.length, hdrOutputPath); + img1.bitmap.recycle(); + img2.bitmap.recycle(); + img1 = null; + img2 = null; + images.clear(); Log.d("结束Hdr处理", "end"); if (b) { showToast("HDR拍摄成功"); diff --git a/app/src/main/java/com/xypower/mppreview/CameraActivity.java b/app/src/main/java/com/xypower/mppreview/CameraActivity.java index af47cb4..46f2c23 100644 --- a/app/src/main/java/com/xypower/mppreview/CameraActivity.java +++ b/app/src/main/java/com/xypower/mppreview/CameraActivity.java @@ -2,9 +2,12 @@ package com.xypower.mppreview; import androidx.appcompat.app.AppCompatActivity; +import android.content.ComponentCallbacks2; +import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Bundle; +import android.util.Log; import android.view.View; import android.view.Window; import android.view.WindowInsets; @@ -15,6 +18,7 @@ import com.xypower.mppreview.bean.Contants; public class CameraActivity extends AppCompatActivity { + private final static String TAG = "HDR"; public int intExtra; @Override @@ -31,4 +35,19 @@ public class CameraActivity extends AppCompatActivity { getSupportFragmentManager().beginTransaction().setReorderingAllowed(true).replace(R.id.container, Camera2RawFragment.class, bundle).commit(); } } + + @Override + public void onTrimMemory(int level) { + Log.w(TAG, "Event onTrimMemory level=" + level); + try { + System.gc(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + @Override + public void onLowMemory() { + Log.w(TAG, "Event onLowMemory"); + } } \ No newline at end of file diff --git a/app/src/main/java/com/xypower/mppreview/ImageSaver.java b/app/src/main/java/com/xypower/mppreview/ImageSaver.java index 5991c9f..e3e1dba 100644 --- a/app/src/main/java/com/xypower/mppreview/ImageSaver.java +++ b/app/src/main/java/com/xypower/mppreview/ImageSaver.java @@ -150,11 +150,13 @@ public class ImageSaver implements Runnable { ImageDecoder.OnHeaderDecodedListener listener = new ImageDecoder.OnHeaderDecodedListener() { @Override public void onHeaderDecoded(@NonNull ImageDecoder decoder, @NonNull ImageDecoder.ImageInfo info, @NonNull ImageDecoder.Source source) { + // decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); decoder.setAllocator(ImageDecoder.ALLOCATOR_HARDWARE); + // decoder.setTargetSize(4702, 3520); } }; - Log.i("HDR", "Start Hardware Decoding Exp=" + t.toString()); + Log.i(TAG, "Start Hardware Decoding Exp=" + t.toString() + " TID=" + Thread.currentThread().getId()); ImageDecoder imageDecoder = null; Bitmap bmp = null; // ImageDecoder.Source source = ImageDecoder.createSource(mFile); @@ -165,8 +167,9 @@ public class ImageSaver implements Runnable { } catch (Exception ex) { ex.printStackTrace(); } - Log.i("HDR", "End Hardware Decoding Exp=" + t.toString()); + Log.i(TAG, "End Hardware Decoding Exp=" + t.toString()); + byteBuffer.clear(); byteBuffer = null; mImagePair.addImage(bmp, 0, t.longValue()); success = true; diff --git a/app/src/main/res/layout/activity_camera.xml b/app/src/main/res/layout/activity_camera.xml index 4fefecb..4ec324e 100644 --- a/app/src/main/res/layout/activity_camera.xml +++ b/app/src/main/res/layout/activity_camera.xml @@ -4,6 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" + android:keepScreenOn="true" tools:context=".CameraActivity"> diff --git a/app/src/main/res/layout/activity_camera_channel.xml b/app/src/main/res/layout/activity_camera_channel.xml index e900486..01496ca 100644 --- a/app/src/main/res/layout/activity_camera_channel.xml +++ b/app/src/main/res/layout/activity_camera_channel.xml @@ -4,6 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" + android:keepScreenOn="true" tools:context=".CameraChannelActivity">