IONIC - 电容器/相机 - 更改图像大小或压缩图像

问题描述 投票:0回答:1

我使用以下代码使用@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
}
image ionic-framework camera resize compression
1个回答
0
投票

终于可以解决我的问题了。

我可以找到并合并不同平台和语言的各种解决方案,以生成我自己的调整图片大小的函数(使用画布,是的,但不与 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)中测试调整大小功能,以查看照片的最终尺寸。

© www.soinside.com 2019 - 2024. All rights reserved.