YUV拍照Hdr
parent
4b9232f549
commit
e5026556f6
@ -0,0 +1,195 @@
|
|||||||
|
package com.xypower.mppreview.utils;
|
||||||
|
|
||||||
|
import static com.xypower.mppreview.utils.HdrUtil.generateTimestamp;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.ImageFormat;
|
||||||
|
import android.media.Image;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.renderscript.Allocation;
|
||||||
|
import android.renderscript.Element;
|
||||||
|
import android.renderscript.RenderScript;
|
||||||
|
import android.renderscript.ScriptIntrinsicYuvToRGB;
|
||||||
|
import android.renderscript.Type;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class ImageConverterUtil {
|
||||||
|
private final String TAG = "ImageConverterUtil";
|
||||||
|
|
||||||
|
public void saveYuvImageFromImageReader(Image image, RenderScript rs, String i) {
|
||||||
|
// Image image = null;
|
||||||
|
try {
|
||||||
|
// // Acquire the latest image from ImageReader
|
||||||
|
// image = imageReader.acquireLatestImage();
|
||||||
|
// if (image == null) {
|
||||||
|
// Log.e(TAG, "No image available");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Convert Image to Bitmap directly using RenderScript
|
||||||
|
Bitmap bitmap = imageYuvToBitmap(image, rs);
|
||||||
|
|
||||||
|
// Save the bitmap to file (PNG format to avoid lossy compression)
|
||||||
|
saveBitmapToFile(bitmap, i);
|
||||||
|
|
||||||
|
Log.d(TAG, "Image saved successfully");
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error saving image: " + e.getMessage());
|
||||||
|
} finally {
|
||||||
|
if (image != null) {
|
||||||
|
image.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bitmap imageYuvToBitmap(Image image, RenderScript rs) {
|
||||||
|
if (image.getFormat() != ImageFormat.YUV_420_888) {
|
||||||
|
throw new IllegalArgumentException("Only YUV_420_888 format is supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
int width = image.getWidth();
|
||||||
|
int height = image.getHeight();
|
||||||
|
|
||||||
|
// Convert YUV to NV21 format
|
||||||
|
byte[] nv21Data = yuv420ToNv21(image);
|
||||||
|
|
||||||
|
// Create output bitmap
|
||||||
|
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||||
|
|
||||||
|
// Use RenderScript for YUV to RGB conversion (more efficient)
|
||||||
|
Allocation inputAllocation = Allocation.createSized(rs, Element.U8(rs), nv21Data.length);
|
||||||
|
inputAllocation.copyFrom(nv21Data);
|
||||||
|
|
||||||
|
Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs))
|
||||||
|
.setX(width)
|
||||||
|
.setY(height)
|
||||||
|
.setYuvFormat(ImageFormat.NV21);
|
||||||
|
Allocation yuvAllocation = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);
|
||||||
|
yuvAllocation.copyFrom(nv21Data);
|
||||||
|
|
||||||
|
Allocation outputAllocation = Allocation.createFromBitmap(rs, bitmap);
|
||||||
|
|
||||||
|
ScriptIntrinsicYuvToRGB yuvToRgbScript = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
|
||||||
|
yuvToRgbScript.setInput(yuvAllocation);
|
||||||
|
yuvToRgbScript.forEach(outputAllocation);
|
||||||
|
|
||||||
|
outputAllocation.copyTo(bitmap);
|
||||||
|
|
||||||
|
// Clean up allocations
|
||||||
|
inputAllocation.destroy();
|
||||||
|
yuvAllocation.destroy();
|
||||||
|
outputAllocation.destroy();
|
||||||
|
yuvToRgbScript.destroy();
|
||||||
|
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] yuv420ToNv21(Image image) {
|
||||||
|
Image.Plane[] planes = image.getPlanes();
|
||||||
|
ByteBuffer yBuffer = planes[0].getBuffer();
|
||||||
|
ByteBuffer uBuffer = planes[1].getBuffer();
|
||||||
|
ByteBuffer vBuffer = planes[2].getBuffer();
|
||||||
|
|
||||||
|
int ySize = yBuffer.remaining();
|
||||||
|
int width = image.getWidth();
|
||||||
|
int height = image.getHeight();
|
||||||
|
int uvSize = width * height / 4; // U and V are quarter size
|
||||||
|
|
||||||
|
byte[] nv21 = new byte[ySize + uvSize * 2];
|
||||||
|
|
||||||
|
// Copy Y plane as-is
|
||||||
|
yBuffer.get(nv21, 0, ySize);
|
||||||
|
|
||||||
|
// Interleave V and U planes into NV21 format (which is really NV12 with U and V swapped)
|
||||||
|
int uvRowStride = planes[1].getRowStride();
|
||||||
|
int uvPixelStride = planes[1].getPixelStride();
|
||||||
|
int pos = ySize;
|
||||||
|
|
||||||
|
for (int row = 0; row < height / 2; row++) {
|
||||||
|
for (int col = 0; col < width / 2; col++) {
|
||||||
|
int vuPos = col * uvPixelStride + row * uvRowStride;
|
||||||
|
nv21[pos++] = vBuffer.get(vuPos);
|
||||||
|
nv21[pos++] = uBuffer.get(vuPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nv21;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alternative method using direct YUV-to-RGB color space conversion
|
||||||
|
private Bitmap yuvImageToBitmapDirect(Image image) {
|
||||||
|
if (image.getFormat() != ImageFormat.YUV_420_888) {
|
||||||
|
throw new IllegalArgumentException("Only YUV_420_888 format is supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
int width = image.getWidth();
|
||||||
|
int height = image.getHeight();
|
||||||
|
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||||
|
|
||||||
|
// Get YUV data
|
||||||
|
Image.Plane[] planes = image.getPlanes();
|
||||||
|
ByteBuffer yBuffer = planes[0].getBuffer();
|
||||||
|
ByteBuffer uBuffer = planes[1].getBuffer();
|
||||||
|
ByteBuffer vBuffer = planes[2].getBuffer();
|
||||||
|
|
||||||
|
int yRowStride = planes[0].getRowStride();
|
||||||
|
int uvRowStride = planes[1].getRowStride();
|
||||||
|
int uvPixelStride = planes[1].getPixelStride();
|
||||||
|
|
||||||
|
// Convert YUV to RGB directly, pixel by pixel
|
||||||
|
int[] rgbData = new int[width * height];
|
||||||
|
|
||||||
|
for (int j = 0; j < height; j++) {
|
||||||
|
for (int i = 0; i < width; i++) {
|
||||||
|
int yIndex = j * yRowStride + i;
|
||||||
|
int uvJ = j / 2;
|
||||||
|
int uvI = i / 2;
|
||||||
|
int uvIndex = uvJ * uvRowStride + uvI * uvPixelStride;
|
||||||
|
|
||||||
|
int y = yBuffer.get(yIndex) & 0xFF;
|
||||||
|
int u = uBuffer.get(uvIndex) & 0xFF;
|
||||||
|
int v = vBuffer.get(uvIndex) & 0xFF;
|
||||||
|
|
||||||
|
// YUV to RGB conversion
|
||||||
|
y = y - 16;
|
||||||
|
u = u - 128;
|
||||||
|
v = v - 128;
|
||||||
|
|
||||||
|
int r = (int) (1.164 * y + 1.596 * v);
|
||||||
|
int g = (int) (1.164 * y - 0.813 * v - 0.391 * u);
|
||||||
|
int b = (int) (1.164 * y + 2.018 * u);
|
||||||
|
|
||||||
|
// Clamp RGB values
|
||||||
|
r = r > 255 ? 255 : (r < 0 ? 0 : r);
|
||||||
|
g = g > 255 ? 255 : (g < 0 ? 0 : g);
|
||||||
|
b = b > 255 ? 255 : (b < 0 ? 0 : b);
|
||||||
|
|
||||||
|
rgbData[j * width + i] = 0xFF000000 | (r << 16) | (g << 8) | b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap.setPixels(rgbData, 0, width, 0, 0, width, height);
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveBitmapToFile(Bitmap bitmap, String fileName) throws IOException {
|
||||||
|
// File picturesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
|
||||||
|
|
||||||
|
File picturesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
|
||||||
|
File outputFile = new File(picturesDir, "YUV_" + generateTimestamp() + "_" + fileName + ".bmp");
|
||||||
|
|
||||||
|
FileOutputStream outputStream = new FileOutputStream(outputFile);
|
||||||
|
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
|
||||||
|
outputStream.flush();
|
||||||
|
outputStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
|||||||
|
package com.xypower.mppreview.utils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class RouteManager {
|
||||||
|
|
||||||
|
// 添加路由
|
||||||
|
public static void addRoute(String network, String interfaceName) {
|
||||||
|
try {
|
||||||
|
// 构建命令
|
||||||
|
String command = "ip route add " + network + " dev " + interfaceName+" proto static scope link table ccmni1";
|
||||||
|
// 执行命令
|
||||||
|
Process process = Runtime.getRuntime().exec(command);
|
||||||
|
// 等待命令执行完成
|
||||||
|
process.waitFor();
|
||||||
|
|
||||||
|
String command2 = "ip route add " + network + " dev " + interfaceName+" proto static scope link table ccmni0";
|
||||||
|
// 执行命令
|
||||||
|
Process process2 = Runtime.getRuntime().exec(command2);
|
||||||
|
// 等待命令执行完成
|
||||||
|
process2.waitFor();
|
||||||
|
// 检查命令是否成功
|
||||||
|
if (process.exitValue() == 0) {
|
||||||
|
System.out.println("Route added successfully: " + command);
|
||||||
|
} else {
|
||||||
|
System.err.println("Failed to add route: " + command);
|
||||||
|
}
|
||||||
|
} catch (IOException | InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static void main(String[] args) {
|
||||||
|
// // 示例:添加 192.168.2.0/24 网段的路由到 eth0 接口
|
||||||
|
// addRoute("192.168.68.0/24", "eth0");
|
||||||
|
// }
|
||||||
|
}
|
Loading…
Reference in New Issue