{
  "$schema": "https://appvau.lt/api/v1/openapi.json",
  "dataset": "image-specs",
  "title": "Image format support, resize arithmetic and platform size limits",
  "description": "What a browser can decode and encode, the exact resize modes and quality ladder the tools on this site run, mail attachment ceilings with the real file budget computed from each, and profile-image dimensions for ten platforms.",
  "updated": "2026-09-11",
  "source": "https://appvau.lt",
  "documentation": "https://appvau.lt/tools/",
  "publisher": "Vast Flow, LLP",
  "licence": {
    "name": "CC BY 4.0",
    "url": "https://creativecommons.org/licenses/by/4.0/",
    "attribution": "App-Vault (https://appvau.lt)",
    "terms": "Free to reuse, republish and build on, including commercially, with attribution and a link to the source page."
  },
  "caveats": [
    "Third-party limits change without notice. `read_on` is the date each was checked; treat anything older than a few months as a hint rather than a fact.",
    "`formats[].encode` means a browser canvas can WRITE the format. Every listed format except HEIC can be read; only three can be written, which is what constrains every converter here.",
    "HEIC decodes in Safari and in no other browser. A tool that claims to open an iPhone photo in Chrome is either converting server-side or wrong.",
    "`mail_limits[].file_budget_bytes` is computed from the stated limit, not quoted from the provider. The arithmetic is published under `encoding_overhead` so it can be checked."
  ],
  "read_on": "2026-09-11",
  "formats": [
    {
      "id": "jpeg",
      "label": "JPEG",
      "media_type": "image/jpeg",
      "extensions": [
        ".jpg",
        ".jpeg"
      ],
      "browser_can_decode": true,
      "browser_canvas_can_encode": true,
      "lossy": true,
      "supports_transparency": false,
      "supports_animation": false,
      "metadata_containers": [
        "EXIF",
        "XMP",
        "IPTC",
        "ICC",
        "JUMBF (C2PA)"
      ],
      "note": "The universal photographic format. No transparency: an alpha channel is flattened onto a colour you choose."
    },
    {
      "id": "png",
      "label": "PNG",
      "media_type": "image/png",
      "extensions": [
        ".png"
      ],
      "browser_can_decode": true,
      "browser_canvas_can_encode": true,
      "lossy": false,
      "supports_transparency": true,
      "supports_animation": false,
      "metadata_containers": [
        "tEXt",
        "iTXt",
        "zTXt",
        "eXIf",
        "iCCP",
        "caBX (C2PA)"
      ],
      "note": "Lossless and transparent. Large for photographs, correct for screenshots, logos and line art."
    },
    {
      "id": "webp",
      "label": "WebP",
      "media_type": "image/webp",
      "extensions": [
        ".webp"
      ],
      "browser_can_decode": true,
      "browser_canvas_can_encode": true,
      "lossy": true,
      "supports_transparency": true,
      "supports_animation": true,
      "metadata_containers": [
        "EXIF",
        "XMP",
        "ICCP"
      ],
      "note": "Lossy or lossless, with transparency in both. Typically 25–35% smaller than JPEG at a matched quality."
    },
    {
      "id": "avif",
      "label": "AVIF",
      "media_type": "image/avif",
      "extensions": [
        ".avif"
      ],
      "browser_can_decode": true,
      "browser_canvas_can_encode": false,
      "lossy": true,
      "supports_transparency": true,
      "supports_animation": true,
      "metadata_containers": [
        "EXIF",
        "XMP"
      ],
      "note": "Decoded everywhere, encoded by no browser canvas. These tools read AVIF and write JPEG, PNG or WebP."
    },
    {
      "id": "heic",
      "label": "HEIC / HEIF",
      "media_type": "image/heic",
      "extensions": [
        ".heic",
        ".heif"
      ],
      "browser_can_decode": false,
      "browser_canvas_can_encode": false,
      "lossy": true,
      "supports_transparency": true,
      "supports_animation": false,
      "metadata_containers": [
        "EXIF",
        "XMP"
      ],
      "note": "What an iPhone shoots by default. Safari decodes it; Chrome and Firefox do not, so these tools cannot open it outside Safari. Share or export the photo as JPEG first."
    },
    {
      "id": "gif",
      "label": "GIF",
      "media_type": "image/gif",
      "extensions": [
        ".gif"
      ],
      "browser_can_decode": true,
      "browser_canvas_can_encode": false,
      "lossy": false,
      "supports_transparency": true,
      "supports_animation": true,
      "metadata_containers": [
        "Comment extension"
      ],
      "note": "Read as a single frame. These tools do not write GIF and do not preserve animation."
    }
  ],
  "resize_modes": [
    {
      "id": "longest",
      "label": "Longest edge",
      "inputs": [
        "px"
      ],
      "what_it_does": "Scales so the longer of the two sides lands on the number you give. The usual choice when a service states one limit.",
      "crops": false
    },
    {
      "id": "width",
      "label": "Width",
      "inputs": [
        "px"
      ],
      "what_it_does": "Sets the width; the height follows from the aspect ratio.",
      "crops": false
    },
    {
      "id": "height",
      "label": "Height",
      "inputs": [
        "px"
      ],
      "what_it_does": "Sets the height; the width follows.",
      "crops": false
    },
    {
      "id": "percent",
      "label": "Percentage",
      "inputs": [
        "%"
      ],
      "what_it_does": "Scales both sides by the same factor.",
      "crops": false
    },
    {
      "id": "fit",
      "label": "Fit inside a box",
      "inputs": [
        "px",
        "px"
      ],
      "what_it_does": "Scales down until the whole image fits inside the box. Nothing is cropped, so one side is usually smaller than the box.",
      "crops": false
    },
    {
      "id": "cover",
      "label": "Fill a box (crops)",
      "inputs": [
        "px",
        "px"
      ],
      "what_it_does": "Scales until the box is covered, then centre-crops the overflow. The output is exactly the box, and pixels are lost.",
      "crops": true
    }
  ],
  "quality_ladder": {
    "values": [
      0.95,
      0.92,
      0.88,
      0.84,
      0.8,
      0.75,
      0.7,
      0.65,
      0.6,
      0.55,
      0.5,
      0.45,
      0.4,
      0.35,
      0.3,
      0.25,
      0.2
    ],
    "what": "The exact sequence the size-ceiling search walks, highest first. Published so a result is reproducible: the receipt names the rung that met the ceiling, and the same file at the same rung gives the same bytes.",
    "on_failure": "If the lowest rung still exceeds the ceiling, the dimensions are reduced by 12% and the ladder is walked again, up to nine times. The receipt says which of the two got there."
  },
  "size_presets": [
    {
      "id": "50kb",
      "bytes": 50000,
      "label": "50 kB",
      "typical_use": "Forum avatars and older upload forms."
    },
    {
      "id": "100kb",
      "bytes": 100000,
      "label": "100 kB",
      "typical_use": "A photograph inside a web page without hurting Largest Contentful Paint."
    },
    {
      "id": "200kb",
      "bytes": 200000,
      "label": "200 kB",
      "typical_use": "A full-width hero image at a sensible resolution."
    },
    {
      "id": "500kb",
      "bytes": 500000,
      "label": "500 kB",
      "typical_use": "A detailed photograph where quality matters more than the last kilobyte."
    },
    {
      "id": "1mb",
      "bytes": 1000000,
      "label": "1 MB",
      "typical_use": "Government and visa upload forms usually sit at or below this."
    },
    {
      "id": "2mb",
      "bytes": 2000000,
      "label": "2 MB",
      "typical_use": "A generous ceiling; most upload forms accept it."
    }
  ],
  "brighten_curves": [
    {
      "id": "natural",
      "label": "Natural",
      "what": "A gamma curve over the whole image. Everything gets lighter by the same proportion, so contrast is preserved and nothing clips.",
      "sampled_at_strength_60": [
        {
          "input": 5,
          "output": 16
        },
        {
          "input": 20,
          "output": 38
        },
        {
          "input": 40,
          "output": 58
        },
        {
          "input": 60,
          "output": 74
        },
        {
          "input": 80,
          "output": 87
        },
        {
          "input": 95,
          "output": 97
        }
      ]
    },
    {
      "id": "shadows",
      "label": "Shadow lift",
      "what": "Lifts the dark end and tapers to nothing by the midtones, so a bright sky stays bright. This is the right choice for most underexposed photographs.",
      "sampled_at_strength_60": [
        {
          "input": 5,
          "output": 34
        },
        {
          "input": 20,
          "output": 40
        },
        {
          "input": 40,
          "output": 51
        },
        {
          "input": 60,
          "output": 64
        },
        {
          "input": 80,
          "output": 81
        },
        {
          "input": 95,
          "output": 95
        }
      ]
    },
    {
      "id": "backlit",
      "label": "Backlit subject",
      "what": "A strong shadow lift with a mild highlight roll-off, for a subject photographed against a window or the sun. Expect visible noise in the shadows: brightening cannot invent detail the sensor did not record.",
      "sampled_at_strength_60": [
        {
          "input": 5,
          "output": 51
        },
        {
          "input": 20,
          "output": 55
        },
        {
          "input": 40,
          "output": 63
        },
        {
          "input": 60,
          "output": 72
        },
        {
          "input": 80,
          "output": 84
        },
        {
          "input": 95,
          "output": 91
        }
      ]
    }
  ],
  "redaction_modes": [
    {
      "id": "block",
      "label": "Solid block",
      "what": "Paints the area a flat colour. Nothing of the original survives, and nothing about the result suggests what was there.",
      "reversible": false,
      "note": "The only mode that leaves no residue at all."
    },
    {
      "id": "pixelate",
      "label": "Pixelate",
      "what": "Averages the area into large squares. Irreversible once re-encoded, but the block pattern still shows the shape of what was covered.",
      "reversible": false,
      "note": "The region is averaged into cells before any smoothing, so there is no original signal left to recover — but the shape and colour of what was covered still read."
    },
    {
      "id": "blur",
      "label": "Blur",
      "what": "A heavy box blur. The most natural-looking option and the weakest: a blur applied at a small radius over text has been recovered before, so this tool forces a radius proportional to the region.",
      "reversible": false,
      "note": "The region is averaged into cells before any smoothing, so there is no original signal left to recover — but the shape and colour of what was covered still read."
    }
  ],
  "hdr_presets": [
    {
      "id": "gentle",
      "label": "Gentle",
      "max_stops": 1,
      "what": "One stop of extra headroom, applied only to the brightest quarter of the image. The safest setting and the one that still looks like a photograph."
    },
    {
      "id": "standard",
      "label": "Standard",
      "max_stops": 2,
      "what": "Two stops. Specular highlights — a window, a reflection, the sun on water — come forward; the rest of the picture is untouched."
    },
    {
      "id": "strong",
      "label": "Strong",
      "max_stops": 3,
      "what": "Three stops, which is roughly what a phone camera records natively. On a bright image this becomes obvious rather than natural."
    }
  ],
  "encoding_overhead": {
    "base64_ratio": 1.3333333333333333,
    "mime_line_break_overhead": 0.02631578947368421,
    "worked_example": {
      "file_bytes": 5000000,
      "encoded_bytes": 6842107,
      "explanation": "A 5 MB photograph becomes about 6.85 MB inside a MIME message: base64 turns every three bytes into four, and a CRLF is inserted every 76 characters."
    }
  },
  "mail_limits": [
    {
      "service": "Gmail",
      "stated_limit_bytes": 25000000,
      "scope": "total message size, sending",
      "file_budget_bytes": 18265575,
      "over_the_limit": "Files over the limit are replaced with a Google Drive link.",
      "read_on": "2026-09-11",
      "source": "https://support.google.com/mail/answer/6584"
    },
    {
      "service": "Outlook.com",
      "stated_limit_bytes": 20000000,
      "scope": "attachments per message",
      "file_budget_bytes": 14611728,
      "over_the_limit": "Offers OneDrive sharing instead.",
      "read_on": "2026-09-11",
      "source": "https://support.microsoft.com/office/attach-files-in-outlook-com-b9e02b9e-2b4a-4d2e-9b09-52d40e9e1e2f"
    },
    {
      "service": "iCloud Mail",
      "stated_limit_bytes": 20000000,
      "scope": "total message size",
      "file_budget_bytes": 14611728,
      "over_the_limit": "Mail Drop carries up to 5 GB for 30 days.",
      "read_on": "2026-09-11",
      "source": "https://support.apple.com/en-us/102412"
    },
    {
      "service": "Yahoo Mail",
      "stated_limit_bytes": 25000000,
      "scope": "total message size",
      "file_budget_bytes": 18265575,
      "over_the_limit": "None; the send fails.",
      "read_on": "2026-09-11",
      "source": "https://help.yahoo.com/kb/SLN28346.html"
    },
    {
      "service": "Proton Mail",
      "stated_limit_bytes": 25000000,
      "scope": "total message size",
      "file_budget_bytes": 18265575,
      "over_the_limit": "None on the free plan.",
      "read_on": "2026-09-11",
      "source": "https://proton.me/support/attachment-size-limit"
    },
    {
      "service": "Exchange Online (work account)",
      "stated_limit_bytes": 35000000,
      "scope": "default message size, tenant-configurable",
      "file_budget_bytes": 25573269,
      "over_the_limit": "An administrator can lower or raise it, so check locally.",
      "read_on": "2026-09-11",
      "source": "https://learn.microsoft.com/en-us/office365/servicedescriptions/exchange-online-service-description/exchange-online-limits"
    }
  ],
  "platform_images": [
    {
      "platform": "Instagram",
      "slot": "Profile picture",
      "upload_px": [
        1080,
        1080
      ],
      "displayed_px": [
        320,
        320
      ],
      "mask": "circle",
      "note": "Uploads are re-encoded; the crop is square before the circle mask.",
      "read_on": "2026-09-11"
    },
    {
      "platform": "LinkedIn",
      "slot": "Profile photo",
      "upload_px": [
        400,
        400
      ],
      "displayed_px": [
        400,
        400
      ],
      "mask": "circle",
      "note": "Minimum 400×400; the maximum accepted file is 8 MB.",
      "read_on": "2026-09-11"
    },
    {
      "platform": "X",
      "slot": "Profile picture",
      "upload_px": [
        400,
        400
      ],
      "displayed_px": [
        400,
        400
      ],
      "mask": "circle",
      "note": "2 MB ceiling for a still image.",
      "read_on": "2026-09-11"
    },
    {
      "platform": "Facebook",
      "slot": "Profile picture",
      "upload_px": [
        320,
        320
      ],
      "displayed_px": [
        176,
        176
      ],
      "mask": "circle",
      "note": "Displayed at 176 px on desktop and 196 px on the app.",
      "read_on": "2026-09-11"
    },
    {
      "platform": "WhatsApp",
      "slot": "Profile photo",
      "upload_px": [
        640,
        640
      ],
      "displayed_px": [
        192,
        192
      ],
      "mask": "circle",
      "note": "Heavily re-compressed on upload; a large file buys nothing.",
      "read_on": "2026-09-11"
    },
    {
      "platform": "YouTube",
      "slot": "Channel picture",
      "upload_px": [
        800,
        800
      ],
      "displayed_px": [
        98,
        98
      ],
      "mask": "circle",
      "note": "4 MB ceiling. PNG or GIF without animation.",
      "read_on": "2026-09-11"
    },
    {
      "platform": "Discord",
      "slot": "Avatar",
      "upload_px": [
        512,
        512
      ],
      "displayed_px": [
        128,
        128
      ],
      "mask": "circle",
      "note": "8 MB ceiling; animated avatars need Nitro.",
      "read_on": "2026-09-11"
    },
    {
      "platform": "Slack",
      "slot": "Profile photo",
      "upload_px": [
        512,
        512
      ],
      "displayed_px": [
        192,
        192
      ],
      "mask": "rounded square",
      "note": "Minimum 512×512.",
      "read_on": "2026-09-11"
    },
    {
      "platform": "GitHub",
      "slot": "Avatar",
      "upload_px": [
        500,
        500
      ],
      "displayed_px": [
        260,
        260
      ],
      "mask": "rounded square",
      "note": "1 MB ceiling.",
      "read_on": "2026-09-11"
    },
    {
      "platform": "Telegram",
      "slot": "Profile photo",
      "upload_px": [
        512,
        512
      ],
      "displayed_px": [
        160,
        160
      ],
      "mask": "circle",
      "note": "Re-encoded server-side to JPEG.",
      "read_on": "2026-09-11"
    }
  ],
  "one_size_that_covers_everything": {
    "width": 512,
    "height": 512,
    "why": "Every avatar slot in `platform_images` displays at 400 px or less, and every platform re-encodes what it receives. A 512 x 512 square is larger than any of them render and small enough that no platform rejects it."
  }
}
