static computeWaste(image, viewportDimensions, networkRecords) {
    const networkRecord = networkRecords.find(record => record.url === image.src);
    // If we don't know how big it was, we can't really report savings, treat it as passed.
    if (!networkRecord) return null;
    // If the image had its loading behavior explicitly controlled already, treat it as passed.
    if (image.loading === 'lazy' || image.loading === 'eager') return null;

    const url = UrlUtils.elideDataURI(image.src);
    const totalPixels = image.displayedWidth * image.displayedHeight;
    const visiblePixels = this.computeVisiblePixels(image.clientRect, viewportDimensions);
    // Treat images with 0 area as if they're offscreen. See https://github.com/GoogleChrome/lighthouse/issues/1914
    const wastedRatio = totalPixels === 0 ? 1 : 1 - visiblePixels / totalPixels;
    const totalBytes = NetworkRequest.getResourceSizeOnNetwork(networkRecord);
    const wastedBytes = Math.round(totalBytes * wastedRatio);

    if (!Number.isFinite(wastedRatio)) {
      return new Error(`Invalid image sizing information ${url}`);
    }

    return {
      node: ByteEfficiencyAudit.makeNodeItem(image.node),
      url,
      requestStartTime: networkRecord.networkRequestTime,
      totalBytes,
      wastedBytes,
      wastedPercent: 100 * wastedRatio,
    };
  }
@param {LH.Artifacts.ImageElement} image
@param {{innerWidth: number, innerHeight: number}} viewportDimensions
@param {Array<LH.Artifacts.NetworkRequest>} networkRecords
@return {null|Error|WasteResult}