Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix rotation on Android, using EXIF data #20

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 166 additions & 7 deletions android/src/main/java/com/terrylinla/rnsketchcanvas/SketchCanvas.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.os.Environment;
import android.util.Base64;
import android.util.Log;
Expand All @@ -26,6 +28,15 @@
import java.io.FileOutputStream;
import java.util.ArrayList;

class CanvasText {
public String text;
public Paint paint;
public PointF anchor, position, drawPosition, lineOffset;
public boolean isAbsoluteCoordinate;
public Rect textBounds;
public float height;
}

public class SketchCanvas extends View {

private ArrayList<SketchData> mPaths = new ArrayList<SketchData>();
Expand All @@ -44,6 +55,10 @@ public class SketchCanvas extends View {
private Bitmap mBackgroundImage;
private String mContentMode;

private ArrayList<CanvasText> mArrCanvasText = new ArrayList<CanvasText>();
private ArrayList<CanvasText> mArrTextOnSketch = new ArrayList<CanvasText>();
private ArrayList<CanvasText> mArrSketchOnText = new ArrayList<CanvasText>();

public SketchCanvas(ThemedReactContext context) {
super(context);
mContext = context;
Expand All @@ -56,10 +71,30 @@ public boolean openImageFile(String filename, String directory, String mode) {
"drawable",
mContext.getPackageName());
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
File file = new File(filename, directory == null ? "" : directory);
Bitmap bitmap = res == 0 ?
BitmapFactory.decodeFile(new File(filename, directory == null ? "" : directory).toString(), bitmapOptions) :
BitmapFactory.decodeFile(file.toString(), bitmapOptions) :
BitmapFactory.decodeResource(mContext.getResources(), res);
if(bitmap != null) {

try {
ExifInterface exif = new ExifInterface(file.getAbsolutePath());
Matrix matrix = new Matrix();

int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
matrix.postRotate(90);
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
matrix.postRotate(180);
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
matrix.postRotate(270);
}

bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); // rotating bitmap
} catch (Exception e) {

}

if (bitmap != null) {
mBackgroundImage = bitmap;
mOriginalHeight = bitmap.getHeight();
mOriginalWidth = bitmap.getWidth();
Expand All @@ -73,6 +108,96 @@ public boolean openImageFile(String filename, String directory, String mode) {
return false;
}

public void setCanvasText(ReadableArray aText) {
mArrCanvasText.clear();
mArrSketchOnText.clear();
mArrTextOnSketch.clear();

if (aText != null) {
for (int i=0; i<aText.size(); i++) {
ReadableMap property = aText.getMap(i);
if (property.hasKey("text")) {
String alignment = property.hasKey("alignment") ? property.getString("alignment") : "Left";
int lineOffset = 0, maxTextWidth = 0;
String[] lines = property.getString("text").split("\n");
ArrayList<CanvasText> textSet = new ArrayList<CanvasText>(lines.length);
for (String line: lines) {
ArrayList<CanvasText> arr = property.hasKey("overlay") && "TextOnSketch".equals(property.getString("overlay")) ? mArrTextOnSketch : mArrSketchOnText;
CanvasText text = new CanvasText();
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setTextAlign(Paint.Align.LEFT);
text.text = line;
if (property.hasKey("font")) {
Typeface font;
try {
font = Typeface.createFromAsset(mContext.getAssets(), property.getString("font"));
} catch(Exception ex) {
font = Typeface.create(property.getString("font"), Typeface.NORMAL);
}
p.setTypeface(font);
}
p.setTextSize(property.hasKey("fontSize") ? (float)property.getDouble("fontSize") : 12);
p.setColor(property.hasKey("fontColor") ? property.getInt("fontColor") : 0xFF000000);
text.anchor = property.hasKey("anchor") ? new PointF((float)property.getMap("anchor").getDouble("x"), (float)property.getMap("anchor").getDouble("y")) : new PointF(0, 0);
text.position = property.hasKey("position") ? new PointF((float)property.getMap("position").getDouble("x"), (float)property.getMap("position").getDouble("y")) : new PointF(0, 0);
text.paint = p;
text.isAbsoluteCoordinate = !(property.hasKey("coordinate") && "Ratio".equals(property.getString("coordinate")));
text.textBounds = new Rect();
p.getTextBounds(text.text, 0, text.text.length(), text.textBounds);

text.lineOffset = new PointF(0, lineOffset);
lineOffset += text.textBounds.height() * 1.5 * (property.hasKey("lineHeightMultiple") ? property.getDouble("lineHeightMultiple") : 1);
maxTextWidth = Math.max(maxTextWidth, text.textBounds.width());

arr.add(text);
mArrCanvasText.add(text);
textSet.add(text);
}
for(CanvasText text: textSet) {
text.height = lineOffset;
if (text.textBounds.width() < maxTextWidth) {
float diff = maxTextWidth - text.textBounds.width();
text.textBounds.left += diff * text.anchor.x;
text.textBounds.right += diff * text.anchor.x;
}
}
if (getWidth() > 0 && getHeight() > 0) {
for(CanvasText text: textSet) {
text.height = lineOffset;
PointF position = new PointF(text.position.x, text.position.y);
if (!text.isAbsoluteCoordinate) {
position.x *= getWidth();
position.y *= getHeight();
}
position.x -= text.textBounds.left;
position.y -= text.textBounds.top;
position.x -= (text.textBounds.width() * text.anchor.x);
position.y -= (text.height * text.anchor.y);
text.drawPosition = position;
}
}
if (lines.length > 1) {
for(CanvasText text: textSet) {
switch(alignment) {
case "Left":
default:
break;
case "Right":
text.lineOffset.x = (maxTextWidth - text.textBounds.width());
break;
case "Center":
text.lineOffset.x = (maxTextWidth - text.textBounds.width()) / 2;
break;
}
}
}
}
}
}

invalidateCanvas(false);
}

public void clear() {
mPaths.clear();
mCurrentPath = null;
Expand Down Expand Up @@ -161,11 +286,11 @@ public void onSaved(boolean success, String path) {
event);
}

public void save(String format, String folder, String filename, boolean transparent, boolean includeImage, boolean cropToImageSize) {
public void save(String format, String folder, String filename, boolean transparent, boolean includeImage, boolean includeText, boolean cropToImageSize) {
File f = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + folder);
boolean success = f.exists() ? true : f.mkdirs();
if (success) {
Bitmap bitmap = createImage(format.equals("png") && transparent, includeImage, cropToImageSize);
Bitmap bitmap = createImage(format.equals("png") && transparent, includeImage, includeText, cropToImageSize);

File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) +
File.separator + folder + File.separator + filename + (format.equals("png") ? ".png" : ".jpg"));
Expand All @@ -185,9 +310,9 @@ public void save(String format, String folder, String filename, boolean transpar
}
}

public String getBase64(String format, boolean transparent, boolean includeImage, boolean cropToImageSize) {
public String getBase64(String format, boolean transparent, boolean includeImage, boolean includeText, boolean cropToImageSize) {
WritableMap event = Arguments.createMap();
Bitmap bitmap = createImage(format.equals("png") && transparent, includeImage, cropToImageSize);
Bitmap bitmap = createImage(format.equals("png") && transparent, includeImage, includeText, cropToImageSize);
ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();

bitmap.compress(
Expand All @@ -209,6 +334,21 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
Bitmap.Config.ARGB_8888);
mTranslucentDrawingCanvas = new Canvas(mTranslucentDrawingBitmap);

for(CanvasText text: mArrCanvasText) {
PointF position = new PointF(text.position.x, text.position.y);
if (!text.isAbsoluteCoordinate) {
position.x *= getWidth();
position.y *= getHeight();
}

position.x -= text.textBounds.left;
position.y -= text.textBounds.top;
position.x -= (text.textBounds.width() * text.anchor.x);
position.y -= (text.height * text.anchor.y);
text.drawPosition = position;

}

mNeedsFullRedraw = true;
invalidate();
}
Expand All @@ -234,13 +374,21 @@ protected void onDraw(Canvas canvas) {
null);
}

for(CanvasText text: mArrSketchOnText) {
canvas.drawText(text.text, text.drawPosition.x + text.lineOffset.x, text.drawPosition.y + text.lineOffset.y, text.paint);
}

if (mDrawingBitmap != null) {
canvas.drawBitmap(mDrawingBitmap, 0, 0, mPaint);
}

if (mTranslucentDrawingBitmap != null && mCurrentPath != null && mCurrentPath.isTranslucent) {
canvas.drawBitmap(mTranslucentDrawingBitmap, 0, 0, mPaint);
}

for(CanvasText text: mArrTextOnSketch) {
canvas.drawText(text.text, text.drawPosition.x + text.lineOffset.x, text.drawPosition.y + text.lineOffset.y, text.paint);
}
}

private void invalidateCanvas(boolean shouldDispatchEvent) {
Expand All @@ -255,7 +403,7 @@ private void invalidateCanvas(boolean shouldDispatchEvent) {
invalidate();
}

private Bitmap createImage(boolean transparent, boolean includeImage, boolean cropToImageSize) {
private Bitmap createImage(boolean transparent, boolean includeImage, boolean includeText, boolean cropToImageSize) {
Bitmap bitmap = Bitmap.createBitmap(
mBackgroundImage != null && cropToImageSize ? mOriginalWidth : getWidth(),
mBackgroundImage != null && cropToImageSize ? mOriginalHeight : getHeight(),
Expand All @@ -270,6 +418,12 @@ private Bitmap createImage(boolean transparent, boolean includeImage, boolean cr
canvas.drawBitmap(mBackgroundImage, null, targetRect, null);
}

if (includeText) {
for(CanvasText text: mArrSketchOnText) {
canvas.drawText(text.text, text.drawPosition.x + text.lineOffset.x, text.drawPosition.y + text.lineOffset.y, text.paint);
}
}

if (mBackgroundImage != null && cropToImageSize) {
Rect targetRect = new Rect();
Utility.fillImage(mDrawingBitmap.getWidth(), mDrawingBitmap.getHeight(),
Expand All @@ -279,6 +433,11 @@ private Bitmap createImage(boolean transparent, boolean includeImage, boolean cr
canvas.drawBitmap(mDrawingBitmap, 0, 0, mPaint);
}

if (includeText) {
for(CanvasText text: mArrTextOnSketch) {
canvas.drawText(text.text, text.drawPosition.x + text.lineOffset.x, text.drawPosition.y + text.lineOffset.y, text.paint);
}
}
return bitmap;
}
}