Let's talk
engineering

Vehicle inspection app photos arriving cropped: the cause

Handover photos from a rental inspection app arrived as a corner of the car. Large phone photos were being cut, not shrunk. How to check yours.

· · updated

Hands photographing a car's front wing on a phone at handover

If photos from your vehicle inspection app reach the office cropped, showing a corner of the car instead of the whole panel, the usual cause is the app cutting the picture while it shrinks it for upload, and it hits the best cameras hardest. The first check is to compare one photo on the driver’s phone with the same photo in the office. Whatever was cut cannot be recovered afterwards.

Here is how that looked at one car rental business, and what fixing it took.

You run a self-drive car rental business in Goa (the system behind GOI Car & Taxi). At every pickup and every return your driver photographs the car, panel by panel, because when a customer disputes a damage charge those photographs are the whole argument. One morning the office opens a booking and each picture is a corner of a car: a bonnet, the edge of a wing, then the edge of the frame. The rest never arrived.

It was not one booking. Every handover photo since the release before last had come in the same way, and how much was missing depended on the phone. Between half and nearly nine-tenths of each frame was gone, and the better the camera, the worse the loss: a phone with a 108-megapixel sensor was sending about one-sixtieth of what the driver had seen on his screen. There was nothing to go back for, either. The full picture never left the phone, so the evidence for every dispute in that window is gone for good.

What was actually going on

Two days before this report we had looked at a “cropped thumbnail” complaint on the same app and concluded the stored photos were fine and only the small preview tile in the app was cut off. That answer was wrong, and it is worth saying so, because the way it was wrong is the whole story. The stored files looked like whole photographs. They had the right proportions and a plausible size. Nothing about them said “a quarter of a car” until somebody laid them over the originals and measured: the uploaded file matched the top-left half of the original in each direction, corner to corner, with a correlation of 0.9998. They were not squashed. They were cut.

The cause, in plain words: before sending a photo, the app shrinks it. To do that it asks the phone how big the photo is, and on this kind of phone the answer is the size of a smaller working copy the phone keeps for large images, not the size of the photograph. For a 4,000 by 3,000 frame the phone said 2,000 by 1,500. The app then told the shrinking routine to keep a box that big from the top-left corner, and that routine, it turned out, always cuts a box first and scales second. So it cut half the photo in each direction and enlarged it back up.

Small photos were never affected, because the phone does not keep a reduced copy of a small image. That is why the fault looked intermittent, and why an earlier test with small images passed. Every real camera frame is large. A previous attempt at the same complaint had adjusted the arithmetic for the photo’s proportions, which was never the cause; with the right dimensions that path loses a tenth of a percent.

What we changed

The first fix read the true pixel size from the file itself and planned a box that provably covered the whole frame. It worked, on a real driver’s phone, across 20 test images and then five more at 64, 108 and 200 megapixels. Then we threw it away. It depended on a hand-written copy of the library’s private behaviour, which a future update could silently drift from with no test able to notice, and when its own file-reading failed it fell back to asking the phone, which was the broken thing. A fix that is correct today and a trap tomorrow is not a fix.

The replacement uses a different library chosen after reading its source rather than its description. It takes the size from the decoded picture itself, so no number the app supplies can disagree with reality, and it only scales; there is no cutting step anywhere in its path. One test asserts the scaling mode, because switching it is a one-word edit that would crop again. Verified on the driver’s phone with 38 images from 200 by 150 pixels up to 200 megapixels, every proportion and orientation the camera produces, and the twelve real photographs from the driver’s own session, each one whole after the round trip to storage. Shipped as app version 1.0.8.

What it did not fix

The photos already uploaded stay as they are. The full frame was discarded on the phone before anything was sent, so no server-side work can bring them back.

The app cannot update itself, so drivers kept sending cut photos until the new version was installed. We only learned the fault was live at all because a handover note said the previous release had not been uploaded to the store, and the owner corrected it: it had been, which meant every driver was on it.

Two smaller things were found and left. A very small 200 by 150 upload arrives whole, but the burned-in watermark covers its top third. And the home-screen badge saying bookings still need photos only clears when the driver opens the pending screen, so a fully uploaded booking keeps nagging.

How to check your own inspection photos

  1. Take a photo on the phone your drivers actually use, ideally a recent one with a high-resolution camera, and compare it with what arrives in the office.
  2. Test both large and small photos. Small ones passed here, which is why the fault looked intermittent.
  3. Ask your supplier whether the upload step only scales the picture and never cuts it, and whether that was tested on a real phone.
  4. Check which app version your drivers are on. The app cannot update itself, so old versions keep sending cut photos until the new one is installed.
  5. Ask when the full-size original is discarded on the phone, because after that nothing can be recovered.

The mechanism, briefly

The native resize call was a crop-and-resize with no resize-only mode, fed a crop rectangle built from a decoder’s power-of-two downsampled size rather than the file’s pixel size. It was replaced with a contain-mode scale that reads the decoded bitmap’s own dimensions, with a test pinning the mode and a byte-target loop that re-derives from the original each pass instead of resampling its own output.

Where this ends up

A damage dispute is decided by what the photograph shows, which is why the handover capture in Sazinga Rentals is verified frame by frame against the original on a real phone, not judged by whether the upload looks like a photo.

This came out of building Sazinga Rentals

Bookings, availability and the fleet standing behind them. The problem above is one we met while building it, and what we did about it is in the product.

If you run something like this, there is one thing you can do without a call: send one week's booking sheet.