'How to change the pixel quality and size of Image using Google Apps Script?

I have a list of image URLs and I want to get all those images which are more than 14Mb in size or 14 Megapixel in quality and resize them to under 5Mb in size and 10 Megapixel in quality. I used Image library provided by @Tanaike on Github to manipulate image size and quality.

Here is the code snippet to download the image as a blob and check its size and dimension using ImgApp library:

 funtion CompressImage() {

    var url = "http://images.salsify.com/image/upload/s--PyaEswlb
--/f595bd4e42783097f42e4615e17024b6b82da014.jpg";

      var folderId = "Your Folder ID";
      var folder = DriveApp.getFolderById(folderId);
 
      var response = UrlFetchApp.fetch(url)
      var fileBlob = response.getBlob()
 
   
      var res = ImgApp.getSize(fileBlob);
   
       
       if((res.filesize/1000000)>14 || res.width>14000000)
       {
       
         ProcessImage(fileBlob , folder);
       
       }
}

The If statement in the above code checks the file size and pixel quality, if it is above the threshold (14Mb size, 14 Megapixel quality) then it executes the ProcessImage function. This function sets the width size, and replaces the old image with the newly resized image.

  function ProcessImage(fileBlob,folder) 

  {
   
  var width = 3600; // Please set the size of width with the unit of pixels.
  var file = folder.createFile(fileBlob);

  var fileId = file.getId();
  var link = Drive.Files.get(fileId).thumbnailLink.replace(/\=s.+/, "=s" + width);
  var blob2 = UrlFetchApp.fetch(link).getBlob().setName("Compressed Image");
  var file = folder.createFile(blob2);
  
  var img = Drive.Files.get(file.getId()).webContentLink; //get the view link of image downloaded in drive
  Logger.log(img);
  Drive.Files.remove(fileId); 
    
   }

The above two functions combine to get the resized image which is less than 14 Mb in size but I am not able to change the pixel quality of the image (less than 14 Megapixel). Can you please guide what am I doing wrong? Any help would be much appreciated. Thank you.



Solution 1:[1]

I believe your goal is as follows.

  • You want to reduce the image size from 4480x4480 to 2000x2000. At this time, you want to reduce the lower quality of the image.
  • You want to achieve this using Google Apps Script.

Issue and workaround:

I thought that in this case, for example, when you want to reduce the image size from 4480x4480 to 2000x2000, the following flow can achieve your goal.

  1. Reduce the image from 4480x4480 to 100x100.
  2. Increase the image from 100x100 to 2000x2000.

By this, the image quality can be reduced by keeping the size. But, unfortunately, the method using thumbnailLink cannot increase the image. By this, it is required to use another workaround.

In this answer, I would like to propose another workaround for changing the image size.

Usage

1. Install Google Apps Script library.

As one more Google Apps Script library, please install DocsServiceApp. You can see how to install it at here.

2. Sample script.

When your script is used, the modified script is as follows. In this case, I modified your function ProcessImage.

// Please run this function.
function CompressImage() {
  var url = "http://images.salsify.com/image/upload/s--54TepGAl--/2f76d5ec5400b654b6f3dbd068db7898a76389cf.jpg";
  var folderId = "root";
  var folder = DriveApp.getFolderById(folderId);
  var response = UrlFetchApp.fetch(url)
  var fileBlob = response.getBlob()
  var res = ImgApp.getSize(fileBlob);
  if ((res.filesize / 1000000) > 14 || res.width > 14000000) {
    ProcessImage(fileBlob, folder);
  }
}

function ProcessImage(fileBlob, folder) {
  var width1 = 100; // Please adjust this value.
  var width2 = 2000; // Please adjust this value.

  // Create original image as a file.
  var file1 = folder.createFile(fileBlob);
  var fileId1 = file1.getId();

  // Reduce original image size.
  var link1 = Drive.Files.get(fileId1).thumbnailLink.replace(/\=s.+/, "=s" + width1);

  // Increase converted image size.
  const object = { title: "temp", parent: "root", width: { unit: "pixel", size: width2 }, height: { unit: "pixel", size: width2 } };
  const sId = DocsServiceApp.createNewSlidesWithPageSize(object);
  const s = SlidesApp.openById(sId);
  const slide = s.getSlides()[0];
  slide.insertImage(link1).setWidth(width2 / 1.33333).setHeight(width2 / 1.33333);
  s.saveAndClose();

  // Retrieve result image.
  const link2 = Slides.Presentations.Pages.getThumbnail(sId, slide.getObjectId(), { "thumbnailProperties.thumbnailSize": "LARGE" }).contentUrl;
  var blob2 = UrlFetchApp.fetch(link2).getBlob().setName("Compressed Image");
  var file2 = folder.createFile(blob2);
  var img = Drive.Files.get(file2.getId()).webContentLink;
  Logger.log(img);

  Drive.Files.remove(fileId1);
  Drive.Files.remove(sId);
}
  • IMPORTANT: In this workaround, as an important point, by the current specification of Slides API, the output image size can be selected only 3 patterns like LARGE (The thumbnail image width of 1600px.), MEDIUM (The thumbnail image width of 800px.), SMALL (The thumbnail image width of 200px.). I think that this is the bottleneck of this workaround.

  • When this script is run, the image size of the original image is converted from 4480x4480 to 100x100 using thumbnailLink. And, the image of 100x100 is converted to 2000x2000 using DocsServiceApp and Google Slides. And, when an image is exported from Google Slides, an image with low quality with 1600x1600 is obtained.

Note:

  • 100x100 and 2000x2000 are the sample sizes. So, please modify the values of var width1 = 100; and var width2 = 2000; for your actual situation. By this, you can control the quarity of the image.

Reference:

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tanaike