Classic Monks - Image Converter: large uploads lose attachment metadata; size copies are duplicated

Environment

  • Classic Monks 2.4.0
  • WordPress 7.1.2, PHP 8.5, memory_limit 512M
  • Image Converter settings: Auto-Convert on Upload = ON, format WebP, Quality 92,
    resize_mode = width, Preserve Original Files = OFF, Preserve Metadata = ON,
    no “cm-full” size configured
  • Upload made through the standard Media Library uploader (wp-admin/media-new.php)

Issue 1 - Large images are silently downscaled to 2560 px by a hard-coded limit

Steps:

  1. Upload a PNG of 3074 x 2131 px (6.7 MB, with transparency).

Expected: the original keeps its dimensions (no “cm-full” size is set, and WordPress’s own
big_image_size_threshold is disabled by the plugin, which returns 0).

Actual: the resulting WebP attachment is 2560 x 1775.

Cause (from reading class-image-converter-core.php): validate_image_size() /
should_defer_processing() estimate the memory needed. When the estimate exceeds 60% of the
available memory, pre_scale_large_image() overwrites the original with a copy resized to
$max_dimension = 2560 and the conversion is moved to background processing.
The 2560 value is hard-coded. No setting or filter controls it, and nothing in the UI tells the
user that the image was resized.

Request: make the limit configurable (a setting or a filter), or at least show a notice/log
entry in the Media Library that the original was downscaled.

Issue 2 - After the deferred (large-image) path the attachment has no metadata

Same upload as Issue 1. Afterwards:

  • wp_get_attachment_metadata( $id ) returns false (no width, no height, no sizes);
  • _cm_optimization_data is present: method “resize_convert”, original_size 4,668,888,
    optimized_size 967,682;
  • all intermediate files exist on disk (150, 300, 768, 1024, 1536, 2048, each in two naming
    variants, see Issue 3).

Consequences:

  • no intermediate size can be selected in page builders/editors, so the full-size file is
    always served;
  • when the attachment is deleted, WordPress does not know about the copies, so all of them
    stay on the server as orphans.

Smaller uploads on the same site (under the memory threshold) get correct metadata, so the
loss seems specific to the deferred / pre-scaled path. We did not locate the exact point
where the metadata is lost.

Issue 3 - Size copies are often written twice under two names

Some converted images get each intermediate size twice: once as “-” and once as
“-x”, with the same dimensions. Example, a 1409 x 977 image:

karta-1-1024.webp 1024 x 710 341,150 bytes md5 7eaae6b3ab34e4065678df374031a24d
karta-1-1024x710.webp 1024 x 710 341,150 bytes md5 7eaae6b3ab34e4065678df374031a24d

The same pairs exist for 150, 300 and 768.

Scope, checked on the 60 most recent WebP attachments: 9 of them have such pairs, 28 pairs in
total. In 10 pairs the two files are byte-identical. In the other 18 the dimensions are the same
but the files differ, i.e. the same size was encoded twice. We did not find what decides whether
an image gets the pairs.

Only the “-WxH” names are recorded in _wp_attachment_metadata. The “-” copies are not
referenced anywhere, so they waste disk space and are left behind when the attachment is
deleted.

Issue 4 - Sizes larger than the original are created as full-size copies

For the same 1409 x 977 image the plugin also creates:

karta-1-1536.webp 1409 x 977 621,538 bytes md5 0f6492d85f6c15e13df9a51b5946008b
karta-1-2048.webp 1409 x 977 621,538 bytes md5 0f6492d85f6c15e13df9a51b5946008b

Both have the original’s dimensions and are not used anywhere. Across the 60 most recent WebP
attachments we found 22 such files. WordPress core skips sizes that are larger than the source
image; the plugin should do the same.

Note - “Preserve Metadata” is not related

The “Preserve Metadata” option is enabled. According to the code it only controls
maybe_strip_output_metadata() (removing EXIF from the output file). It does not affect
_wp_attachment_metadata, so it is not the cause of Issue 2.

Related issues found earlier (WebP quality)

A. The quality setting is passed to WP_Image_Editor::save() as a third argument
($editor->save($path, $mime, [‘quality’ => $q])). In WordPress 7.1 save() accepts only
($destfilename, $mime_type), so the argument is dropped and the editor default quality is
used. Quality should be set with $editor->set_quality($q) before saving.

B. When Preserve Metadata is OFF, maybe_strip_output_metadata() opens the finished WebP with
Imagick and writes it again. This re-encodes the image at about q75, regardless of the
quality setting. Measured with Quality set to 100: the same source gave 217,598 bytes after
the plugin’s conversion versus 394,692 bytes for a direct GD save at q100. Files converted
this way show base_q 36 in the VP8 header (about q75); after enabling Preserve Metadata the
same upload gives base_q 0 (q100). Stripping EXIF should not re-encode the pixel data. If re-encoding is unavoidable,
it should use the configured quality.

1 Like