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

4

28

I have the based64 encoded code of an image. Now I want to reduce the size and quality of the image. How can I do this in JavaScript or jQuery?

Resolve here is the working code : Index.php Here is javascript code which worked form me

<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 file

<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>
Midiron answered 4/12, 2013 at 15:14 Comment(2)
Is there a solution with ruby,ruby on rails, php?Nonsectarian
@PradeepJaiswar Thanks for the solution, but it's better to post a self-answer than edit your solution into the question.Bethesda
B
40

You can use canvas, put image into it, scale it and get image src with new base64 code.

Here's the function doing that, it returns promise object, as image needs to be loaded (cached) first before drawing canvas out of it and getting its encoded 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();    
}

Can be used like this:

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

here's the jsfiddle

Beseem answered 4/12, 2013 at 18:0 Comment(3)
How can I cast the resized image to a File object?Auvil
This is nice but one note: ...).load(function()... should now be ....).on('load', function()... #38872253Raynata
.load() and .on('load') is not the same!Throne
E
22

A non-jquery solution based on @paulitto 's answer for future googlers like me:

/**
 * 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)=>{
        const 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());               
        }
    });
}

Use it like:

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

Note that this function returns a base64 string. To get an <img>, you can use something like

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

Example:

function resizeBase64Img(base64, newWidth, newHeight) {
    return new Promise((resolve, reject)=>{
        const 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;
}
Elisabethelisabethville answered 10/8, 2020 at 22:38 Comment(1)
canvas.style.width = newWidth.toString()+"px"; should be canvas.width = newWidth;. Same for height.Throne
T
1

Here is an improved typescript pro version.

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
    }
  }
}

Transubstantiate answered 27/6, 2022 at 17:57 Comment(0)
C
0

Here's another solution, reduce width/height until it satisfies the image size.

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);
}

Cyclostyle answered 24/5, 2023 at 12:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.