JavaScript使用based64编码代码降低图像的大小和质量

JavaScript reduce the size and quality of image with based64 encoded code

本文关键字:图像 based64 使用 编码 代码 JavaScript      更新时间:2024-02-28

我有一个图像的based64编码代码。现在我想缩小图像的大小和质量。如何在JavaScript或jQuery中做到这一点?

这里解决的是工作代码:Index.php这是我的javascript代码

<html>
<head>
<title>JavaScript Image Resize</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<style>
body {
    font-size: 16px;
    font-family: Arial;
}
</style>
<script type="text/javascript">
function _resize(img, maxWidth, maxHeight) 
{
    var ratio = 1;
    var canvas = document.createElement("canvas");
    canvas.style.display="none";
    document.body.appendChild(canvas);
    var canvasCopy = document.createElement("canvas");
    canvasCopy.style.display="none";
    document.body.appendChild(canvasCopy);
    var ctx = canvas.getContext("2d");
    var copyContext = canvasCopy.getContext("2d");
        if(img.width > maxWidth)
                ratio = maxWidth / img.width;
        else if(img.height > maxHeight)
                ratio = maxHeight / img.height;
        canvasCopy.width = img.width;
        canvasCopy.height = img.height;
try {
        copyContext.drawImage(img, 0, 0);
} catch (e) { 
    document.getElementById('loader').style.display="none";
    alert("There was a problem - please reupload your image");
    return false;
}
        canvas.width = img.width * ratio;
        canvas.height = img.height * ratio;
        // the line to change
        //ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
        // the method signature you are using is for slicing
        ctx.drawImage(canvasCopy, 0, 0, canvas.width, canvas.height);
        var dataURL = canvas.toDataURL("image/png");
        document.body.removeChild(canvas);
        document.body.removeChild(canvasCopy);
        return dataURL.replace(/^data:image'/(png|jpg);base64,/, "");

};
function resize() { 
    var photo = document.getElementById("photo");
    if(photo.files!=undefined){ 
        var loader = document.getElementById("loader");
        loader.style.display = "inline";
        var file  = photo.files[0];
        document.getElementById("orig").value = file.fileSize;
        var preview = document.getElementById("preview");
        var r = new FileReader();
        r.onload = (function(previewImage) { 
            return function(e) { 
                var maxx = 500;
                var maxy = 500;
                previewImage.src = e.target.result; 
                var k = _resize(previewImage, maxx, maxy);
                if(k!=false) { 
                document.getElementById('base64').value= k;
                document.getElementById('upload').submit();
                } else {
                alert('problem - please attempt to upload again');
                }
            }; 
        })(preview);
        r.readAsDataURL(file);
    } else {
        alert("Seems your browser doesn't support resizing");
    }
    return false;
}
</script>
</head>
<body>
<div align="center">
<h2>Image Resize Demo</h2>
    <input type="file" name="photo" id="photo">
    <br> 
    <br>    
    <input type="button" onClick="resize();" value="Resize">
    <img src="loader.gif" id="loader" />
    <img src="" alt="Image preview" id="preview">
   <form name="upload" id="upload" method='post' action='show.php'>
        <textarea name="base64" id="base64" rows='10' cols='90'></textarea>
        <input type="hidden" id="orig" name="orig" value=""/>
   </form>
</div>
</body>
</html>

Show.php文件

<html>
<head>
<title>JavaScript file upload</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<style>
body {
    font-size: 16px;
    font-family: Arial;
}
#preview {
    display:none;
}
#base64 {
    display:none;
}
</style>
</head>
<body>
<?php
$base64size = strlen($_POST['base64']);
$f = base64_decode($_POST['base64']);
$name = microtime(true).".png";
file_put_contents("./$name", $f);
#header("Content-type: image/png");
#header("Content-Disposition: attachment; filename='"shrunk.png'"");
#echo $f;
#die();
?>
<h2>Shrunk file</h2>
<p>Original file was: <?=$_POST['orig'];?> bytes</p>
<p>Transmitted size was: <?=$base64size;?> bytes (due to base64)</p>
<p>New file is: <?=filesize("./$name");?> bytes</p>
<p><img src="<?=$name;?>"/></p>
</body>
</html>

您可以使用画布,将图像放入其中,缩放它,并使用新的base64代码获得图像src。

这是一个函数,它返回promise对象,因为在从中绘制画布并获得编码的src之前,需要首先加载(缓存)图像。

function resizeBase64Img(base64, width, height) {
    var canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    var context = canvas.getContext("2d");
    var deferred = $.Deferred();
    $("<img/>").attr("src", "data:image/gif;base64," + base64).load(function() {
        context.scale(width/this.width,  height/this.height);
        context.drawImage(this, 0, 0); 
        deferred.resolve($("<img/>").attr("src", canvas.toDataURL()));               
    });
    return deferred.promise();    
}

可以这样使用:

resizeBase64Img(oldBase64, 100, 100).then(function(newImg){
    $("body").append(newImg);
});

这是jsfiddle

一个基于@paulitto的非jquery解决方案,适用于像我这样的未来谷歌用户:

/**
 * Resize a base 64 Image
 * @param {String} base64 - The base64 string (must include MIME type)
 * @param {Number} newWidth - The width of the image in pixels
 * @param {Number} newHeight - The height of the image in pixels
 */
function resizeBase64Img(base64, newWidth, newHeight) {
    return new Promise((resolve, reject)=>{
        var canvas = document.createElement("canvas");
        canvas.style.width = newWidth.toString()+"px";
        canvas.style.height = newHeight.toString()+"px";
        let context = canvas.getContext("2d");
        let img = document.createElement("img");
        img.src = base64;
        img.onload = function () {
            context.scale(newWidth/img.width,  newHeight/img.height);
            context.drawImage(img, 0, 0); 
            resolve(canvas.toDataURL());               
        }
    });
}

像一样使用

resizeBase64Img(basedata, 50, 50).then((result)=>{
    console.log("After resize: "+result);
});

请注意,此函数返回一个base64字符串。要获得<img>,您可以使用类似的东西

resizeBase64Img(basedata, 50, 50).then((result)=>{
    let img = document.createElement("img");
    img.onload = ()=>{
        // do something with the img
    }
    img.src = result;
});

示例:

function resizeBase64Img(base64, newWidth, newHeight) {
    return new Promise((resolve, reject)=>{
        var canvas = document.createElement("canvas");
        canvas.width = newWidth;
        canvas.height = newHeight;
        let context = canvas.getContext("2d");
        let img = document.createElement("img");
        img.src = base64;
        img.onload = function () {
            context.scale(newWidth/img.width,  newHeight/img.height);
            context.drawImage(img, 0, 0); 
            resolve(canvas.toDataURL());               
        }
    });
}
let base64 = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/4QCgRXhpZgAATU0AKgAAAAgABQEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAAEyAAIAAAAUAAAAWodpAAQAAAABAAAAbgAAAAAAAABgAAAAAQAAAGAAAAABMjAyMDoxMjozMSAwOTozODoxNwAAA6ABAAMAAAABAAEAAKACAAMAAAABAEwAAKADAAMAAAABADIAAAAAAAD/4QyJaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA1LjUuMCI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjAtMTItMzFUMDk6Mzg6MTctMDU6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDIwLTEyLTMxVDA5OjM4OjE3LTA1OjAwIj4gPGRjOnRpdGxlPiA8cmRmOkFsdD4gPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5DaXR5c2NhcGVfYW5kX3NreWxpbmVfYnlfdGhlX0NvcGVuaGFnZW5fTGFrZXMsX0Rlbm1hcmtfLV8oMzYwMTgxMDk5NTYpPC9yZGY6bGk+IDwvcmRmOkFsdD4gPC9kYzp0aXRsZT4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHhtcE1NOmFjdGlvbj0icHJvZHVjZWQiIHhtcE1NOnNvZnR3YXJlQWdlbnQ9IkFmZmluaXR5IFBob3RvIChOb3YgIDYgMjAyMCkiIHhtcE1NOndoZW49IjIwMjAtMTItMzFUMDk6MzY6MjktMDU6MDAiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InByb2R1Y2VkIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZmZpbml0eSBQaG90byAoTm92ICA2IDIwMjApIiBzdEV2dDp3aGVuPSIyMDIwLTEyLTMxVDA5OjM4OjE3LTA1OjAwIi8+IDwvcmRmOlNlcT4gPC94bXBNTTpIaXN0b3J5PiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8P3hwYWNrZXQgZW5kPSJ3Ij8+/+0BkFBob3Rvc2hvcCAzLjAAOEJJTQPtAAAAAAAQAGAAAAABAAIAYAAAAAEAAjhCSU0D8gAAAAAACgAA////////AAA4QklNBAQAAAAAAFQcAVoAAxslRxwCAAACAAQcAgUAQENpdHlzY2FwZV9hbmRfc2t5bGluZV9ieV90aGVfQ29wZW5oYWdlbl9MYWtlcyxfRGVubWFya18tXygzNjAxODE4QklNBAYAAAAAAAcACAAAAAMBADhCSU0ECAAAAAAAEAAAAAEAAAJAAAAC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";
document.body.append("Before: ");
let before = document.createElement("img");
before.src = base64;
document.body.appendChild(before);
resizeBase64Img(base64, 20, 20).then(resized=>{
  document.body.append("After: ");
  let img = document.createElement("img");
  img.src = resized;
  document.body.appendChild(img);
});
img {
  display: block;
}

这里是一个改进的typescript专业版。

export type ResizeOptions = {
  newSizeOrScale: number
  sizeOrScale: 'size' | 'scale'
  target: 'width' | 'height'
}
export type ImageSizes = {
  width: number
  height: number
}


export class Img {
  /**
   *
   *
   *
   *
   * converts an image file to base64 date url (get image file from and input element with type of file)
   */
  static async toBase64(imageFile: File, onError?: (error: ProgressEvent<FileReader>) => void) {
    const toBase64 = (): Promise<string | null> => {
      return new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.readAsDataURL(imageFile)
        reader.onload = () => resolve(<string | null>reader.result)
        reader.onerror = reject
      })
    }
    try {
      return await toBase64()
    } catch (error) {
      onError?.(error as ProgressEvent<FileReader>)
      return null
    }
  }
  /**
   *
   *
   *
   *
   * convert a base64 date url to an image element
   */
  static async base64ToImage(base64: string, onError?: (error?: Error) => void): Promise<HTMLImageElement | null> {
    const getImage = (): Promise<HTMLImageElement | null> => {
      return new Promise((resolve, reject) => {
        const image = new Image()
        image.src = base64
        image.onload = () => resolve(image)
        image.onerror = (_0, _1, _2, _3, error) => reject(error)
      })
    }
    try {
      return await getImage()
    } catch (error) {
      onError?.(error as Error | undefined)
      return null
    }
  }
  /**
   *
   *
   *
   *
   * returns the actual size of and image (image could be a base64 data url or a file)
   */
  static async getSizes(image: File | string, onError?: (error?: Error | undefined | ProgressEvent<FileReader>) => void) {
    const base64Image = typeof image === 'string' ? image : await Img.toBase64(image, onError)
    if (!base64Image) {
      return null
    }
    const getSizes = (): Promise<ImageSizes | null> => {
      return new Promise(function (resolve, reject) {
        const image = new Image()
        image.onload = () => resolve(image)
        image.onerror = (_0, _1, _2, _3, error) => reject(error)
        image.src = base64Image
      })
    }
    try {
      return await getSizes()
    } catch (error) {
      onError?.(error as Error | undefined)
      return null
    }
  }
  /**
   *
   *
   *
   *
   * it's a helper for the Img.decreaseSize static method
   * helps to calculate the new width and height of the given image on that method
   */
  private static calculateSize(defaultWidth: number, defaultHeight: number, scaleOrCustom: ResizeOptions): ImageSizes {
    const { newSizeOrScale, sizeOrScale, target } = scaleOrCustom
    let width = defaultWidth
    let height = defaultHeight
    switch (sizeOrScale) {
      case 'scale': {
        width = defaultWidth / newSizeOrScale
        height = defaultHeight / newSizeOrScale
        break
      }
      case 'size': {
        if (target === 'width') {
          if (defaultWidth > newSizeOrScale) {
            width = newSizeOrScale
            height = (defaultHeight * newSizeOrScale) / defaultWidth
          }
        } else {
          if (defaultHeight > newSizeOrScale) {
            height = newSizeOrScale
            width = (defaultWidth * newSizeOrScale) / defaultHeight
          }
        }
        break
      }
    }
    return { width, height }
  }
  /**
   *
   *
   *
   *
   * resizes an image (image could be a base64 data url or a file)
   */
  static async resize(
    image: File | string,
    scaleOrCustom: ResizeOptions = {
      newSizeOrScale: 0.5,
      sizeOrScale: 'scale',
      target: 'width',
    },
    onError?: (error?: ProgressEvent<FileReader> | Error) => void,
  ) {
    const resize = async (): Promise<string | null> => {
      return new Promise(async (resolve, reject) => {
        const _image = typeof image === 'string' ? image : await Img.toBase64(image, reject)
        if (!_image) return null
        const sizes = await Img.getSizes(_image, reject)
        if (!sizes) return
        const { width: defaultWidth, height: defaultHeight } = sizes
        const { width: newWidth, height: newHeight } = Img.calculateSize(defaultWidth, defaultHeight, scaleOrCustom)
        const canvas = document.createElement('canvas')
        canvas.width = newWidth
        canvas.height = newHeight
        const context = canvas.getContext('2d')
        if (!context) return
        const img = await Img.base64ToImage(_image, reject)
        if (!img) return
        context.drawImage(img, 0, 0, newWidth, newHeight)
        resolve(canvas.toDataURL())
      })
    }
    try {
      return await resize()
    } catch (error) {
      onError?.(error as ProgressEvent<FileReader> | Error)
      return null
    }
  }
}

这里有另一个解决方案,减少宽度/高度,直到它满足图像大小。

const maxFileSize = 2 * 1024 * 1024; // 2Mb, image should have width/height which will give not more 2Mb
let base64: string = await this.resizeImage(base64);
while (getBase64Size(base64) > maxFileSize) {
    base64 = await this.resizeImage(base64);
}
// at this point, base64 will be lower than maxFileSize. You can put it in img.src
private async resizeImage(base64: string): Promise<string> {
    return new Promise((resolve) => {
        const image = document.createElement('img');
        image.src = base64;
        image.onload = () => {
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            const decreaser = 0.86;
            canvas.width = image.width * decreaser;
            canvas.height = image.height * decreaser;
            ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
            resolve(canvas.toDataURL());
        };
    });
}
private getBase64Size(base64: string): number {
    return Math.ceil(base64.length * 0.73);
}