0

I'm trying to validate images before being sent to the DALL E API. The API rejects certain image properties that I need to validate:

  1. file type
  2. image dimensions
  3. file size
  4. whether the image has an alpha channel

What is the best way to do this?

JimmyTheCode
  • 3,783
  • 7
  • 29
  • 71

1 Answers1

0

This is a solution that works for me, although I would guess there are more efficient ways to accomplish it:

Validate items 1-3:

// Takes an imageBase64 url (we create locally, within javascript, from a file) and checks the dimensions once rendered.
function checkImageDims(imageBase64: string) {
  const img = new Image();
  img.src = imageBase64;
  const promise = new Promise<string | null>((resolve, reject) => {
    img.onload = () => {
      const { width, height } = img;
      if (height !== width) {
        resolve(
          `Image needs to be square. Current dimensions are ${width}x${height}`
        );
      } else {
        resolve(null);
      }
      img.onerror = reject;
    };
  });
  return promise;
}

// I am using AWS Amplify with S3. This gets the URL to the image:
  const getS3Url = await Storage.get(`myFolder/${s3ObjectName}`);
// Once we have the URL
  const fetched = await fetch(getS3Url);
  const blobbed = await fetched.blob();
  const imageBase64 = URL.createObjectURL(blobbed);
  const dimensionsError = await checkImageDims(imageBase64);
  if (dimensionsError) return dimensionsError;

  console.log({
    size: blobbed.size,
    type: blobbed.type,
  });

Validate item 4 (alpha)

// Checks image for alpha channel (transparency) https://stackoverflow.com/a/41302302/11664580
function checkForAlphaChannel(buffer: ArrayBuffer) {
  const view = new DataView(buffer);
  // is a PNG?
  if (view.getUint32(0) === 0x89504e47 && view.getUint32(4) === 0x0d0a1a0a) {
    // We know format field exists in the IHDR chunk. The chunk exists at
    // offset 8 +8 bytes (size, name) +8 (depth) & +9 (type)
    const type = view.getUint8(8 + 8 + 9);
    return type === 4 || type === 6; // grayscale + alpha or RGB + alpha
  }
  return false;
}

  const arrayBuffer = await blobbed.arrayBuffer();
  const checkAlpha = checkForAlphaChannel(arrayBuffer);
  console.log({checkAlpha})

Credit https://stackoverflow.com/a/41302302/11664580 for the Alpha validation.

JimmyTheCode
  • 3,783
  • 7
  • 29
  • 71