skip to Main Content

In order for me to download an image published on a Telegram channel, I need this path:

var contents = JSON.parse(e.postData.contents);
Logger.log(contents.channel_post.photo);

And the answer is:

[{
    "file_id":"AAAAA",
    "file_size":11111,
    "width":253,
    "height":320
},{
    "file_id":"BBBBB",
    "file_size":22222,
    "width":632,
    "height":800
},{
    "file_id":"CCCCC",
    "file_size":44444,
    "width":1400,
    "height":1100
},{
    "file_id":"DDDDD",
    "file_size":33333,
    "width":980,
    "height":750
}]

The user @Newbie told me to use Math.max(width, height) to be able to define which of the container has the highest quality image so that I can define in this call which file_id should i use for download:

contents.channel_post.photo[CONTAINER NUMBER].file_id

In this case the container would be number 3. But I couldn’t work with this Math.max, I need help to understand how my code should be to do this work.

3

Answers


  1. To retrieve an image URL from a Message object from the Telegram Bot Api you will need to:

    • Retrieve a Message object (from any of the various APIs)
    • extract photo field of type PhotoSize[] Documented Here
    • when you choose a PhotoSize (in your case the biggest one) you have file_id
    • the you need to pass file_id to getFile() Documented Here
    • it will return a File object Documented Here
    • that can be then assembled in a URL like https://api.telegram.org/file/bot<token>/<file_path>
    Login or Signup to reply.
  2. you can find highest quality image like this:

    Math.max.apply(Math, array.map(function(o) { return o.width * o.height; }))
    
    Login or Signup to reply.
  3. Is the image quality not already determined by the file_size property? It appears as the resolution increases (width * height), so does the file_size and thereby the quality as well. For this, check my first solution above.

    If instead, you want to find the highest quality image based on a ratio comparing width * height and file_size to find the average file_size in bytes per pixel (not recommended), please check my second solution below:

    Finding the largest image

    This solution sorts the returned array of image data by comparing their resolution (width * height) and then takes the first (largest) image from the newly sorted array.

    const contents = {}; contents.channel_post = {}; contents.channel_post.photo = [
      { file_id: "AAAAA", file_size: 11111, width: 253, height: 320 },
      { file_id: "BBBBB", file_size: 22222, width: 632, height: 800 },
      { file_id: "CCCCC", file_size: 44444, width: 1400, height: 1100 },
      { file_id: "DDDDD", file_size: 33333, width: 980, height: 750 }
    ];
    
    const largestImage = contents.channel_post.photo.sort((a, b) => (b.width * b.height) - (a.width * a.height))[0];
    
    console.log(`The largest image's file_id is ${largestImage.file_id}, which contains ${largestImage.width * largestImage.height} pixels (${largestImage.width}×${largestImage.height})`);

    Finding the highest quality image (per pixel)

    If you are specifically trying to determine the actual "quality" of the image regardless of resolution, the closest you could get with the data provided would be to divide the file_size by the total pixel area to determine the average file_size in byte per pixel.

    By this logic though, the highest quality image would actually be "AAAAA" which I doubt is what you are going for, so you should probably use the first solution I provided, which returns the largest image.

    It’s worth noting that because image compression algorithms are quite advanced these days, using a formula like this to determine quality per pixel is hardly reliable as it is, so I do recommend using the first solution.

    const contents = {}; contents.channel_post = {}; contents.channel_post.photo = [
      { file_id: "AAAAA", file_size: 11111, width: 253, height: 320 },
      { file_id: "BBBBB", file_size: 22222, width: 632, height: 800 },
      { file_id: "CCCCC", file_size: 44444, width: 1400, height: 1100 },
      { file_id: "DDDDD", file_size: 33333, width: 980, height: 750 }
    ];
    
    const calcImageQuality = ({ file_size, width, height }) => file_size / (width * height);
    const highestQualityImage = contents.channel_post.photo.sort((a, b) => calcImageQuality(b) - calcImageQuality(a))[0];
    
    console.log(`The highest quality image's file_id is ${highestQualityImage.file_id}, which contains ${calcImageQuality(highestQualityImage)} bytes per pixel on average`);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search