google-apps-script

How to Add a Watermark or Logo to an Image Using Google Apps Script Automation?


I need a script in Google Apps Script to merge two images into one (add a logo or watermark to an image). I've tried using the Slides API and the Document API, but encountered issues.

Attempt #1: Using Slides API

Here’s the script I wrote:

function addLogoToImage() {
  var imageBlob = UrlFetchApp.fetch("https://........jpg").getBlob();
  var logoBlob = UrlFetchApp.fetch("https://......jpg").getBlob();

  const presentation = SlidesApp.create('temp');
  const slide = presentation.getSlides()[0];

  // Add the main image
  slide.insertImage(imageBlob);

  // Add the logo
  slide.insertImage(logoBlob).setWidth(50).setHeight(50).setTop(10).setLeft(10);

  Utilities.sleep(2000);

  // Export the slide as an image
  const presentationId = presentation.getId();
  const exportUrl = `https://docs.google.com/presentation/d/${presentationId}/export/png`;

  const token = ScriptApp.getOAuthToken();
  const response = UrlFetchApp.fetch(exportUrl, {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });

  const thumbnail = response.getBlob().setName('merged_image.png');
  DriveApp.createFile(thumbnail);

  // Clean up by deleting the presentation
  Drive.Files.remove(presentationId);
}

However, the result is a blank white image of 3 KB in size.

Attempt #2: Using Document API

I also tried the Document API with the following script:

function addLogoWithGoogleDrawings() {
  // Image URLs
  var imageUrl = "https://.........jpg";
  var logoUrl = "https://........jpg";

  // Add the images to a drawing
  var doc = DocumentApp.create("temp");
  var drawingId = doc.getId();
  var body = doc.getBody();
  body.appendImage(UrlFetchApp.fetch(imageUrl).getBlob());
  body.appendImage(UrlFetchApp.fetch(logoUrl).getBlob());

  // Wait for the content to load
  Utilities.sleep(3000);

  // Export as JPG
  const thumbnail = doc.getAs("image/png").setName('merged_image.png');
  DriveApp.createFile(thumbnail);

  // Clean up by deleting the document
  Drive.Files.remove(drawingId);
}

However, as per the documentation, the getAs() method only supports exporting to application/pdf or text/markdown.

Question: Does anyone have an idea how to merge images and export them as a single image file using Google Apps Script? Alternatively, is there a way to fix one of the scripts above?

Bonus...: In the future, I’ll need a similar solution for adding watermarks to videos (e.g., a logo displayed in a corner throughout the video). Any guidance on that would also be greatly appreciated!

Thank you!


Solution

  • Automated Image Merging and Downloading Using Google Apps Script

    This script uses the Google Slides API (via SlidesApp) to automate the creation of a Google Slides presentation. It merges two images by first fetching the main image and a logo or watermark.

    The script then creates a new Google Slides presentation, inserts the images, and adjusts their sizes and positions.

    The slide is saved as a PNG image, which is stored in Google Drive, and the temporary Google Slides presentation is deleted.

    Code:

    function downloadMergedSlide() {
      var pngFile = mergeAndConvertToPng();
    
      var html = "<script>window.open('" + pngFile.getDownloadUrl() + "');google.script.host.close();</script>";
      var userInterface = HtmlService.createHtmlOutput(html)
        .setHeight(10)
        .setWidth(100);
    
      SlidesApp.getUi().showModalDialog(userInterface, 'Downloading PNG ...');
    
      pngFile.setTrashed(true);
    }
    
    function mergeAndConvertToPng() {
      const mainImageURL = "https://........jpg";
      const logoImageURL = "https://........jpg";
    
      const mainImageBlob = UrlFetchApp.fetch(mainImageURL).getBlob();
      const logoImageBlob = UrlFetchApp.fetch(logoImageURL).getBlob();
    
      const presentation = SlidesApp.create("Temp Merged Slide");
      const slide = presentation.getSlides()[0];
    
      const mainImage = slide.insertImage(mainImageBlob);
      mainImage.setWidth(960).setHeight(540).setTop(0).setLeft(0);
    
      const logoImage = slide.insertImage(logoImageBlob);
      logoImage.setWidth(50).setHeight(50).setTop(10).setLeft(10);
    
      presentation.saveAndClose();
    
      const presentationId = presentation.getId();
      const exportUrl = `https://docs.google.com/presentation/d/${presentationId}/export/png`;
      const token = ScriptApp.getOAuthToken();
    
      const response = UrlFetchApp.fetch(exportUrl, {
        headers: {
          Authorization: `Bearer ${token}`,
        },
        muteHttpExceptions: true,
      });
    
      if (response.getResponseCode() === 200) {
        const pngBlob = response.getBlob();
        const pngFile = DriveApp.createFile(pngBlob.setName("merged_image.png"));
    
       
        DriveApp.getFileById(presentationId).setTrashed(true);
    
        return pngFile;
    
      }
    
      return null;
    }
    

    Sample Output:

    Sample

    To adjust the size or position of the images, you can change the values of setWidth(), setHeight(), setTop(), and setLeft() for both images.

    Reference:

    insertImage

    getfilebyid

    createHtmlOutput(blob)