Skip to content

Commit

Permalink
Android support added for all existing methods
Browse files Browse the repository at this point in the history
  • Loading branch information
fearmear committed Dec 17, 2018
1 parent fd6ae5b commit 38567b6
Show file tree
Hide file tree
Showing 5 changed files with 387 additions and 42 deletions.
15 changes: 2 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# react-native-image-tools-wm
A collection of image processing tools for React Native

## Getting started

Expand Down Expand Up @@ -35,7 +36,7 @@
```
3. Insert the following lines inside the dependencies block in `android/app/build.gradle`:
```
compile project(':react-native-image-tools-wm')
implementation project(':react-native-image-tools-wm')
```
## Usage

Expand All @@ -46,8 +47,6 @@ See examples in the API section.

## API
### mask(image, maskImage)
#### Platform support warning
Not implemented on Android yet.
#### Parameter(s)
* **image:** String - path to image
* **maskImage:** String - path to mask image
Expand All @@ -68,8 +67,6 @@ RNImageTools.mask(image, maskImage, {


### transform(image, translateX, translateY, scale, rotate)
#### Platform support warning
Not implemented on Android yet.
#### Parameter(s)
* **image:** String - path to image
* **translateX:** Number
Expand All @@ -91,8 +88,6 @@ RNImageTools.transform(image, 10, -10, 1.25, 45)


### resize(image, width, height)
#### Platform support warning
Not implemented on Android yet.
#### Parameter(s)
* **image:** String - path to image
* **width:** Number
Expand All @@ -112,8 +107,6 @@ RNImageTools.resize(image, 500, 500)


### crop(image, x, y, width, height)
#### Platform support warning
Not implemented on Android yet.
#### Parameter(s)
* **image:** String - path to image
* **x:** Number - top offset
Expand All @@ -136,8 +129,6 @@ RNImageTools.crop(image, 100, 100, 500, 500)

### createMaskFromShape(options)
Creates a bitmap with white background and draws a black shape from provided points. It's intended usage is to generate mask images on the fly.
#### Platform support warning
Not implemented on Android yet.
#### Parameter(s)
* **options:** Object
* **points:** Array of points
Expand Down Expand Up @@ -169,8 +160,6 @@ RNImageTools.createMaskFromShape({
```

### merge(images)
#### Platform support warning
Not implemented on Android yet.
#### Parameter(s)
* **images:** Array
* **uri:** String - path to image
Expand Down
22 changes: 7 additions & 15 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@

buildscript {
repositories {
jcenter()
}

dependencies {
classpath 'com.android.tools.build:gradle:1.3.1'
}
def safeExtGet(prop, fallback) {
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
}

apply plugin: 'com.android.library'

android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
compileSdkVersion safeExtGet('compileSdkVersion', 26)
buildToolsVersion safeExtGet('buildToolsVersion', "26.0.3")

defaultConfig {
minSdkVersion 16
targetSdkVersion 22
minSdkVersion safeExtGet('minSdkVersion', 16)
targetSdkVersion safeExtGet('targetSdkVersion', 26)
versionCode 1
versionName "1.0"
}
Expand All @@ -31,6 +24,5 @@ repositories {
}

dependencies {
compile 'com.facebook.react:react-native:+'
implementation 'com.facebook.react:react-native:+'
}

245 changes: 235 additions & 10 deletions android/src/main/java/net/wowmaking/RNImageToolsModule.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,247 @@

package net.wowmaking;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;

import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;

import java.io.File;
import java.util.HashMap;

public class RNImageToolsModule extends ReactContextBaseJavaModule {

private final ReactApplicationContext reactContext;
private final ReactApplicationContext reactContext;

public RNImageToolsModule(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
}

@ReactMethod
public void resize(String uriString, int width, int height, final Promise promise) {
Bitmap bmp = Utility.bitmapFromUriString(uriString, promise);
if (bmp == null) {
return;
}

final HashMap containedRectMap = Utility.calcRectForContainedRect(
bmp.getWidth(), bmp.getHeight(),
width, height
);
int rectWidth = (int) containedRectMap.get("width");
int rectHeight = (int) containedRectMap.get("height");
int rectX = (int) containedRectMap.get("x");
int rectY = (int) containedRectMap.get("y");

Bitmap editBmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(editBmp);

Rect srcRect = new Rect(0, 0, bmp.getWidth(), bmp.getHeight());
Rect dstRect = new Rect(rectX, rectY, rectWidth + rectX, rectHeight + rectY);

canvas.drawBitmap(bmp, srcRect, dstRect, null);

File file = Utility.createRandomPNGFile(reactContext);
Utility.writeBMPToPNGFile(editBmp, file, promise);

final WritableMap map = Utility.buildImageReactMap(file, editBmp);
promise.resolve(map);
}

@ReactMethod
public void crop(String uriString, int x, int y, int width, int height, final Promise promise) {
Bitmap bmp = Utility.bitmapFromUriString(uriString, promise);
if (bmp == null) {
return;
}
Bitmap croppedBmp = Bitmap.createBitmap(bmp, x, y, width, height);

File file = Utility.createRandomPNGFile(reactContext);
Utility.writeBMPToPNGFile(croppedBmp, file, promise);

final WritableMap map = Utility.buildImageReactMap(file, croppedBmp);
promise.resolve(map);
}

@ReactMethod
public void transform(String uriString, float translateX, float translateY, float rotate, float scale, final Promise promise) {
Bitmap bmp = Utility.bitmapFromUriString(uriString, promise);
if (bmp == null) {
return;
}
Matrix mtrx = new Matrix();
mtrx.preTranslate(translateX, translateY);
mtrx.preTranslate(bmp.getWidth() / 2 * (1 - scale), bmp.getHeight() / 2 * (1 - scale));
mtrx.preScale(scale, scale);
mtrx.preRotate(rotate, bmp.getWidth() / 2, bmp.getHeight() / 2);

Bitmap editBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);

Canvas canvas = new Canvas(editBmp);
Paint rectPaint = new Paint();
rectPaint.setColor(Color.WHITE);
canvas.drawRect(0, 0, bmp.getWidth(), bmp.getHeight(), rectPaint);
canvas.drawBitmap(bmp, mtrx, null);

File file = Utility.createRandomPNGFile(reactContext);
Utility.writeBMPToPNGFile(editBmp, file, promise);

final WritableMap map = Utility.buildImageReactMap(file, editBmp);
promise.resolve(map);
}

@ReactMethod
public void merge(ReadableArray uriStrings, Promise promise) {
Bitmap firstBmp = Utility.bitmapFromUriString(uriStrings.getString(0), promise);
if (firstBmp == null) {
return;
}
Bitmap editBmp = Bitmap.createBitmap(firstBmp.getWidth(), firstBmp.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(editBmp);
canvas.drawBitmap(firstBmp, new Matrix(), null);

for (int i = 1; i < uriStrings.size(); i++) {
Bitmap bmp = Utility.bitmapFromUriString(uriStrings.getString(i), promise);
if (bmp == null) {
return;
}
Rect srcRect = new Rect(0, 0, bmp.getWidth(), bmp.getHeight());
Rect dstRect = new Rect(0, 0, canvas.getWidth(), canvas.getHeight());
canvas.drawBitmap(bmp, srcRect, dstRect, null);
}

File file = Utility.createRandomPNGFile(reactContext);
Utility.writeBMPToPNGFile(editBmp, file, promise);

final WritableMap map = Utility.buildImageReactMap(file, editBmp);
promise.resolve(map);
}

@ReactMethod
public void createMaskFromShape(ReadableMap options, Promise promise) {
final ReadableArray points = options.getArray("points");
final int width = options.getInt("width");
final int height = options.getInt("height");
final boolean inverted = options.getBoolean("inverted");

final int bgColor = inverted ? Color.BLACK : Color.WHITE;
final int shapeColor = inverted ? Color.WHITE : Color.BLACK;

Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);

final Rect bgRect = new Rect(0, 0, width, height);
final Paint bgPaint = new Paint();
bgPaint.setColor(bgColor);
if (bgColor == Color.BLACK) {
bgPaint.setAlpha(0);
}


canvas.drawRect(bgRect, bgPaint);


final Path shapePath = new Path();

for (int i = 0; i < points.size(); i++) {
final ReadableMap pointsItem = points.getMap(i);
final int x = pointsItem.getInt("x");
final int y = pointsItem.getInt("y");
if (i == 0) {
shapePath.moveTo(x, y);
} else {
shapePath.lineTo(x, y);
}
if (i == points.size() - 1) {
shapePath.close();
}
}

final Paint shapePaint = new Paint();
shapePaint.setColor(shapeColor);
if (shapeColor == Color.BLACK) {
shapePaint.setAlpha(0);
}

canvas.drawPath(shapePath, shapePaint);


File file = Utility.createRandomPNGFile(reactContext);
Utility.writeBMPToPNGFile(bmp, file, promise);

final WritableMap map = Utility.buildImageReactMap(file, bmp);
promise.resolve(map);
}

@ReactMethod
public void mask(String uriString, String maskUriString, ReadableMap options, Promise promise) {

final boolean trimTransparency = options.getBoolean("trimTransparency");

Bitmap bmp = Utility.bitmapFromUriString(uriString, promise);
if (bmp == null) {
return;
}

Bitmap maskBmp = Utility.bitmapFromUriString(maskUriString, promise);
if (maskBmp == null) {
return;
}

final HashMap containedRectMap = Utility.calcRectForContainedRect(
maskBmp.getWidth(), maskBmp.getHeight(),
bmp.getWidth(), bmp.getHeight()
);
int editWidth = (int) containedRectMap.get("width");
int editHeight = (int) containedRectMap.get("height");
int editX = (int) containedRectMap.get("x");
int editY = (int) containedRectMap.get("y");

Bitmap editBmp = Bitmap.createBitmap(editWidth, editHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(editBmp);

Paint maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));

canvas.drawBitmap(bmp, -editX, editY, null);

Rect maskSrcRect = new Rect(0, 0, maskBmp.getWidth(), maskBmp.getHeight());
Rect maskDstRect = new Rect(0, 0, canvas.getWidth(), canvas.getHeight());

canvas.drawBitmap(maskBmp, maskSrcRect, maskDstRect, maskPaint);

maskPaint.setXfermode(null);

canvas.drawBitmap(editBmp, 0, 0, new Paint());

if (trimTransparency) {
editBmp = Utility.trimTransparency(editBmp);
}

File file = Utility.createRandomPNGFile(reactContext);
Utility.writeBMPToPNGFile(editBmp, file, promise);

final WritableMap map = Utility.buildImageReactMap(file, editBmp);
promise.resolve(map);
}

public RNImageToolsModule(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
}

@Override
public String getName() {
return "RNImageTools";
}
@Override
public String getName() {
return "RNImageTools";
}
}
Loading

0 comments on commit 38567b6

Please sign in to comment.