Skip to content

Commit

Permalink
chore: release 2.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
rodgomesc committed Mar 11, 2024
1 parent ab460af commit 3ed2cf6
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 68 deletions.
22 changes: 11 additions & 11 deletions android/src/main/cpp/ResizePlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,31 +150,31 @@ FrameBuffer ResizePlugin::cropARGBBuffer(vision::FrameBuffer frameBuffer, int x,
return destination;
}

FrameBuffer ResizePlugin::flipARGBBuffer(FrameBuffer frameBuffer, bool flip) {
if (!flip) {
FrameBuffer ResizePlugin::mirrorARGBBuffer(FrameBuffer frameBuffer, bool mirror) {
if (!mirror) {
return frameBuffer;
}

__android_log_print(ANDROID_LOG_INFO, TAG, "Flipping ARGB buffer...");
__android_log_print(ANDROID_LOG_INFO, TAG, "Mirroring ARGB buffer...");

size_t channels = getChannelCount(PixelFormat::ARGB);
size_t channelSize = getBytesPerChannel(DataType::UINT8);
size_t argbSize = frameBuffer.width * frameBuffer.height * channels * channelSize;
if (_flipBuffer == nullptr || _flipBuffer->getDirectSize() != argbSize) {
_flipBuffer = allocateBuffer(argbSize, "_flipBuffer");
if (_mirrorBuffer == nullptr || _mirrorBuffer->getDirectSize() != argbSize) {
_mirrorBuffer = allocateBuffer(argbSize, "_mirrorBuffer");
}
FrameBuffer destination = {
.width = frameBuffer.width,
.height = frameBuffer.height,
.pixelFormat = PixelFormat::ARGB,
.dataType = DataType::UINT8,
.buffer = _flipBuffer,
.buffer = _mirrorBuffer,
};

int status = libyuv::ARGBMirror(frameBuffer.data(), frameBuffer.bytesPerRow(), destination.data(), destination.bytesPerRow(),
frameBuffer.width, frameBuffer.height);
if (status != 0) {
throw std::runtime_error("Failed to flip ARGB Buffer! Status: " + std::to_string(status));
throw std::runtime_error("Failed to mirror ARGB Buffer! Status: " + std::to_string(status));
}

return destination;
Expand Down Expand Up @@ -343,7 +343,7 @@ FrameBuffer ResizePlugin::convertBufferToDataType(FrameBuffer frameBuffer, DataT
}

jni::global_ref<jni::JByteBuffer> ResizePlugin::resize(jni::alias_ref<JImage> image, int cropX, int cropY, int cropWidth, int cropHeight,
int scaleWidth, int scaleHeight, int rotation, bool flip,
int scaleWidth, int scaleHeight, int rotationOrdinal, bool mirror,
int /* PixelFormat */ pixelFormatOrdinal, int /* DataType */ dataTypeOrdinal) {
PixelFormat pixelFormat = static_cast<PixelFormat>(pixelFormatOrdinal);
DataType dataType = static_cast<DataType>(dataTypeOrdinal);
Expand All @@ -358,10 +358,10 @@ jni::global_ref<jni::JByteBuffer> ResizePlugin::resize(jni::alias_ref<JImage> im
result = scaleARGBBuffer(result, scaleWidth, scaleHeight);

// 4. Rotate ARGB
result = rotateARGBBuffer(result, rotation);
result = rotateARGBBuffer(result, rotationOrdinal);

// 5 Flip ARGB if needed
result = flipARGBBuffer(result, flip);
// 5 Mirror ARGB if needed
result = mirrorARGBBuffer(result, mirror);

// 6. Convert from ARGB -> ????
result = convertARGBBufferTo(result, pixelFormat);
Expand Down
6 changes: 3 additions & 3 deletions android/src/main/cpp/ResizePlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ struct ResizePlugin : public HybridClass<ResizePlugin> {
explicit ResizePlugin(const alias_ref<jhybridobject>& javaThis);

global_ref<JByteBuffer> resize(alias_ref<JImage> image, int cropX, int cropY, int cropWidth, int cropHeight, int scaleWidth,
int scaleHeight, int rotation, bool flip, int /* PixelFormat */ pixelFormat, int /* DataType */ dataType);
int scaleHeight, int rotation, bool mirror, int /* PixelFormat */ pixelFormat, int /* DataType */ dataType);

FrameBuffer imageToFrameBuffer(alias_ref<JImage> image);
FrameBuffer cropARGBBuffer(FrameBuffer frameBuffer, int x, int y, int width, int height);
FrameBuffer scaleARGBBuffer(FrameBuffer frameBuffer, int width, int height);
FrameBuffer convertARGBBufferTo(FrameBuffer frameBuffer, PixelFormat toFormat);
FrameBuffer convertBufferToDataType(FrameBuffer frameBuffer, DataType dataType);
FrameBuffer rotateARGBBuffer(FrameBuffer frameBuffer, int rotation);
FrameBuffer flipARGBBuffer(FrameBuffer frameBuffer, bool flip);
FrameBuffer mirrorARGBBuffer(FrameBuffer frameBuffer, bool mirror);
global_ref<JByteBuffer> allocateBuffer(size_t size, std::string debugName);

private:
Expand All @@ -62,7 +62,7 @@ struct ResizePlugin : public HybridClass<ResizePlugin> {
global_ref<JByteBuffer> _cropBuffer;
global_ref<JByteBuffer> _scaleBuffer;
global_ref<JByteBuffer> _rotatedBuffer;
global_ref<JByteBuffer> _flipBuffer;
global_ref<JByteBuffer> _mirrorBuffer;
// ARGB (?x?) -> !!!! (?x?)
global_ref<JByteBuffer> _customFormatBuffer;
// Custom Data Type (e.g. float32)
Expand Down
77 changes: 53 additions & 24 deletions android/src/main/java/com/visioncameraresizeplugin/ResizePlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,6 @@ class ResizePlugin(private val proxy: VisionCameraProxy) : FrameProcessorPlugin(
}
}

private external fun resize(image: Image,
cropX: Int, cropY: Int,
cropWidth: Int, cropHeight: Int,
scaleWidth: Int, scaleHeight: Int,
rotation: Int,
flip: Boolean,
pixelFormat: Int, dataType: Int): ByteBuffer
init {
mHybridData = initHybrid()
}
Expand All @@ -55,14 +48,6 @@ class ResizePlugin(private val proxy: VisionCameraProxy) : FrameProcessorPlugin(
throw Error("Options cannot be null!")
}


val image = frame.image

if (image.format != ImageFormat.YUV_420_888) {
throw Error("Frame has invalid PixelFormat! Only YUV_420_888 is supported. Did you set pixelFormat=\"yuv\"?")
}


var cropWidth = frame.width
var cropHeight = frame.height
var cropX = 0
Expand All @@ -71,8 +56,26 @@ class ResizePlugin(private val proxy: VisionCameraProxy) : FrameProcessorPlugin(
var scaleHeight = frame.height
var targetFormat = PixelFormat.ARGB
var targetType = DataType.UINT8
val rotation = (params["rotation"] as? Number)?.toInt() ?: 0
val flip = params["flip"] as? Boolean ?: false

val rotationParam = params["rotation"]
val rotation: Rotation
if (rotationParam is String) {
rotation = Rotation.fromString(rotationParam)
Log.i(TAG, "Rotation: ${rotation.degrees}")
} else {
rotation = Rotation.Rotation0
Log.i(TAG, "Rotation not specified, defaulting to: ${rotation.degrees}")
}

val mirrorParam = params["mirror"]
val mirror: Boolean
if (mirrorParam is Boolean) {
mirror = mirrorParam
Log.i(TAG, "Mirror: $mirror")
} else {
mirror = false
Log.i(TAG, "Mirror not specified, defaulting to: $mirror")
}

val scale = params["scale"] as? Map<*, *>
if (scale != null) {
Expand Down Expand Up @@ -134,13 +137,20 @@ class ResizePlugin(private val proxy: VisionCameraProxy) : FrameProcessorPlugin(
Log.i(TAG, "Target DataType: $targetType")
}

val resized = resize(frame.image,
cropX, cropY,
cropWidth, cropHeight,
scaleWidth, scaleHeight,
rotation,
flip,
targetFormat.ordinal, targetType.ordinal)
val image = frame.image

if (image.format != ImageFormat.YUV_420_888) {
throw Error("Frame has invalid PixelFormat! Only YUV_420_888 is supported. Did you set pixelFormat=\"yuv\"?")
}

val resized = resize(
image,
cropX, cropY,
cropWidth, cropHeight,
scaleWidth, scaleHeight,
rotation.degrees,
mirror,
targetFormat.ordinal, targetType.ordinal)

return SharedArray(proxy, resized)
}
Expand Down Expand Up @@ -183,3 +193,22 @@ class ResizePlugin(private val proxy: VisionCameraProxy) : FrameProcessorPlugin(
}
}
}

private enum class Rotation(val degrees: Int) {
Rotation0(0),
Rotation90(90),
Rotation180(180),
Rotation270(270);

companion object {
fun fromString(value: String): Rotation {
return when (value) {
"0deg" -> Rotation0
"90deg" -> Rotation90
"180deg" -> Rotation180
"270deg" -> Rotation270
else -> throw Error("Invalid rotation value! ($value)")
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = CJW62Q77E7;
DEVELOPMENT_TEAM = JP7B2WX6RY;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = VisionCameraResizePluginExample/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
Expand Down Expand Up @@ -495,7 +495,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = CJW62Q77E7;
DEVELOPMENT_TEAM = JP7B2WX6RY;
INFOPLIST_FILE = VisionCameraResizePluginExample/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand Down
8 changes: 4 additions & 4 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import {
useCameraPermission,
useFrameProcessor,
} from 'react-native-vision-camera';
import { ROTATION, useResizePlugin } from 'vision-camera-resize-plugin';
import { useResizePlugin } from 'vision-camera-resize-plugin';

export default function App() {
const permission = useCameraPermission();
const device = useCameraDevice('front');
const device = useCameraDevice('back');

React.useEffect(() => {
permission.requestPermission();
Expand All @@ -35,8 +35,8 @@ export default function App() {
},
pixelFormat: 'rgba',
dataType: 'uint8',
rotation: ROTATION.R90,
flip: true,
rotation: '90deg',
mirror: true,
});
console.log(
result[Math.round(result.length / 2) + 0],
Expand Down
64 changes: 51 additions & 13 deletions ios/ResizePlugin.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@

#import "FrameBuffer.h"

typedef NS_ENUM(NSInteger, Rotation) {
Rotation0 = 0,
Rotation90 = 90,
Rotation180 = 180,
Rotation270 = 270
};

@interface ResizePlugin : FrameProcessorPlugin
@end

Expand All @@ -27,7 +34,7 @@ @implementation ResizePlugin {
FrameBuffer* _argbBuffer;
// 2. ARGB (?x?) -> ARGB (!x!)
FrameBuffer* _resizeBuffer;
FrameBuffer* _flipBuffer;
FrameBuffer* _mirrorBuffer;
FrameBuffer* _rotateBuffer;
// 3. ARGB (!x!) -> !!!! (!x!)
FrameBuffer* _convertBuffer;
Expand All @@ -51,6 +58,22 @@ - (void)dealloc {
free(_tempResizeBuffer);
}

- (Rotation)parseRotationFromString:(NSString*)rotationString {
if ([rotationString isEqualToString:@"0deg"]) {
return Rotation0;
} else if ([rotationString isEqualToString:@"90deg"]) {
return Rotation90;
} else if ([rotationString isEqualToString:@"180deg"]) {
return Rotation180;
} else if ([rotationString isEqualToString:@"270deg"]) {
return Rotation270;
} else {
@throw [NSException exceptionWithName:@"InvalidRotationValueException"
reason:[NSString stringWithFormat:@"Invalid rotation value! (%@)", rotationString]
userInfo:nil];
}
}

ConvertPixelFormat parsePixelFormat(NSString* pixelFormat) {
if ([pixelFormat isEqualToString:@"rgb"]) {
return RGB;
Expand Down Expand Up @@ -350,31 +373,31 @@ - (FrameBuffer*)convertInt8Buffer:(FrameBuffer*)buffer toDataType:(ConvertDataTy
return _customTypeBuffer;
}

- (FrameBuffer*)flipARGBBuffer:(FrameBuffer*)buffer flip:(BOOL)flip {
- (FrameBuffer*)mirrorARGBBuffer:(FrameBuffer*)buffer mirror:(BOOL)mirror {

if (!flip) {
if (!mirror) {
return buffer;
}

NSLog(@"Flipping ARGB buffer...");
NSLog(@"Mirroring ARGB buffer...");

if (_flipBuffer == nil || _flipBuffer.width != buffer.width || _flipBuffer.height != buffer.height) {
_flipBuffer = [[FrameBuffer alloc] initWithWidth:buffer.width
if (_mirrorBuffer == nil || _mirrorBuffer.width != buffer.width || _mirrorBuffer.height != buffer.height) {
_mirrorBuffer = [[FrameBuffer alloc] initWithWidth:buffer.width
height:buffer.height
pixelFormat:buffer.pixelFormat
dataType:buffer.dataType
proxy:_proxy];
}

vImage_Buffer src = *buffer.imageBuffer;
vImage_Buffer dest = *_flipBuffer.imageBuffer;
vImage_Buffer dest = *_mirrorBuffer.imageBuffer;

vImage_Error error = vImageHorizontalReflect_ARGB8888(&src, &dest, kvImageNoFlags);
if (error != kvImageNoError) {
[NSException raise:@"Flip Error" format:@"Failed to flip ARGB buffer! Error: %ld", error];
[NSException raise:@"Mirror Error" format:@"Failed to mirror ARGB buffer! Error: %ld", error];
}

return _flipBuffer;
return _mirrorBuffer;
}

- (FrameBuffer*)rotateARGBBuffer:(FrameBuffer*)buffer rotation:(int)rotation {
Expand Down Expand Up @@ -460,14 +483,29 @@ - (id)callback:(Frame*)frame withArguments:(NSDictionary*)arguments {
} else {
NSLog(@"ResizePlugin: No custom scale supplied.");
}

NSString* rotationParam = arguments[@"rotation"];
Rotation rotation;
if (rotationParam != nil) {
rotation = [self parseRotationFromString:rotationParam];
NSLog(@"ResizePlugin: Rotation: %ld", (long)rotation);
} else {
rotation = Rotation0;
NSLog(@"ResizePlugin: Rotation not specified, defaulting to: %ld", (long)rotation);
}

NSNumber* mirrorParam = arguments[@"mirror"];
BOOL mirror = NO;
if (mirrorParam != nil) {
mirror = [mirrorParam boolValue];
}
NSLog(@"ResizePlugin: Mirror: %@", mirror ? @"YES" : @"NO");

double cropWidth = (double)frame.width;
double cropHeight = (double)frame.height;
double cropX = 0;
double cropY = 0;
NSDictionary* crop = arguments[@"crop"];
BOOL flip = [[arguments objectForKey:@"flip"] boolValue];
int rotation = [arguments[@"rotation"] intValue];
if (crop != nil) {
cropWidth = ((NSNumber*)crop[@"width"]).doubleValue;
cropHeight = ((NSNumber*)crop[@"height"]).doubleValue;
Expand Down Expand Up @@ -537,8 +575,8 @@ - (id)callback:(Frame*)frame withArguments:(NSDictionary*)arguments {
// 4. Rotate
result = [self rotateARGBBuffer:result rotation:rotation];

// 5. Flip
result = [self flipARGBBuffer:result flip:flip];
// 5. Mirror
result = [self mirrorARGBBuffer:result mirror:mirror];

// 6. Convert ARGB -> ??? format
result = [self convertARGB:result to:pixelFormat];
Expand Down
Loading

0 comments on commit 3ed2cf6

Please sign in to comment.