Add resolution downsizing to image compression
This commit is contained in:
+27
-13
@@ -204,20 +204,17 @@ export async function compressImage(
|
|||||||
img: ComposerImage,
|
img: ComposerImage,
|
||||||
options?: {
|
options?: {
|
||||||
highResolution?: boolean
|
highResolution?: boolean
|
||||||
|
attempts?: number
|
||||||
|
maxDimension?: number
|
||||||
},
|
},
|
||||||
): Promise<PickerImage> {
|
): Promise<PickerImage> {
|
||||||
const source = img.transformed || img.source
|
const source = img.transformed || img.source
|
||||||
|
const highResolution = options?.highResolution ?? false
|
||||||
|
const attempts = options?.attempts || 0
|
||||||
|
const maxDimension =
|
||||||
|
options?.maxDimension || (highResolution ? 4000 : POST_IMG_MAX.width)
|
||||||
|
|
||||||
const [w, h] = containImageRes(
|
const [w, h] = containImageRes(source.width, source.height, maxDimension)
|
||||||
source.width,
|
|
||||||
source.height,
|
|
||||||
options?.highResolution
|
|
||||||
? {
|
|
||||||
width: 4000,
|
|
||||||
height: 4000,
|
|
||||||
}
|
|
||||||
: POST_IMG_MAX,
|
|
||||||
)
|
|
||||||
|
|
||||||
let minQualityPercentage = 0
|
let minQualityPercentage = 0
|
||||||
let maxQualityPercentage = 101 // exclusive
|
let maxQualityPercentage = 101 // exclusive
|
||||||
@@ -228,6 +225,15 @@ export async function compressImage(
|
|||||||
(maxQualityPercentage + minQualityPercentage) / 2,
|
(maxQualityPercentage + minQualityPercentage) / 2,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In the event the image doesn't compress well, we want to avoid
|
||||||
|
* unecessary iterations. In this case, binary search will check 51, 26,
|
||||||
|
* 13(rounded). We don't want to go below 25, hence the break here at 13,
|
||||||
|
* which will result in a subsequent attempt with a smaller maxDimension
|
||||||
|
* and reset qualityPercentage to 100.
|
||||||
|
*/
|
||||||
|
if (qualityPercentage <= 13) break
|
||||||
|
|
||||||
const res = await manipulateAsync(
|
const res = await manipulateAsync(
|
||||||
source.path,
|
source.path,
|
||||||
[{resize: {width: w, height: h}}],
|
[{resize: {width: w, height: h}}],
|
||||||
@@ -258,6 +264,14 @@ export async function compressImage(
|
|||||||
return newDataUri
|
return newDataUri
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (attempts < 4) {
|
||||||
|
return compressImage(img, {
|
||||||
|
highResolution,
|
||||||
|
attempts: attempts + 1,
|
||||||
|
maxDimension: maxDimension * 0.8,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
throw new Error(`Unable to compress image`)
|
throw new Error(`Unable to compress image`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,12 +380,12 @@ function joinPath(a: string, b: string) {
|
|||||||
function containImageRes(
|
function containImageRes(
|
||||||
w: number,
|
w: number,
|
||||||
h: number,
|
h: number,
|
||||||
{width: maxW, height: maxH}: {width: number; height: number},
|
max: number,
|
||||||
): [width: number, height: number] {
|
): [width: number, height: number] {
|
||||||
let scale = 1
|
let scale = 1
|
||||||
|
|
||||||
if (w > maxW || h > maxH) {
|
if (w > max || h > max) {
|
||||||
scale = w > h ? maxW / w : maxH / h
|
scale = w > h ? max / w : max / h
|
||||||
w = Math.floor(w * scale)
|
w = Math.floor(w * scale)
|
||||||
h = Math.floor(h * scale)
|
h = Math.floor(h * scale)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user