Photo sizing using the Capacitor camera plugin

I’m using the Capacitor camera plugin to allow the user take a photo with the phone’s camera. I need to reduce the resolution of the photo so the images are a manageable size, since they need to be uploaded to our server. The only problem I’m having is getting the pixel resolution I want in the resulting images.

The desired resolution is simple: If the photo is landscape, then I want the width to be 1024 pixels (and scale the height proportionally). If the photo is portrait, then I want the height to be 1024 (and scale the width proportionally).

This seems to be impossible to achieve with the current camera plugin, unless I am missing something.

There are fields named “width” and a “height” in the “ImageOptions” interface that you can use to control the photo’s resolution. The problem is that I don’t know the width or height because it depends on the orientation of the camera (portrait vs landscape). I know I want the larger edge to be 1024 pixels.

However, there is also a field named “correctOrientation” in the “ImageOptions” interface. When this is set to true (the default), it auto-rotates the image so that a portrait-orientation photo is not sideways. I can set this field to false, to prevent auto-rotation. Now I can set the “width” field to 1024, and the image is scaled according to my requirements. But the problem now is that all portrait-orientation photos are sideways.

Is there a way to set up the ImageOptions field values so that I get both of the following:

  • The longer edge is 1024 pixels, and the shorter edge is scaled proportionally
    AND
  • The photo is properly rotated for portrait/landscape orientation

Thank you for any guidance you can provide.

In case anyone else finds this in the future, I eventually had to assume that creating a fixed resolution photo with auto-orientation enabled is simply not possible with the current camera plugin. This seems like a shame because I would think that this is the most common use-case.

In any event, the solution is to use the EXIF data that the camera plugin returns to detect the orientation of the camera when the photo was taken, and then rotate the resulting image yourself with some JavaScript code. Assuming your JavaScript is running in a web browser with access to HTML elements, then you can do this with the following code (excerpted from Rotate image preview to compensate for EXIF orientation (Javascript / Typescript) · GitHub):

rotateImageInElement(imageElement: HTMLImageElement, orientation: number): string {
    const canvas: HTMLCanvasElement = document.createElement("canvas")
	const context: CanvasRenderingContext2D|null = canvas.getContext("2d")
	if (context==null) {
		console.log("Failed to create 2D context on canvas element")
		return ""
	}
	const width = imageElement.width
	const height = imageElement.height
	if (orientation >= 5 && orientation <= 8) {
		canvas.width = height
		canvas.height = innerWidth
	} else {
		canvas.width = width
		canvas.height = height
	}
	console.log("canvas dimensions "+canvas.width+"x"+canvas.height)
	switch (orientation) {
	case 2:
		context.transform(-1, 0, 0, 1, width, 0);
		break;
	case 3:
		context.transform(-1, 0, 0, -1, width, height);
		break;
	case 4:
		context.transform(1, 0, 0, -1, 0, height);
		break;
	case 5:
		context.transform(0, 1, 1, 0, 0, 0);
		break;
	case 6:
		context.transform(0, 1, -1, 0, height, 0);
		break;
	case 7:
		context.transform(0, -1, -1, 0, height, width);
		break;
	case 8:
		context.transform(0, -1, 1, 0, 0, width);
		break;
	default:
		break;
	}
	context.drawImage(imageElement, 0, 0, width, height)
	let newImage: string = canvas.toDataURL("image/jpeg", 0.8)
	const commaIndex = newImage.indexOf(",")
	if (commaIndex<0) {
		console.log("Failed to get base64 image data of rotated image")
		return ""
	}
	newImage = newImage.substring(commaIndex+1)
	return newImage
}

I’ve create this ticket: [Feature]: native camera resolution handeling (picture max size) to avoid app crashes · Issue #7401 · ionic-team/capacitor · GitHub

This feature should be handled natively to compensate very big modern cameras, as dedicated RAM of native web views isn’t enough to handle big pictures manipulation