Rework scaled dimensions and compression (#737)

* Rework scaled dimensions and compression

* Unbreak image / banner uploads

---------

Co-authored-by: Paul Frazee <pfrazee@gmail.com>
This commit is contained in:
Ollie H 2023-05-30 17:23:55 -07:00 committed by GitHub
parent deebe18aaa
commit 072682dd9f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 175 additions and 238 deletions

View file

@ -110,6 +110,7 @@ export async function post(store: RootStoreModel, opts: PostOpts) {
const images: AppBskyEmbedImages.Image[] = []
for (const image of opts.images) {
opts.onStateChange?.(`Uploading image #${images.length + 1}...`)
await image.compress()
const path = image.compressed?.path ?? image.path
const res = await uploadBlob(store, path, 'image/jpeg')
images.push({

View file

@ -6,52 +6,8 @@ import * as RNFS from 'react-native-fs'
import uuid from 'react-native-uuid'
import * as Sharing from 'expo-sharing'
import {Dimensions} from './types'
import {POST_IMG_MAX} from 'lib/constants'
import {isAndroid, isIOS} from 'platform/detection'
export async function compressAndResizeImageForPost(
image: Image,
): Promise<Image> {
const uri = `file://${image.path}`
let resized: Omit<Image, 'mime'>
for (let i = 0; i < 9; i++) {
const quality = 100 - i * 10
try {
resized = await ImageResizer.createResizedImage(
uri,
POST_IMG_MAX.width,
POST_IMG_MAX.height,
'JPEG',
quality,
undefined,
undefined,
undefined,
{mode: 'cover'},
)
} catch (err) {
throw new Error(`Failed to resize: ${err}`)
}
if (resized.size < POST_IMG_MAX.size) {
const path = await moveToPermanentPath(resized.path)
return {
path,
mime: 'image/jpeg',
size: resized.size,
height: resized.height,
width: resized.width,
}
}
}
throw new Error(
`This image is too big! We couldn't compress it down to ${POST_IMG_MAX.size} bytes`,
)
}
export async function compressIfNeeded(
img: Image,
maxSize: number = 1000000,

View file

@ -1,25 +1,6 @@
import {Dimensions} from './types'
import {Image as RNImage} from 'react-native-image-crop-picker'
import {getDataUriSize, blobToDataUri} from './util'
import {POST_IMG_MAX} from 'lib/constants'
export async function compressAndResizeImageForPost({
path,
width,
height,
}: {
path: string
width: number
height: number
}): Promise<RNImage> {
// Compression is handled in `doResize` via `quality`
return await doResize(path, {
width,
height,
maxSize: POST_IMG_MAX.size,
mode: 'stretch',
})
}
export async function compressIfNeeded(
img: RNImage,

View file

@ -2,7 +2,7 @@ import {RootStoreModel} from 'state/index'
import {Image as RNImage} from 'react-native-image-crop-picker'
import RNFS from 'react-native-fs'
import {CropperOptions} from './types'
import {compressAndResizeImageForPost} from './manip'
import {compressIfNeeded} from './manip'
let _imageCounter = 0
async function getFile() {
@ -13,7 +13,7 @@ async function getFile() {
.join('/'),
)
const file = files[_imageCounter++ % files.length]
return await compressAndResizeImageForPost({
return await compressIfNeeded({
path: file.path,
mime: 'image/jpeg',
size: file.size,

View file

@ -1,5 +1,3 @@
import {Dimensions} from './types'
export function extractDataUriMime(uri: string): string {
return uri.substring(uri.indexOf(':') + 1, uri.indexOf(';'))
}
@ -10,21 +8,6 @@ export function getDataUriSize(uri: string): number {
return Math.round((uri.length * 3) / 4)
}
export function scaleDownDimensions(
dim: Dimensions,
max: Dimensions,
): Dimensions {
if (dim.width < max.width && dim.height < max.height) {
return dim
}
const wScale = dim.width > max.width ? max.width / dim.width : 1
const hScale = dim.height > max.height ? max.height / dim.height : 1
if (wScale < hScale) {
return {width: dim.width * wScale, height: dim.height * wScale}
}
return {width: dim.width * hScale, height: dim.height * hScale}
}
export function isUriImage(uri: string) {
return /\.(jpg|jpeg|png).*$/.test(uri)
}