imageEncodingProblem function
What rules refuse about image's encoding, as a sentence to follow the
file's name, or null when nothing does.
Returned rather than thrown because the two callers report differently — the App Store loader throws on the first problem, the Play checker collects them — and a check that picked one could only be used by that one.
Implementation
String? imageEncodingProblem(ImageInfo image, StoreImageRules rules) {
if (image.hasAlpha && !rules.allowsAlpha) {
return 'has an alpha channel; ${rules.store} refuses transparency — '
'${rules.alphaRule}.\n'
' Remove it, and change nothing else about the image:\n'
' cux_ship screenshots flatten <path>\n'
' `sips` cannot do this while staying PNG — it writes RGBA whatever '
'flags it\n'
' is given, so a round trip through it changes nothing.';
}
// **`> 8` rather than `!= 8`, and the difference is whether this is checking
// a rule or inventing one.** Play asks for eight bits per channel by name —
// "24-bit PNG" — and Apple, publishing no depth at all, has been observed
// refusing sixteen at ingestion. Fewer than eight is
// a greyscale or palettised PNG, whose palette entries are eight bits each —
// so "24-bit" is arguably what it already is, no store has been seen to
// refuse one, and failing it would be this package enforcing a rule with no
// failure under it. That is the mistake the aspect-ratio note in
// play_metadata.dart exists to refuse to make.
//
// **PNG only, and for the same reason.** Every justification under this
// check is PNG's: Play states a depth for PNG and none for JPEG — "24-bit"
// in "JPEG or 24-bit PNG (no alpha)" modifies the PNG, not the JPEG beside
// it — the set Apple was observed refusing was a PNG, and `screenshots
// flatten` decodes PNG and nothing else. Applied to a JPEG this quoted Play
// for a rule Play does not state, offered a PNG refusal as evidence about a
// JPEG, and named a remedy that throws (the CLI walks `.png`, so it would
// skip the file, exit 0, and leave verify still refusing it) — a loop, and
// the same shape as the greyscale-with-alpha gate found in review.
//
// A >8-bit JPEG is legal and essentially unproducible: baseline SOF0 is
// 8-bit by definition, 12 needs an extended sequential or progressive frame,
// and reading one needs the 12-bit decoder entry points, which Blink and
// everything else on libjpeg's 8-bit API do not call. So it is a rule with
// no observed failure and no working remedy. Measured and argued in
// docs/design/store-image-rules.md.
if (image.format == ImageFormat.png && image.bitDepth > 8) {
return 'is ${image.bitDepth} bits per channel; ${rules.store} takes 8 — '
'${rules.depthRule}.\n'
' Reduce it, and change nothing else about the image:\n'
' cux_ship screenshots flatten <path>\n'
' It rescales rather than truncating, so the picture survives. A '
'macOS\n'
' `--no-chrome` capture is the usual source of a 16-bit screenshot.';
}
return null;
}