DrKLO/Telegram · error
%s: transformation is not perfect
Error message
%s: transformation is not perfect
What it means
When the -perfect flag is set, jpegtran calls jtransform_request_workspace at jpegtran.c:578. If this returns FALSE, the requested transformation (rotate, flip, crop, transpose) cannot be applied losslessly because the image dimensions are not compatible with the transform's block-alignment requirements. The -perfect flag makes this a hard failure rather than a silent trim.
Source
Thrown at TMessagesProj/jni/mozjpeg/jpegtran.c:579
jpeg_mem_src(&srcinfo, inbuffer, insize);
} else
#endif
jpeg_stdio_src(&srcinfo, fp);
/* Enable saving of extra markers that we want to copy */
jcopy_markers_setup(&srcinfo, copyoption);
/* Read file header */
(void)jpeg_read_header(&srcinfo, TRUE);
/* Any space needed by a transform option must be requested before
* jpeg_read_coefficients so that memory allocation will be done right.
*/
#if TRANSFORMS_SUPPORTED
/* Fail right away if -perfect is given and transformation is not perfect.
*/
if (!jtransform_request_workspace(&srcinfo, &transformoption)) {
fprintf(stderr, "%s: transformation is not perfect\n", progname);
exit(EXIT_FAILURE);
}
#endif
/* Read source file as DCT coefficients */
src_coef_arrays = jpeg_read_coefficients(&srcinfo);
/* Initialize destination compression parameters from source values */
jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
/* Adjust destination parameters if required by transform options;
* also find out which set of coefficient arrays will hold the output.
*/
#if TRANSFORMS_SUPPORTED
dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo,
src_coef_arrays,
&transformoption);
#elseView on GitHub (pinned to 45ab8f4308)
Solutions
- Remove the -perfect flag to allow jpegtran to trim edges automatically (lossy trim)
- Adjust the transform to match block boundaries: crop to multiples of 16 (or 8 for non-progressive)
- Pad or pre-resize the image so dimensions are multiples of the MCU size before transforming
Example fix
// before jpegtran -perfect -rotate 90 input.jpg -outfile out.jpg // after // remove -perfect to allow trimming jpegtran -rotate 90 input.jpg -outfile out.jpg // or align crop to 16-pixel boundary jpegtran -perfect -crop 1920x1080+0+0 input.jpg -outfile out.jpg
Defensive patterns
Strategy: validation
Validate before calling
// Read JPEG dimensions and check MCU alignment before invoking jpegtran -perfect
#include "jpeglib.h"
int transform_is_safe(const char *path, int transform_type) {
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
FILE *f = fopen(path, "rb");
if (!f) { jpeg_destroy_decompress(&cinfo); return -1; }
jpeg_stdio_src(&cinfo, f);
jpeg_read_header(&cinfo, TRUE);
int w = cinfo.image_width, h = cinfo.image_height;
int block = cinfo.progressive_mode ? 16 : 8;
fclose(f); jpeg_destroy_decompress(&cinfo);
// for rotate 90: width must be multiple of block
// for flip: the flipped dimension must be multiple of block
// for crop: all offsets/dims must be multiples of block
if (transform_type == ROTATE_90 || transform_type == ROTATE_270)
return (w % block == 0) ? 0 : -1;
if (transform_type == FLIP_H)
return (w % block == 0) ? 0 : -1;
if (transform_type == FLIP_V)
return (h % block == 0) ? 0 : -1;
return 0;
} Prevention
- Check image dimensions are multiples of the MCU block size (8 or 16) before using -perfect
- Remove -perfect if lossless trimming of edge blocks is acceptable
- Align crop regions to 16-pixel boundaries when using -perfect
When it happens
Trigger: Rotating a non-square JPEG with -rotate 90 -perfect when width is not a multiple of the MCU height. Cropping with -crop when the target dimensions don't align to JPEG block boundaries (multiples of 8 or 16). Flipping an image whose dimensions aren't multiples of the block size.
Common situations: User adds -perfect to guarantee lossless output but the source image has odd dimensions (e.g. 1921x1080). Automated pipeline that always includes -perfect but processes images with varying dimensions. A crop region that doesn't start/end on block boundaries.
Related errors
- %s: only one input file
- %s: can't open %s for reading
- %s: can't open %s
- %s: can't determine size of %s
- %s: can't allocate memory for ICC profile
AI-assisted analysis of DrKLO/Telegram@45ab8f4308 (2026-08-14).
Data as JSON: /api/errors/2ebd615e479a4965.
Report an issue: GitHub.