{
  "schemaVersion": 1,
  "slug": "image-file-size-calculator",
  "category": "photography",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "271bbd06c15808ad2ad393db95b3174a41f4170e4fe85b3a54579d87d9908010",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/image-file-size-calculator.json",
    "src/engine.js"
  ],
  "runtimeSource": "/sources/engine.txt",
  "runtimeHash": "5c888d8898afbdee36267bb9977829e1e2ac568f6677c8ee87469c139864645c",
  "scope": "The compute function records implemented equations, constants, lookup tables and custom rules. Inputs record defaults and allowed values; outputs record precision and units. Defaults are examples, not recommendations. General background references are not evidence for this specific algorithm.",
  "publishedFormula": {
    "formula": "MB = W × H × d × c ÷ 8 ÷ 1048576 × q ; N = ⌊S × 1024 ÷ MB⌋",
    "vars": [
      [
        "W",
        "image width (px)"
      ],
      [
        "H",
        "image height (px)"
      ],
      [
        "d",
        "bit depth"
      ],
      [
        "c",
        "colour channels"
      ],
      [
        "q",
        "compression factor (JPEG 0.09, PNG 0.55, raw 1)"
      ],
      [
        "S",
        "memory card size (GB)"
      ]
    ],
    "note": "Uncompressed bytes = width × height × bit depth × channels ÷ 8; estimated size = uncompressed size × user-entered percentage. Card capacity uses decimal GB."
  },
  "externalEvidence": null,
  "contract": {
    "compute": "const mp=width*height/1000000; const bpp=bitDepth*channels; const bytes=width*height*bpp/8; const uncompressed=bytes/1048576; const est=uncompressed*compressionPercent/100; const cardMB=cardSize*1000; return {megapixels:mp,uncompressedMB:uncompressed,estimatedMB:est,photosOnCard:est>0?Math.floor(cardMB/est):0,aspectRatio:height>0?width/height:0};",
    "inputs": [
      {
        "name": "width",
        "type": "number",
        "default": 6000,
        "min": 1,
        "max": 200000,
        "step": 1
      },
      {
        "name": "height",
        "type": "number",
        "default": 4000,
        "min": 1,
        "max": 200000,
        "step": 1
      },
      {
        "name": "bitDepth",
        "type": "select",
        "default": 8,
        "options": [
          {
            "value": 8
          },
          {
            "value": 10
          },
          {
            "value": 12
          },
          {
            "value": 14
          },
          {
            "value": 16
          }
        ]
      },
      {
        "name": "channels",
        "type": "select",
        "default": 3,
        "options": [
          {
            "value": 1
          },
          {
            "value": 3
          },
          {
            "value": 4
          }
        ]
      },
      {
        "name": "cardSize",
        "type": "number",
        "default": 64,
        "min": 0.1,
        "max": 4096,
        "step": 1,
        "slider": true
      },
      {
        "name": "compressionPercent",
        "type": "number",
        "default": 10,
        "min": 0.1,
        "max": 100,
        "step": 0.5,
        "slider": true
      }
    ],
    "outputs": [
      {
        "name": "megapixels",
        "precision": 2,
        "unit": "MP"
      },
      {
        "name": "uncompressedMB",
        "precision": 2,
        "unit": "MB"
      },
      {
        "name": "estimatedMB",
        "precision": 2,
        "unit": "MB"
      },
      {
        "name": "photosOnCard",
        "precision": 0,
        "unit": ""
      },
      {
        "name": "aspectRatio",
        "precision": 2,
        "unit": ""
      }
    ],
    "interpret": null
  }
}
