mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-03-28 18:01:35 +01:00
Load image file as pixel by Android uri
This commit is contained in:
parent
f903fd8e6f
commit
8af5b648b5
7 changed files with 179 additions and 0 deletions
|
@ -0,0 +1,65 @@
|
|||
package com.nkming.nc_photos.plugin
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.nkming.nc_photos.plugin.image_processor.Rgba8Image
|
||||
import com.nkming.nc_photos.plugin.image_processor.TfLiteHelper
|
||||
import io.flutter.plugin.common.MethodCall
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
|
||||
class ImageLoaderChannelHandler(context: Context) :
|
||||
MethodChannel.MethodCallHandler {
|
||||
companion object {
|
||||
const val METHOD_CHANNEL = "${K.LIB_ID}/image_loader_method"
|
||||
}
|
||||
|
||||
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
|
||||
when (call.method) {
|
||||
"loadUri" -> {
|
||||
try {
|
||||
loadUri(
|
||||
call.argument("fileUri")!!,
|
||||
call.argument("maxWidth")!!,
|
||||
call.argument("maxHeight")!!,
|
||||
call.argument("resizeMethod")!!,
|
||||
call.argument("isAllowSwapSide")!!,
|
||||
call.argument("shouldUpscale")!!,
|
||||
result
|
||||
)
|
||||
} catch (e: Throwable) {
|
||||
result.error("systemException", e.toString(), null)
|
||||
}
|
||||
}
|
||||
|
||||
else -> result.notImplemented()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and resize an image pointed by a uri
|
||||
*
|
||||
* @param fileUri
|
||||
* @param maxWidth
|
||||
* @param maxHeight
|
||||
* @param resizeMethod
|
||||
* @param isAllowSwapSide
|
||||
* @param shouldUpscale
|
||||
* @param result
|
||||
*/
|
||||
private fun loadUri(
|
||||
fileUri: String, maxWidth: Int, maxHeight: Int, resizeMethod: Int,
|
||||
isAllowSwapSide: Boolean, shouldUpscale: Boolean,
|
||||
result: MethodChannel.Result
|
||||
) {
|
||||
val image = BitmapUtil.loadImage(
|
||||
context, Uri.parse(fileUri), maxWidth, maxHeight,
|
||||
BitmapResizeMethod.values()[resizeMethod], isAllowSwapSide,
|
||||
shouldUpscale
|
||||
).use {
|
||||
Rgba8Image(TfLiteHelper.bitmapToRgba8Array(it), it.width, it.height)
|
||||
}
|
||||
result.success(image.toJson())
|
||||
}
|
||||
|
||||
private val context = context
|
||||
}
|
|
@ -113,6 +113,14 @@ class NcPhotosPlugin : FlutterPlugin, ActivityAware,
|
|||
PreferenceChannelHandler.METHOD_CHANNEL
|
||||
)
|
||||
preferenceMethodChannel.setMethodCallHandler(preferenceChannelHandler)
|
||||
|
||||
val imageLoaderChannelHandler =
|
||||
ImageLoaderChannelHandler(flutterPluginBinding.applicationContext)
|
||||
imageLoaderMethodChannel = MethodChannel(
|
||||
flutterPluginBinding.binaryMessenger,
|
||||
ImageLoaderChannelHandler.METHOD_CHANNEL
|
||||
)
|
||||
imageLoaderMethodChannel.setMethodCallHandler(imageLoaderChannelHandler)
|
||||
}
|
||||
|
||||
override fun onDetachedFromEngine(
|
||||
|
@ -131,6 +139,7 @@ class NcPhotosPlugin : FlutterPlugin, ActivityAware,
|
|||
permissionMethodChannel.setMethodCallHandler(null)
|
||||
logcatMethodChannel.setMethodCallHandler(null)
|
||||
preferenceMethodChannel.setMethodCallHandler(null)
|
||||
imageLoaderMethodChannel.setMethodCallHandler(null)
|
||||
}
|
||||
|
||||
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
|
||||
|
@ -219,6 +228,7 @@ class NcPhotosPlugin : FlutterPlugin, ActivityAware,
|
|||
private lateinit var permissionMethodChannel: MethodChannel
|
||||
private lateinit var logcatMethodChannel: MethodChannel
|
||||
private lateinit var preferenceMethodChannel: MethodChannel
|
||||
private lateinit var imageLoaderMethodChannel: MethodChannel
|
||||
|
||||
private lateinit var lockChannelHandler: LockChannelHandler
|
||||
private lateinit var mediaStoreChannelHandler: MediaStoreChannelHandler
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package com.nkming.nc_photos.plugin.image_processor
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
/**
|
||||
* Container of pixel data stored in RGBA format
|
||||
*/
|
||||
class Rgba8Image(val pixel: ByteArray, val width: Int, val height: Int) {
|
||||
companion object {
|
||||
fun fromJson(json: Map<String, Any>) = Rgba8Image(
|
||||
json["pixel"] as ByteArray, json["width"] as Int,
|
||||
json["height"] as Int
|
||||
)
|
||||
}
|
||||
|
||||
fun toJson() = mapOf<String, Any>(
|
||||
"pixel" to pixel,
|
||||
"width" to width,
|
||||
"height" to height,
|
||||
)
|
||||
|
||||
fun toBitmap(): Bitmap {
|
||||
return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||||
.apply {
|
||||
copyPixelsFromBuffer(ByteBuffer.wrap(pixel))
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
assert(pixel.size == width * height * 4)
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package com.nkming.nc_photos.plugin.image_processor
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.IntBuffer
|
||||
|
||||
interface TfLiteHelper {
|
||||
|
@ -25,6 +26,18 @@ interface TfLiteHelper {
|
|||
return rgb8
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an ARGB_8888 Android bitmap to a RGBA byte array
|
||||
*
|
||||
* @param bitmap
|
||||
* @return
|
||||
*/
|
||||
fun bitmapToRgba8Array(bitmap: Bitmap): ByteArray {
|
||||
val buffer = ByteBuffer.allocate(bitmap.width * bitmap.height * 4)
|
||||
bitmap.copyPixelsToBuffer(buffer)
|
||||
return buffer.array()
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a RGB8 byte array to an ARGB_8888 Android bitmap
|
||||
*
|
||||
|
|
|
@ -2,6 +2,8 @@ library nc_photos_plugin;
|
|||
|
||||
export 'src/content_uri.dart';
|
||||
export 'src/exception.dart';
|
||||
export 'src/image.dart';
|
||||
export 'src/image_loader.dart';
|
||||
export 'src/image_processor.dart';
|
||||
export 'src/lock.dart';
|
||||
export 'src/logcat.dart';
|
||||
|
|
22
plugin/lib/src/image.dart
Normal file
22
plugin/lib/src/image.dart
Normal file
|
@ -0,0 +1,22 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
/// Container of pixel data stored in RGBA format
|
||||
class Rgba8Image {
|
||||
const Rgba8Image(this.pixel, this.width, this.height);
|
||||
|
||||
factory Rgba8Image.fromJson(Map<String, dynamic> json) => Rgba8Image(
|
||||
json["pixel"],
|
||||
json["width"],
|
||||
json["height"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"pixel": pixel,
|
||||
"width": width,
|
||||
"height": height,
|
||||
};
|
||||
|
||||
final Uint8List pixel;
|
||||
final int width;
|
||||
final int height;
|
||||
}
|
34
plugin/lib/src/image_loader.dart
Normal file
34
plugin/lib/src/image_loader.dart
Normal file
|
@ -0,0 +1,34 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:nc_photos_plugin/src/image.dart';
|
||||
import 'package:nc_photos_plugin/src/k.dart' as k;
|
||||
|
||||
enum ImageLoaderResizeMethod {
|
||||
fit,
|
||||
fill,
|
||||
}
|
||||
|
||||
class ImageLoader {
|
||||
static Future<Rgba8Image> loadUri(
|
||||
String fileUri,
|
||||
int maxWidth,
|
||||
int maxHeight,
|
||||
ImageLoaderResizeMethod resizeMethod, {
|
||||
bool isAllowSwapSide = false,
|
||||
bool shouldUpscale = false,
|
||||
}) async {
|
||||
final result =
|
||||
await _methodChannel.invokeMethod<Map>("loadUri", <String, dynamic>{
|
||||
"fileUri": fileUri,
|
||||
"maxWidth": maxWidth,
|
||||
"maxHeight": maxHeight,
|
||||
"resizeMethod": resizeMethod.index,
|
||||
"isAllowSwapSide": isAllowSwapSide,
|
||||
"shouldUpscale": shouldUpscale,
|
||||
});
|
||||
return Rgba8Image.fromJson(result!.cast<String, dynamic>());
|
||||
}
|
||||
|
||||
static const _methodChannel = MethodChannel("${k.libId}/image_loader_method");
|
||||
}
|
Loading…
Add table
Reference in a new issue