我使用以下代码使用@capacitor/camera 库拍照:
let capturedPhoto:any = await Camera
.getPhoto({
resultType: CameraResultType.Uri,
source: CameraSource.Camera,
quality: 30,
height: 150,
allowEditing: false,
direction: CameraDirection.Front
})
.catch(err => {
});
当我在 Android 或 iOS 中使用带有此代码的应用程序时,图片文件太大(接近 4MB)。该文件需要存储在 Firebase Storage 中,我需要节省空间,因为大量用户的成本可能会成为问题。
所以我不知道如何调整图片大小或压缩图像?我需要在打字稿中实现一些算法,而不使用画布或 HTML。这可能吗?
我的想法是使用“capturedPhoto”并以某种方式处理它,但是我能找到的所有选项都使用canvas或HTML元素并且不起作用或者我不知道我必须如何实现。
capturePhoto 具有这种格式,当尝试放入 jpg 时,Camera.getPhoto 的“选项”,不要让我。
{
"webPath": "blob:http://localhost:8100/df29b43e-da65-4345-8bbb-704a8745d483",
"format": "png",
"saved": false
}
终于可以解决我的问题了。
我可以找到并合并不同平台和语言的各种解决方案,以生成我自己的调整图片大小的函数(使用画布,是的,但不与 HTML 页面交互)。
第一次测试非常顺利,用电脑摄像头拍的照片有285KB,最后结果是2.75KB(极度缩小),再加上png到jpg的转换。
我接下来介绍该功能(resizeImage),但将其与我的项目中需要使用的所有其他功能集成在一个服务中。
import { Injectable } from '@angular/core';
// NATIVE CAMERA
import { Camera, CameraDirection, CameraResultType, CameraSource, Photo } from '@capacitor/camera';
import {decode} from "base64-arraybuffer";
// https://ionicframework.com/docs/native/camera
// https://www.npmjs.com/package/@capacitor/camera
import * as moment from 'moment'
@Injectable({
providedIn: 'root'
})
export class PhotoService {
base64ResizedImage: string = null;
constructor(
) { }
async takePicture() {
return await Camera
.getPhoto({
resultType: CameraResultType.Uri,
source: CameraSource.Camera,
quality: 30,
height: 150,
allowEditing: false,
direction: CameraDirection.Front
})
.catch(err => {
return undefined;
});
}
base64StringToFile(base64String: string, format: string) {
const blob = new Blob([new Uint8Array(decode(base64String))], {
type: `image/${format}`,
});
let file:any = new File([blob], "Name", {
lastModified: moment().unix(),
type: blob.type,
});
return file;
}
base64Tobase64String(base64: string) {
console.log("photo.service.ts: base64Tobase64String => base64", base64);
let result = base64.split(';base64,')[1];
console.log("photo.service.ts: base64Tobase64String => base64String", result);
return result;
}
getTypeBase64(base64: string) {
let type = base64.substring("data:image/".length, base64.indexOf(";base64"));
console.log("photo.service.ts: getTypeBase64 => type", type);
return type;
}
resizeImage(base64image: string, width: number, height: number) {
return new Promise((resolve, reject) => {
console.log("photo.service.ts: resizeImage => entered");
let img = new Image();
img.src = base64image;
var that = this;
img.onload = function () {
console.log("photo.service.ts: resizeImage => img.onload");
// Check if the image require resize at all
if(img.height <= height && img.width <= width) {
that.base64ResizedImage = base64image;
// TODO: Call method to do something with the resize image
console.log("photo.service.ts: resizeImage => not require resize");
resolve (that.base64ResizedImage);
}
else {
// Make sure the width and height preserve the original aspect ratio and adjust if needed
if(img.height > img.width) {
width = Math.floor(height * (img.width / img.height));
}
else {
height = Math.floor(width * (img.height / img.width));
}
let resizingCanvas: HTMLCanvasElement = document.createElement('canvas');
let resizingCanvasContext = resizingCanvas.getContext("2d");
// Start with original image size
resizingCanvas.width = img.width;
resizingCanvas.height = img.height;
// Draw the original image on the (temp) resizing canvas
resizingCanvasContext.drawImage(img, 0, 0, resizingCanvas.width, resizingCanvas.height);
let curImageDimensions = {
width: Math.floor(img.width),
height: Math.floor(img.height)
};
let halfImageDimensions = {
width: 0,
height: 0
};
// Quickly reduce the dize by 50% each time in few iterations until the size is less then
// 2x time the target size - the motivation for it, is to reduce the aliasing that would have been
// created with direct reduction of very big image to small image
while (curImageDimensions.width * 0.5 > width) {
// Reduce the resizing canvas by half and refresh the image
halfImageDimensions.width = Math.floor(curImageDimensions.width * 0.5);
halfImageDimensions.height = Math.floor(curImageDimensions.height * 0.5);
resizingCanvasContext.drawImage(resizingCanvas, 0, 0, curImageDimensions.width, curImageDimensions.height, 0, 0, halfImageDimensions.width, halfImageDimensions.height);
curImageDimensions.width = halfImageDimensions.width;
curImageDimensions.height = halfImageDimensions.height;
}
// Now do final resize for the resizingCanvas to meet the dimension requirments
// directly to the output canvas, that will output the final image
let outputCanvas: HTMLCanvasElement = document.createElement('canvas');
let outputCanvasContext = outputCanvas.getContext("2d");
outputCanvas.width = width;
outputCanvas.height = height;
outputCanvasContext.drawImage(resizingCanvas, 0, 0, curImageDimensions.width, curImageDimensions.height, 0, 0, width, height);
// output the canvas pixels as an image. params: format, quality
that.base64ResizedImage = outputCanvas.toDataURL('image/jpeg', 0.85);
// TODO: Call method to do something with the resize image
console.log("photo.service.ts: resizeImage => resize OK");
resolve (that.base64ResizedImage);
}
}
img.onerror = reject;
});
}
}
现在,我的下一步是在手机(Android 或 iOS)中测试调整大小功能,以查看照片的最终尺寸。