Optimize compressImage method to also use binary search (#7490)

* use binary search for compressImage

* use binary search for doResize (mobile version)

* use binary search for doResize (web version)

* use safeDeleteAsync in compressImage

---------

Co-authored-by: nguyen <nguyensvo123@gmail.com>
This commit is contained in:
Kae
2025-04-27 04:10:32 +10:00
committed by GitHub
parent ea718190ca
commit 1eb678cabd
3 changed files with 56 additions and 21 deletions
+20 -7
View File
@@ -178,15 +178,20 @@ async function doResize(localUri: string, opts: DoResizeOpts): Promise<Image> {
height: imageRes.height,
})
for (let i = 0; i < 9; i++) {
// nearest 10th
const quality = Math.round((1 - 0.1 * i) * 10) / 10
let minQualityPercentage = 0
let maxQualityPercentage = 101 // exclusive
let newDataUri
while (maxQualityPercentage - minQualityPercentage > 1) {
const qualityPercentage = Math.round(
(maxQualityPercentage + minQualityPercentage) / 2,
)
const resizeRes = await manipulateAsync(
localUri,
[{resize: newDimensions}],
{
format: SaveFormat.JPEG,
compress: quality,
compress: qualityPercentage / 100,
},
)
@@ -198,8 +203,8 @@ async function doResize(localUri: string, opts: DoResizeOpts): Promise<Image> {
}
if (fileInfo.size < opts.maxSize) {
safeDeleteAsync(imageRes.uri)
return {
minQualityPercentage = qualityPercentage
newDataUri = {
path: normalizePath(resizeRes.uri),
mime: 'image/jpeg',
size: fileInfo.size,
@@ -207,9 +212,17 @@ async function doResize(localUri: string, opts: DoResizeOpts): Promise<Image> {
height: resizeRes.height,
}
} else {
safeDeleteAsync(resizeRes.uri)
maxQualityPercentage = qualityPercentage
}
safeDeleteAsync(resizeRes.uri)
}
if (newDataUri) {
safeDeleteAsync(imageRes.uri)
return newDataUri
}
throw new Error(
`This image is too big! We couldn't compress it down to ${opts.maxSize} bytes`,
)
+16 -5
View File
@@ -72,17 +72,28 @@ interface DoResizeOpts {
async function doResize(dataUri: string, opts: DoResizeOpts): Promise<RNImage> {
let newDataUri
for (let i = 0; i <= 10; i++) {
newDataUri = await createResizedImage(dataUri, {
let minQualityPercentage = 0
let maxQualityPercentage = 101 //exclusive
while (maxQualityPercentage - minQualityPercentage > 1) {
const qualityPercentage = Math.round(
(maxQualityPercentage + minQualityPercentage) / 2,
)
const tempDataUri = await createResizedImage(dataUri, {
width: opts.width,
height: opts.height,
quality: 1 - i * 0.1,
quality: qualityPercentage / 100,
mode: opts.mode,
})
if (getDataUriSize(newDataUri) < opts.maxSize) {
break
if (getDataUriSize(tempDataUri) < opts.maxSize) {
minQualityPercentage = qualityPercentage
newDataUri = tempDataUri
} else {
maxQualityPercentage = qualityPercentage
}
}
if (!newDataUri) {
throw new Error('Failed to compress image')
}