{"id":388436,"date":"2026-11-06T13:46:01","date_gmt":"2026-11-06T13:46:01","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/ai-image-disclosure\/"},"modified":"2026-11-06T13:45:30","modified_gmt":"2026-11-06T13:45:30","slug":"mme-ai-image-disclosure","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/mme-ai-image-disclosure\/","author":23572692,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.3.0","stable_tag":"1.3.0","tested":"7.1.4","requires":"6.4","requires_php":"7.4","requires_plugins":null,"header_name":"MME AI Image Disclosure","header_author":"MME Pro","header_description":"Bakes an AI-disclosure badge (EU AI Act Art. 50) directly into Media Library image files, with full backup, revert and cache purging.","assets_banners_color":"a392cb","last_updated":"2026-11-06 13:45:30","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/mme-pro.de","rating":0,"author_block_rating":0,"active_installs":0,"downloads":38,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.3.0":{"tag":"1.3.0","author":"mmeprowp","date":"2026-11-06 13:45:30","revision":3788018}},"upgrade_notice":{"1.3.0":"<p>The plugin is now called MME AI Image Disclosure. No data or settings change.<\/p>","1.2.6":"<p>Redesigned tab bar and plugin mark; badge variants reduced to light and dark.<\/p>","1.2.5":"<p>Clearer badge source chooser and a tighter text label layout.<\/p>","1.2.4":"<p>New text label shape defaults and a tidier colour settings layout. Existing labelled images are unaffected.<\/p>","1.2.3":"<p>Removes the sort order field from the label type screens.<\/p>","1.2.2":"<p>Layout polish on the label types screen and a redesigned add button. No processing changes.<\/p>","1.2.1":"<p>Cleaner label-type screen: add types in a modal, and only the settings for the badge source you picked are shown.<\/p>","1.2.0":"<p>Redesigned admin interface with live text-label previews. No change to how images are processed; existing labels and backups are untouched.<\/p>","1.1.0":"<p>Adds text labels that need no badge image, AVIF support, and fixes labelling failing on Windows servers running ImageMagick.<\/p>","1.0.0":"<p>First release.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3788018,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3788018,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256},"icon.svg":{"filename":"icon.svg","revision":3788018,"resolution":false,"location":"assets","locale":false}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3788018,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3788018,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.3.0"],"block_files":[],"assets_screenshots":[],"screenshots":{"1":"Choosing label type, badge corner and contrast handling for a selection of images.","2":"Label types with their light and dark badge variants.","3":"Batch progress and per-image results, including the step that failed.","4":"Backup storage overview and the manual \"delete unused backups\" tool."}},"plugin_section":[262246],"plugin_tags":[2353,271023,14361,23968,39578],"plugin_category":[],"plugin_contributors":[282707],"plugin_business_model":[],"class_list":["post-388436","plugin","type-plugin","status-publish","hentry","plugin_section-dashboard-widgets","plugin_tags-ai","plugin_tags-ai-act","plugin_tags-compliance","plugin_tags-disclosure","plugin_tags-labeling","plugin_contributors-mmeprowp","plugin_committers-mmeprowp"],"banners":{"banner":"https:\/\/ps.w.org\/mme-ai-image-disclosure\/assets\/banner-772x250.png?rev=3788018","banner_2x":"https:\/\/ps.w.org\/mme-ai-image-disclosure\/assets\/banner-1544x500.png?rev=3788018","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":"https:\/\/ps.w.org\/mme-ai-image-disclosure\/assets\/icon.svg?rev=3788018","icon":"https:\/\/ps.w.org\/mme-ai-image-disclosure\/assets\/icon.svg?rev=3788018","icon_2x":false,"generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p>Article 50 of the EU AI Act requires visible disclosure when an image is AI-generated or AI-edited. A CSS overlay does not survive a right-click download, a hotlink, an RSS feed or a theme change \u2014 so this plugin composites a badge PNG <strong>into the image file itself<\/strong>, overwriting the file at its existing path so no URL, link or post content ever changes.<\/p>\n\n<p>Labelling is always a deliberate, manual action: you select the images, choose the label type and badge corner, and confirm. Nothing is ever labelled automatically, in bulk, or behind your back.<\/p>\n\n<p><strong>How it works<\/strong><\/p>\n\n<ol>\n<li>Select one or more images in the Media Library and choose the <em>Add AI Label<\/em> bulk action.<\/li>\n<li>Pick a label type, a corner, and either auto-contrast or a specific badge variant.<\/li>\n<li>Each image is queued as its own background job, so a large batch never hits a PHP timeout and one failure cannot block the rest.<\/li>\n<li>Per image, the plugin copies the original into a protected backup folder, samples the target corner's brightness to pick the readable badge variant, composites the badge, overwrites the file, regenerates the registered image sizes from the labelled original, appends a disclosure suffix to the alt text, and purges the caches it can reach.<\/li>\n<li>A results screen shows success or failure per image, with the exact step that failed.<\/li>\n<\/ol>\n\n<p><strong>Two kinds of label \u2014 image or text<\/strong><\/p>\n\n<p>Every label type can either composite a badge PNG, or render its own text label on the server: wording, text and background colour, opacity, corner radius and border, with separate colours for light and dark backgrounds. Text labels need no design work and no image file at all, so you can start disclosing immediately and swap in a designed badge later. They are rendered at high resolution and scaled down onto the image, so they stay crisp, and they get their own scale setting because a wide text strip needs more width than a square seal to stay readable.<\/p>\n\n<p><strong>Ready-made badges included<\/strong><\/p>\n\n<p>The plugin ships with two label types, <em>AI-generated<\/em> and <em>AI-modified<\/em>, each with a ready-made badge in a light and a dark version, so you can label images straight after activation. Upload your own PNG for either variant at any time to replace the default.<\/p>\n\n<p><strong>Re-labelling never stacks badges<\/strong><\/p>\n\n<p>Changing a label \u2014 different type, different corner, edited text, new badge file \u2014 always restores the original from the backup first and applies the new label to those original bytes. The plugin will not composite onto a file it knows is already labelled: if the backup is missing it refuses and says so rather than baking a second badge into the image.<\/p>\n\n<p><strong>Reversible by design<\/strong><\/p>\n\n<p><em>Restore original<\/em> copies the untouched backup back over the live file, rebuilds the image sizes and removes the alt-text suffix. Backups are never deleted automatically \u2014 not on restore, not on deactivation, not even on uninstall. Only the explicit <em>Delete unused backups<\/em> tool removes them, and it refuses to touch a backup whose image is still labelled.<\/p>\n\n<p><strong>Features<\/strong><\/p>\n\n<ul>\n<li>Badge is baked into the image bytes \u2014 verifiable by re-downloading the file.<\/li>\n<li>Filename and URL never change; no database rewriting, no broken links.<\/li>\n<li>Ships with one ready-to-use label type (AI-generated) and no hardcoded limit \u2014 add, rename or delete types freely, each with a light- and a dark-background variant.<\/li>\n<li>Per type: use an uploaded badge PNG, or a text label the plugin renders itself \u2014 no image required.<\/li>\n<li>Re-labelling always restores the original first, so a second badge can never be stacked onto an already-labelled image.<\/li>\n<li>Auto-contrast: the target corner's mean luminance decides which badge variant is used.<\/li>\n<li>Imagick preferred, GD fallback \u2014 works on both kinds of host. JPEG, PNG, GIF and WebP everywhere; AVIF and HEIC where the host supports them.<\/li>\n<li>Idempotent: re-running the label on an already-labelled image never stacks a second badge.<\/li>\n<li>Background processing via Action Scheduler when another plugin provides it, WP-Cron otherwise. No bundled library.<\/li>\n<li>Legibility floor: image sizes too small to carry a readable badge are rebuilt from the unlabelled original instead of showing a smudge.<\/li>\n<li>Automatic cache purging for WP Rocket, W3 Total Cache, LiteSpeed Cache and SiteGround Optimizer when active; optional Cloudflare purge-by-URL.<\/li>\n<li>Optional labelled WebP sidecar, served through a <code>&lt;picture&gt;<\/code> element. Off by default; the primary file always keeps its own format and MIME type.<\/li>\n<li>Persistent job log with the failed step per image, plus a dashboard widget for backup folder size.<\/li>\n<li>Own capability (<code>ai_label_manage<\/code>), granted to administrators, so an agency can hand labelling to an editor without full admin rights.<\/li>\n<li>Per-site settings and badge registry, so one multisite network can serve many clients.<\/li>\n<li>WP-CLI: <code>wp ai-label apply|restore|reapply|status|run-queue<\/code>.<\/li>\n<\/ul>\n\n<h3>External services<\/h3>\n\n<p>This plugin does not contact any external service by default.<\/p>\n\n<p>If \u2014 and only if \u2014 you enter a Cloudflare zone ID and API token on the settings screen, the plugin calls the Cloudflare cache-purge API (<code>https:\/\/api.cloudflare.com\/client\/v4\/zones\/{zone}\/purge_cache<\/code>) after an image is labelled or restored, so the CDN stops serving the previous version of that file. The only data sent is the public URLs of the image files that changed, together with your API token for authentication. No personal data and no image content is transmitted. The token is stored encrypted and is never displayed again.<\/p>\n\n<p>Cloudflare terms of service: https:\/\/www.cloudflare.com\/terms\/\nCloudflare privacy policy: https:\/\/www.cloudflare.com\/privacypolicy\/<\/p>\n\n<p>Remove the token from the settings screen (type <code>delete<\/code> into the field) to stop all outgoing requests.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin to <code>\/wp-content\/plugins\/mme-ai-image-disclosure<\/code> and activate it.<\/li>\n<li>Activation creates two label types, <em>AI-generated<\/em> and <em>AI-modified<\/em>, each using the built-in badge images for light and dark backgrounds \u2014 so you can label an image straight away without designing anything.<\/li>\n<li>Optional: under <strong>Media \u2192 MME AI Image Disclosure \u2192 Label types &amp; badges<\/strong>, upload your own badge PNG for either variant, or switch a type to a generated text label and set its wording and colours.<\/li>\n<li>Review <strong>Settings<\/strong> \u2014 badge scale, edge padding, auto-contrast threshold and the width down to which image sizes keep the badge.<\/li>\n<li>Select images in the Media Library and use the <strong>Add AI Label<\/strong> bulk action.<\/li>\n<\/ol>\n\n<p>The plugin needs either the Imagick or the GD PHP extension, and a writable <code>wp-content\/uploads<\/code> folder for the backup store.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20this%20decide%20for%20me%20which%20images%20need%20a%20label%3F\"><h3>Does this decide for me which images need a label?<\/h3><\/dt>\n<dd><p>No. Whether an image requires an Article 50 disclosure is a human, legal judgement. The plugin only carries out the disclosure you ask it to apply.<\/p><\/dd>\n<dt id=\"is%20my%20original%20image%20lost%3F\"><h3>Is my original image lost?<\/h3><\/dt>\n<dd><p>No. The original bytes are copied into <code>wp-content\/uploads\/ai-label-backups\/{attachment-id}\/<\/code> before anything is written, and that copy is never overwritten or deleted automatically. <em>Restore original<\/em> puts it back exactly as it was.<\/p><\/dd>\n<dt id=\"will%20my%20image%20urls%20change%3F\"><h3>Will my image URLs change?<\/h3><\/dt>\n<dd><p>No. The labelled file is written to the same path with the same filename, so post content, hotlinks and search-engine indexes keep working.<\/p><\/dd>\n<dt id=\"why%20do%20small%20thumbnails%20sometimes%20have%20no%20badge%3F\"><h3>Why do small thumbnails sometimes have no badge?<\/h3><\/dt>\n<dd><p>A badge scaled down to a handful of pixels is illegible and looks broken. Sizes narrower than your configured threshold whose badge would fall below the 24px legibility floor are rebuilt from the unlabelled original, and the skip is recorded in the job log.<\/p><\/dd>\n<dt id=\"what%20about%20an%20image%20optimiser%20like%20smush%20or%20shortpixel%3F\"><h3>What about an image optimiser like Smush or ShortPixel?<\/h3><\/dt>\n<dd><p>Run the optimiser's bulk optimise after labelling. If an optimiser (or any thumbnail-regeneration tool) rebuilds the sizes of an already-labelled image, the Media Library flags it so you can re-apply the label.<\/p><\/dd>\n<dt id=\"i%20don%27t%20have%20a%20badge%20image.%20can%20i%20still%20label%20images%3F\"><h3>I don't have a badge image. Can I still label images?<\/h3><\/dt>\n<dd><p>Yes. Open <strong>Media \u2192 MME AI Image Disclosure \u2192 Label types &amp; badges<\/strong>, set that label type's badge source to <em>Generated text label<\/em>, type the wording and save. The plugin renders the label itself using a font on the server, so no upload and no design work is needed. If no font is found automatically, enter the path to a .ttf or .otf file under Settings \u2192 Font file.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20i%20label%20an%20image%20that%20is%20already%20labelled%3F\"><h3>What happens if I label an image that is already labelled?<\/h3><\/dt>\n<dd><p>The original is restored from its backup first, and your new label is applied to those original bytes \u2014 so the wording, corner or badge changes without a second badge appearing. If the backup is missing, the plugin refuses rather than compositing on top of the existing badge.<\/p><\/dd>\n<dt id=\"i%20changed%20the%20label%20text.%20do%20existing%20images%20update%3F\"><h3>I changed the label text. Do existing images update?<\/h3><\/dt>\n<dd><p>No, and that is deliberate: editing a label type never rewrites images behind your back. Images labelled with the old wording are flagged in the Media Library, and <em>Re-apply with current badge<\/em> re-labels them from their originals when you choose to.<\/p><\/dd>\n<dt id=\"which%20image%20formats%20are%20supported%3F\"><h3>Which image formats are supported?<\/h3><\/dt>\n<dd><p>JPEG, PNG, static GIF and WebP on every host. AVIF is added when your PHP build can read and write it (Imagick with libavif, or GD on PHP 8.1+), and HEIC when ImageMagick supports it. Unsupported formats are refused with a clear message instead of being silently skipped.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20animated%20gifs%20or%20svg%3F\"><h3>Does it work with animated GIFs or SVG?<\/h3><\/dt>\n<dd><p>No. Animated images would lose their animation and SVG has no pixel buffer to composite onto, so both are refused with a clear error rather than silently mangled.<\/p><\/dd>\n<dt id=\"can%20i%20add%20my%20own%20cdn%3F\"><h3>Can I add my own CDN?<\/h3><\/dt>\n<dd><p>Yes. Hook <code>ai_label_purge_cdn<\/code> (or the broader <code>ai_label_purge_attachment<\/code>), both of which receive the attachment ID and the list of changed URLs.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.3.0<\/h4>\n\n<ul>\n<li>Added built-in badge images for light and dark backgrounds, and a new default <em>AI-modified<\/em> label type alongside <em>AI-generated<\/em>. Label types without an uploaded badge use the built-in images automatically.<\/li>\n<li>Admin notices from other plugins now appear above the plugin header instead of beside the title.<\/li>\n<li>Renamed the plugin to MME AI Image Disclosure. The text domain changed to match; settings, label types, badge registry, job log, attachment metadata and backups are all untouched and keep working.<\/li>\n<\/ul>\n\n<h4>1.2.6<\/h4>\n\n<ul>\n<li>Redesigned the tab bar: a white rail with an icon per section, the active tab filled with the accent gradient, and a live counter on Job log while background jobs are running. Collapses to icons only on small screens.<\/li>\n<li>New plugin mark \u2014 a framed image with a disclosure seal stamped into its corner, drawn as inline SVG \u2014 plus a version chip beside the title.<\/li>\n<li>Save and Delete for a label type now share one row, with the destructive control at the far end.<\/li>\n<li>Removed the two optional extra badge variants. Each label type carries a light- and a dark-background badge, which is what auto-contrast chooses between.<\/li>\n<\/ul>\n\n<h4>1.2.5<\/h4>\n\n<ul>\n<li>The badge source is now a centred chooser with its own heading and icons, styled like the primary button so it reads as the decision it is.<\/li>\n<li>Label text, padding, corner radius and border width sit on one row.<\/li>\n<\/ul>\n\n<h4>1.2.4<\/h4>\n\n<ul>\n<li>Renamed the \"Display name\" field to \"Label type name\".<\/li>\n<li>Simplified the label type card header to just the type name \u2014 the badge source, readiness, slug and usage count chips are gone.<\/li>\n<li>New text label defaults: padding 50, corner radius 50, border width 1. Label types still carrying the previous defaults are moved onto the new ones on update; any type whose shape was edited is left untouched, and no already-labelled image changes.<\/li>\n<li>The colour and opacity settings for each contrast variant are now one per row, label left and control right, instead of wrapping into a ragged grid.<\/li>\n<\/ul>\n\n<h4>1.2.3<\/h4>\n\n<ul>\n<li>Removed the sort order field from the label type form and the add dialog. Types are listed alphabetically; the stored order is still respected if set programmatically.<\/li>\n<\/ul>\n\n<h4>1.2.2<\/h4>\n\n<ul>\n<li>The environment summary (image engine, queue runner, text-label readiness, backup size) moved from the page header to a footer below the content.<\/li>\n<li>\"Save label type\" now sits below the badge settings in both modes, so the flow reads top to bottom whichever source is selected.<\/li>\n<li>Redesigned the \"Add label type\" button as a gradient pill with an inline SVG icon, so it no longer depends on the dashicons font rendering inside a styled button.<\/li>\n<\/ul>\n\n<h4>1.2.1<\/h4>\n\n<ul>\n<li>Adding a label type now happens in a modal dialog opened from a button, instead of a form always sitting at the bottom of the screen.<\/li>\n<li>Each label type is a single form \u2014 display name, alt-text suffix, sort order, badge source \u2014 and only the settings for the selected badge source are shown: image variants for a badge PNG, wording and colours for generated text.<\/li>\n<li>Switching badge source without saving is flagged, so the visible settings are never mistaken for the saved state.<\/li>\n<li>Label type headers are one row: name, badge source, readiness, slug and how many images use it.<\/li>\n<li>Badge image slots are a tidy pair (light and dark) with the two optional extra variants collapsed.<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>Redesigned the whole admin interface: card layout, live environment status in the header, pill tabs, a visual 2\u00d72 badge-position picker, toggle switches, segmented badge-source control, colour swatches, stat tiles, filter chips, empty states, an animated progress bar and a selection gallery. Responsive, keyboard-friendly, reduced-motion aware, and it inherits the user's admin colour scheme.<\/li>\n<li>Text badge previews now update live as you type the wording, colours or spacing.<\/li>\n<li>A fresh install now creates one label type instead of two, set to a generated text label so the plugin works immediately with nothing to upload.<\/li>\n<li>Every label type explicitly offers both badge sources side by side \u2014 uploaded PNG or generated text \u2014 switchable at any time.<\/li>\n<li>Removed duplicate element ids from forms on screens carrying several forms, and labelled the per-image override selects for screen readers.<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>New: generated text labels as an alternative to uploading a badge PNG, with per-variant colours, opacity, radius and border, and a server-side font with autodetection.<\/li>\n<li>New: separate scale and legibility floor for text labels, derived from the rendered text height.<\/li>\n<li>New: \"Change AI label\" row action, plus an explicit warning on the apply screen when a selection contains already-labelled images.<\/li>\n<li>Added a hard guard so a badge can never be composited onto a file the plugin knows is labelled; if the backup is missing the job fails loudly instead.<\/li>\n<li>Added AVIF support (and HEIC on ImageMagick) where the host can read and write it.<\/li>\n<li>Fixed: on Windows, ImageMagick held a memory-mapped handle on the source file, so every labelled image failed to move into place. Images are now read through a blob, and both backends fall back to an overwriting copy if rename is refused.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release: manual badge compositing into image files, backup and restore, background job queue, label type and badge registry, auto-contrast, sub-size regeneration with a legibility floor, alt-text disclosure, cache and Cloudflare purging, optional WebP sidecar, job log, WP-CLI commands.<\/li>\n<\/ul>","raw_excerpt":"Bake an AI-disclosure badge into your image files \u2014 survives downloads, hotlinking and theme changes. Manual, reversible, with full backups.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/388436","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=388436"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/mmeprowp"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=388436"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=388436"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=388436"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=388436"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=388436"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=388436"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}