mish-tv / fix-image-orientation

MIT License
1 stars 1 forks source link

png transformation does not apply #1

Open prmichaelsen opened 10 months ago

prmichaelsen commented 10 months ago

I was testing the package and I noticed for png it is stripping the rotation data but not actually applying it. Any thoughts?

prmichaelsen commented 10 months ago

Note that it works once I changed const pngSignature = BigInt("0x89504e470d0a1a0a"); to const pngSignature = BigInt("0x30f58d889a0d12"); in src/get-and-remove-orientation/get-and-remove-png-orientation.ts

0x30f58d889a0d12 is hexadecimal for 13780787113102610 which is the official PNG file signature per https://www.w3.org/TR/PNG-Structure.html

It may be there was a mistake in the original code.

prmichaelsen commented 10 months ago

I ended up having to use both signatures to get the existing tests for getAndRemovePngOrientation to pass:

  if (signature !== pngSignature && signature !== pngSignature2) {
    return undefined;
  }
prmichaelsen commented 10 months ago

The orientation is being calculated correctly and the correct transform function is being called but the resulting image is still not rotated correctly. This occurs for png only... very interesting.

prmichaelsen commented 10 months ago

I was able to get .png working by handling it as a special case:


// The PNG must be rotated by first drawing
// the image to a canvas, then retrieving the
// image data from that canvas, drawing to a new canvas
// and then applying the transformation.
const createTransformedDataURLPng = async (
  blob: Blob, orientation: number, type: string
): Promise<string> => {

  const objectURL = URL.createObjectURL(blob);
  const image = await createImage(objectURL);

  const startCanvas = document.createElement("canvas");
  const startContext = startCanvas.getContext("2d");
  if (startContext == undefined) {
    throw new Error("undefined startContext");
  }
  startCanvas.width = image.width;
  startCanvas.height = image.height;
  startContext.drawImage(image, 0, 0);
  const imageData = startContext.getImageData(0, 0, image.width, image.height);

  const canvas = document.createElement("canvas");
  const context = canvas.getContext("2d");
  if (context == undefined) {
    throw new Error("undefined context");
  }

  canvas.width = image.width;
  canvas.height = image.height;
  context.putImageData(imageData, 0, 0);

  const width = reversedAspectRatioOrientations.has(orientation) ? image.height : image.width;
  const height = reversedAspectRatioOrientations.has(orientation) ? image.width : image.height;

  transformsByOrientation[orientation](width, height, context);

  const url = canvas.toDataURL(type);

  URL.revokeObjectURL(objectURL);

  return url;
};