forked from Expensify/App
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Revert "[New architecture] Replace `@oguzhnatly/react-native-image-ma…
…nipulator` with `expo-image-manipulator`"
- Loading branch information
1 parent
626207f
commit 52491bd
Showing
9 changed files
with
170 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
patches/@oguzhnatly+react-native-image-manipulator+1.0.5.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
diff --git a/node_modules/@oguzhnatly/react-native-image-manipulator/android/build.gradle b/node_modules/@oguzhnatly/react-native-image-manipulator/android/build.gradle | ||
index 3a1a548..fe030bb 100644 | ||
--- a/node_modules/@oguzhnatly/react-native-image-manipulator/android/build.gradle | ||
+++ b/node_modules/@oguzhnatly/react-native-image-manipulator/android/build.gradle | ||
@@ -13,12 +13,12 @@ buildscript { | ||
apply plugin: 'com.android.library' | ||
|
||
android { | ||
- compileSdkVersion 28 | ||
+ compileSdkVersion 34 | ||
buildToolsVersion "28.0.3" | ||
|
||
defaultConfig { | ||
minSdkVersion 16 | ||
- targetSdkVersion 28 | ||
+ targetSdkVersion 34 | ||
versionCode 1 | ||
versionName "1.0" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,127 @@ | ||
import {manipulateAsync} from 'expo-image-manipulator'; | ||
import getSaveFormat from './getSaveFormat'; | ||
import type {CropOrRotateImage} from './types'; | ||
import type {CropOptions, CropOrRotateImage, CropOrRotateImageOptions} from './types'; | ||
|
||
const cropOrRotateImage: CropOrRotateImage = (uri, actions, options) => | ||
new Promise((resolve) => { | ||
const format = getSaveFormat(options.type); | ||
manipulateAsync(uri, actions, {compress: options.compress, format}).then((result) => { | ||
fetch(result.uri) | ||
.then((res) => res.blob()) | ||
.then((blob) => { | ||
const file = new File([blob], options.name || 'fileName.jpeg', {type: options.type || 'image/jpeg'}); | ||
file.uri = URL.createObjectURL(file); | ||
resolve(file); | ||
}); | ||
type SizeFromAngle = { | ||
width: number; | ||
height: number; | ||
}; | ||
|
||
/** | ||
* Calculates a size of canvas after rotation | ||
*/ | ||
function sizeFromAngle(width: number, height: number, angle: number): SizeFromAngle { | ||
const radians = (angle * Math.PI) / 180; | ||
let sine = Math.cos(radians); | ||
let cosine = Math.sin(radians); | ||
if (cosine < 0) { | ||
cosine = -cosine; | ||
} | ||
if (sine < 0) { | ||
sine = -sine; | ||
} | ||
return {width: height * cosine + width * sine, height: height * sine + width * cosine}; | ||
} | ||
|
||
/** | ||
* Creates a new rotated canvas | ||
*/ | ||
function rotateCanvas(canvas: HTMLCanvasElement, degrees: number): HTMLCanvasElement { | ||
const {width, height} = sizeFromAngle(canvas.width, canvas.height, degrees); | ||
|
||
// We have to create a new canvas because it is not possible to change already drawn | ||
// elements. Transformations such as rotation have to be applied before drawing | ||
const result = document.createElement('canvas'); | ||
result.width = width; | ||
result.height = height; | ||
|
||
const context = result.getContext('2d'); | ||
if (context) { | ||
// In order to rotate image along its center we have to apply next transformation | ||
context.translate(result.width / 2, result.height / 2); | ||
|
||
const radians = (degrees * Math.PI) / 180; | ||
context.rotate(radians); | ||
|
||
context.drawImage(canvas, -canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height); | ||
} | ||
return result; | ||
} | ||
|
||
/** | ||
* Creates new cropped canvas and returns it | ||
*/ | ||
function cropCanvas(canvas: HTMLCanvasElement, options: CropOptions) { | ||
let {originX = 0, originY = 0, width = 0, height = 0} = options; | ||
const clamp = (value: number, max: number) => Math.max(0, Math.min(max, value)); | ||
|
||
width = clamp(width, canvas.width); | ||
height = clamp(height, canvas.height); | ||
originX = clamp(originX, canvas.width); | ||
originY = clamp(originY, canvas.height); | ||
|
||
width = Math.min(originX + width, canvas.width) - originX; | ||
height = Math.min(originY + height, canvas.height) - originY; | ||
|
||
const result = document.createElement('canvas'); | ||
result.width = width; | ||
result.height = height; | ||
|
||
const context = result.getContext('2d'); | ||
context?.drawImage(canvas, originX, originY, width, height, 0, 0, width, height); | ||
|
||
return result; | ||
} | ||
|
||
function convertCanvasToFile(canvas: HTMLCanvasElement, options: CropOrRotateImageOptions): Promise<File> { | ||
return new Promise((resolve) => { | ||
canvas.toBlob((blob) => { | ||
if (!blob) { | ||
return; | ||
} | ||
const file = new File([blob], options.name || 'fileName.jpeg', {type: options.type || 'image/jpeg'}); | ||
file.uri = URL.createObjectURL(file); | ||
resolve(file); | ||
}); | ||
}); | ||
} | ||
|
||
/** | ||
* Loads image from specified url | ||
*/ | ||
function loadImageAsync(uri: string): Promise<HTMLCanvasElement> { | ||
return new Promise((resolve, reject) => { | ||
const imageSource = new Image(); | ||
imageSource.crossOrigin = 'anonymous'; | ||
const canvas = document.createElement('canvas'); | ||
imageSource.onload = () => { | ||
canvas.width = imageSource.naturalWidth; | ||
canvas.height = imageSource.naturalHeight; | ||
|
||
const context = canvas.getContext('2d'); | ||
context?.drawImage(imageSource, 0, 0, imageSource.naturalWidth, imageSource.naturalHeight); | ||
|
||
resolve(canvas); | ||
}; | ||
imageSource.onerror = () => reject(canvas); | ||
imageSource.src = uri; | ||
}); | ||
} | ||
|
||
/** | ||
* Crops and rotates the image on web | ||
*/ | ||
|
||
const cropOrRotateImage: CropOrRotateImage = (uri, actions, options) => | ||
loadImageAsync(uri).then((originalCanvas) => { | ||
const resultCanvas = actions.reduce((canvas, action) => { | ||
if (action.crop) { | ||
return cropCanvas(canvas, action.crop); | ||
} | ||
if (action.rotate) { | ||
return rotateCanvas(canvas, action.rotate); | ||
} | ||
return canvas; | ||
}, originalCanvas); | ||
return convertCanvasToFile(resultCanvas, options); | ||
}); | ||
|
||
export default cropOrRotateImage; |
Oops, something went wrong.