<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Uglypear Data</title>
    <description>The latest articles on DEV Community by Uglypear Data (@uglypeardata).</description>
    <link>https://dev.to/uglypeardata</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4045045%2Fa9142f8b-0a4c-4a9e-bd3d-a6047d9032e2.png</url>
      <title>DEV Community: Uglypear Data</title>
      <link>https://dev.to/uglypeardata</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/uglypeardata"/>
    <language>en</language>
    <item>
      <title>Email Attachment Too Large? Mail Limits and Compression Strategies</title>
      <dc:creator>Uglypear Data</dc:creator>
      <pubDate>Thu, 13 Aug 2026 04:12:49 +0000</pubDate>
      <link>https://dev.to/uglypeardata/email-attachment-too-large-mail-limits-and-compression-strategies-4nlg</link>
      <guid>https://dev.to/uglypeardata/email-attachment-too-large-mail-limits-and-compression-strategies-4nlg</guid>
      <description>&lt;p&gt;Original URL: &lt;a href="https://www.uglypear.com/en/blog/email-attachment-compression.html" rel="noopener noreferrer"&gt;https://www.uglypear.com/en/blog/email-attachment-compression.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Can't send email attachments that are too large? This article summarizes attachment size limits for QQ Mail, WeCom, Outlook, and Gmail, detailing 3 compression strategies — file compression, split archives, and cloud storage relay, with a comparison table and real case studies. The key is understanding your email provider's limits and choosing the right strategy for each situation.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Comparison of Attachment Size Limits by Email Provider
&lt;/h2&gt;

&lt;p&gt;Different email providers have strict limits on attachment size, and these limits are hard — exceeding by even 1KB means the email won't send. Understanding the limits of the recipient's email provider is the first step in choosing a compression strategy. The table below summarizes the attachment limits of mainstream domestic email providers and office tools.&lt;/p&gt;

&lt;p&gt;As the table above shows, WeCom, Outlook, and DingTalk have the strictest limits (20MB), Gmail is 25MB, and QQ and 163 Mail are relatively lenient (50MB). This means attachments sent to enterprise users should ideally be kept under 20MB to be safe. An 80MB PDF report cannot be sent through any mainstream email provider without compression — compression is a necessary step.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Email/Tool&lt;/th&gt;
&lt;th&gt;Standard Attachment Limit&lt;/th&gt;
&lt;th&gt;Large Attachment Feature&lt;/th&gt;
&lt;th&gt;Over-Limit Handling&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;QQ Mail&lt;/td&gt;
&lt;td&gt;50MB&lt;/td&gt;
&lt;td&gt;Supported, up to 3GB (7-day validity)&lt;/td&gt;
&lt;td&gt;Auto-convert to large attachment link&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WeCom&lt;/td&gt;
&lt;td&gt;20MB&lt;/td&gt;
&lt;td&gt;WeDrive share link&lt;/td&gt;
&lt;td&gt;Prompt to use WeDrive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outlook (web)&lt;/td&gt;
&lt;td&gt;20MB&lt;/td&gt;
&lt;td&gt;OneDrive link&lt;/td&gt;
&lt;td&gt;Auto-upload to OneDrive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gmail&lt;/td&gt;
&lt;td&gt;25MB&lt;/td&gt;
&lt;td&gt;Google Drive link&lt;/td&gt;
&lt;td&gt;Auto-upload to Drive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;163 Mail&lt;/td&gt;
&lt;td&gt;50MB&lt;/td&gt;
&lt;td&gt;Supported, up to 2GB&lt;/td&gt;
&lt;td&gt;Prompt to use Netdisk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DingTalk&lt;/td&gt;
&lt;td&gt;20MB&lt;/td&gt;
&lt;td&gt;DingDrive share link&lt;/td&gt;
&lt;td&gt;Prompt to use DingDrive&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  2. Detailed Explanation of 3 Email Attachment Compression Strategies
&lt;/h2&gt;

&lt;p&gt;Based on file type and size, there are 3 mainstream strategies for dealing with attachment over-limit issues. Each strategy differs in principle, applicable scenario, and operational difficulty. The table below provides an overall comparison first, followed by detailed explanations.&lt;/p&gt;

&lt;p&gt;File compression is the preferred strategy — compressing the file itself before sending both solves the attachment over-limit problem and reduces transfer time and storage consumption. Different file types require different compression strategies: PDF documents mainly rely on embedded image downsampling and font subsetting, images rely on format conversion (PNG to WebP/JPEG) and resolution reduction, and Office documents rely on compressing embedded resources and cleaning up redundancy.&lt;/p&gt;

&lt;p&gt;Taking the most common PDF compression as an example, SmartSlim, based on its Rust compression engine, automatically identifies the image types within a PDF and assigns strategies: scanned documents are downsampled to 150DPI and converted to grayscale JPEG (90%+ compression), photos are reduced to 200DPI and converted to color JPEG quality 80 (80% compression), and vector charts are kept as-is with only structural optimization. This content-based assignment works better than uniform parameters — an 80MB scanned contract can be compressed to 6MB, while text and charts remain virtually lossless.&lt;/p&gt;

&lt;p&gt;For the complete methodology of file compression, see the Complete Guide to File Compression.&lt;/p&gt;

&lt;p&gt;Some files still exceed email limits even after compression — for example, a collection of high-definition images that's still 60MB after compression, or video files that are inherently incompressible. In these cases, use split archive compression: split a large package into multiple smaller packages under the limit, send them in multiple emails, and the recipient downloads all volumes and merges them for extraction.&lt;/p&gt;

&lt;p&gt;The volume size should be set to 80% of the email limit to leave a margin. WeCom limits 20MB, so set volumes to 15MB; QQ Mail limits 50MB, so set volumes to 40MB. A 60MB compressed package split into 15MB volumes will produce 4 packages (15+15+15+15), sent in 4 emails. Note that all volumes must use the same format (ZIP or 7Z), and the recipient needs the corresponding extraction tool.&lt;/p&gt;

&lt;p&gt;When the file itself is an incompressible format (such as video, or an already-compressed ZIP package), or when the size exceeds 100MB, sending it directly as an attachment is impractical. In this case, use cloud storage relay: upload the file to cloud storage, generate a share link, and only send the link and extraction code in the email. The recipient clicks the link to download the file themselves, unconstrained by email limits.&lt;/p&gt;

&lt;p&gt;Common cloud storage services and their limits: Baidu Netdisk single file limit 4GB (free), Alibaba Cloud Drive single file limit 100GB (free), Tencent WeDrive single file limit 1GB (enterprise 100GB), OneDrive single file limit 250GB. For internal enterprise use, enterprise cloud drives (WeDrive/DingDrive/OneDrive for Business) are recommended, as they allow access permission control and provide audit logs.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;Principle&lt;/th&gt;
&lt;th&gt;Applicable Scenario&lt;/th&gt;
&lt;th&gt;Expected Compression Rate&lt;/th&gt;
&lt;th&gt;Operational Difficulty&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;File compression&lt;/td&gt;
&lt;td&gt;Downsampling + format conversion + redundancy removal&lt;/td&gt;
&lt;td&gt;PDF/images/Office documents&lt;/td&gt;
&lt;td&gt;70%–92%&lt;/td&gt;
&lt;td&gt;★☆☆☆☆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Split archive&lt;/td&gt;
&lt;td&gt;Split large package into smaller packages&lt;/td&gt;
&lt;td&gt;Files still over-limit after compression&lt;/td&gt;
&lt;td&gt;No size reduction, split for sending&lt;/td&gt;
&lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud storage relay&lt;/td&gt;
&lt;td&gt;Upload to cloud and send share link&lt;/td&gt;
&lt;td&gt;Video/ultra-large data packages&lt;/td&gt;
&lt;td&gt;No size reduction, link replaces file&lt;/td&gt;
&lt;td&gt;★☆☆☆☆&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  3. Real-World Case: 120MB Project Report Compressed to 18MB for Sending
&lt;/h2&gt;

&lt;p&gt;A consulting firm needed to send a quarterly project report to a client via WeCom. The report was in PDF format, originally 120MB, containing 80 pages of text, 45 on-site project photos, 12 data charts, and 3 pages of scanned signature pages. WeCom's attachment limit is 20MB, and the client's IT policy did not allow the use of external cloud drives, so it had to be sent as a direct attachment.&lt;/p&gt;

&lt;p&gt;Document characteristics: 80 pages A4, 45 photos at 300DPI JPEG format (totaling 85MB), 12 data charts in vector PDF format (totaling 15MB), 3 scanned signature pages at 600DPI (totaling 18MB), embedded fonts 2MB.&lt;/p&gt;

&lt;p&gt;Result: 18MB, a compression rate of 85%, below WeCom's 20MB limit. The on-site photos showed virtually no difference to the naked eye on screen, the scanned signature pages had clearly legible text and official seals, and the data charts had sharp lines with no loss. The entire process was completed locally, and the report did not pass through any online server, meeting the confidentiality requirements for business documents.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File Type&lt;/th&gt;
&lt;th&gt;Original Size&lt;/th&gt;
&lt;th&gt;Compressed Size&lt;/th&gt;
&lt;th&gt;Compression Rate&lt;/th&gt;
&lt;th&gt;Quality Impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Scanned contract PDF&lt;/td&gt;
&lt;td&gt;80MB&lt;/td&gt;
&lt;td&gt;6MB&lt;/td&gt;
&lt;td&gt;92.5%&lt;/td&gt;
&lt;td&gt;Text clearly legible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Project report PDF (with images)&lt;/td&gt;
&lt;td&gt;120MB&lt;/td&gt;
&lt;td&gt;18MB&lt;/td&gt;
&lt;td&gt;85.0%&lt;/td&gt;
&lt;td&gt;Virtually no difference for screen reading&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Product manual PDF&lt;/td&gt;
&lt;td&gt;45MB&lt;/td&gt;
&lt;td&gt;8MB&lt;/td&gt;
&lt;td&gt;82.2%&lt;/td&gt;
&lt;td&gt;Slight loss of image detail&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Word bid document&lt;/td&gt;
&lt;td&gt;50MB&lt;/td&gt;
&lt;td&gt;5MB&lt;/td&gt;
&lt;td&gt;90.0%&lt;/td&gt;
&lt;td&gt;Text and charts unaffected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image collection (PNG)&lt;/td&gt;
&lt;td&gt;200MB&lt;/td&gt;
&lt;td&gt;30MB&lt;/td&gt;
&lt;td&gt;85.0%&lt;/td&gt;
&lt;td&gt;Needs split archive for sending&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  4. Attachment Sending Recommendations for Different Scenarios
&lt;/h2&gt;

&lt;p&gt;Different types of files have very different size characteristics and compression potential. The table below provides attachment sending strategy recommendations by common office scenario.&lt;/p&gt;

&lt;p&gt;One general principle: Compress first whenever possible (reduces both size and transfer time), use split archives if still over-limit after compression, and use cloud storage for ultra-large incompressible files. Confirm the recipient's email limit first, then decide on a strategy — attachments sent to WeCom users should be kept under 20MB to be safest.&lt;/p&gt;

&lt;p&gt;If you need to compare different compression tools for selection, see the File Compression Tool Selection Guide: 7-Dimension Evaluation.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Target Email&lt;/th&gt;
&lt;th&gt;Attachment Limit&lt;/th&gt;
&lt;th&gt;Recommended Volume Size&lt;/th&gt;
&lt;th&gt;Number of Splits for 60MB File&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;WeCom&lt;/td&gt;
&lt;td&gt;20MB&lt;/td&gt;
&lt;td&gt;15MB&lt;/td&gt;
&lt;td&gt;4 packages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outlook&lt;/td&gt;
&lt;td&gt;20MB&lt;/td&gt;
&lt;td&gt;15MB&lt;/td&gt;
&lt;td&gt;4 packages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gmail&lt;/td&gt;
&lt;td&gt;25MB&lt;/td&gt;
&lt;td&gt;20MB&lt;/td&gt;
&lt;td&gt;3 packages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;QQ Mail&lt;/td&gt;
&lt;td&gt;50MB&lt;/td&gt;
&lt;td&gt;40MB&lt;/td&gt;
&lt;td&gt;2 packages&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  5. Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;Q1: What to do when an email attachment exceeds the email limit?&lt;/p&gt;

&lt;p&gt;Three options: First, use a compression tool to compress the file under the limit (e.g., compress a PDF from 80MB to 6MB). Second, if it can't be compressed enough, use split archive compression to break it into multiple packages under the limit and send them in multiple emails. Third, for ultra-large files, use cloud storage relay — upload to cloud storage and generate a share link, sending only the link in the email. A 120MB project report can first be compressed to 18MB, then split into 2 volumes of 9MB each to fit WeCom's 20MB limit. The key is to first understand the recipient's specific email limit, then choose the corresponding strategy.&lt;/p&gt;

&lt;p&gt;Q2: Will PDF quality degrade after compression for email?&lt;/p&gt;

&lt;p&gt;With proper compression, the difference is virtually imperceptible to the naked eye. 150DPI is sufficient for screen reading, and scanned documents reduced to 150DPI and converted to grayscale JPEG can be compressed by over 90% while keeping text clearly legible. Photo content reduced to 200DPI with JPEG quality 80 shows virtually no difference on screen or A4 print. The key is to assign strategies by content type — keep text pages as vector, downsample photo pages, and grayscale scan pages — to avoid blurriness from a one-size-fits-all approach. SmartSlim automatically identifies PDF content types and assigns the optimal strategy.&lt;/p&gt;

&lt;p&gt;Q3: What are the attachment limits for WeCom and QQ Mail?&lt;/p&gt;

&lt;p&gt;WeCom has a single-file attachment limit of 20MB, suitable for sending compressed documents. QQ Mail has a standard attachment limit of 50MB, and its large attachment feature supports files up to 3GB but requires the recipient to download from the server. Outlook limits 20MB, and Gmail limits 25MB. Before sending, confirm the recipient's email limit, then decide whether to use direct attachment or cloud storage relay. For cross-enterprise sending, it's recommended to prepare attachments according to the strictest limit (20MB).&lt;/p&gt;

&lt;p&gt;Q4: How does the recipient extract a split archive?&lt;/p&gt;

&lt;p&gt;Place all volume packages in the same folder, right-click the first package (usually with a .part1 or .zip.001 suffix) and select extract, and the tool will automatically recognize and merge the remaining volumes. Make sure all volumes are fully downloaded — missing any one will prevent extraction. We recommend using 7-Zip or SmartSlim, which are compatible with both ZIP and 7Z split formats. Do not rename the volume packages, as this may cause recognition failure.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Key Parameters&lt;/th&gt;
&lt;th&gt;Size Change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;On-site photo compression&lt;/td&gt;
&lt;td&gt;300DPI→150DPI, JPEG q80&lt;/td&gt;
&lt;td&gt;120→35MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Scanned signature page compression&lt;/td&gt;
&lt;td&gt;600DPI→150DPI, grayscale JPEG q72&lt;/td&gt;
&lt;td&gt;35→19MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Data chart optimization&lt;/td&gt;
&lt;td&gt;Vector preserved, remove redundant objects&lt;/td&gt;
&lt;td&gt;19→18.5MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Font subsetting + repackaging&lt;/td&gt;
&lt;td&gt;Keep only used characters&lt;/td&gt;
&lt;td&gt;18.5→18MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  6. Summary
&lt;/h2&gt;

&lt;p&gt;Email attachments can't be sent because the file size exceeds the email provider's hard limit. The 3 strategies have clear logic: File compression is the first choice (downsampling + format conversion + redundancy removal, 70%–92% compression rate), split archive compression is the backup (split packages for sending when still over-limit after compression), and cloud storage relay is the fallback (send links for ultra-large incompressible files). A 120MB project report can be reliably compressed to 18MB using the "compress first, then send" strategy, fitting all mainstream email providers.&lt;/p&gt;

&lt;p&gt;Remember three points: First, confirm the recipient's email limit before choosing a strategy — preparing for 20MB is safest for enterprise users. Second, prioritize compressing the file itself (reduces both size and transfer time), and use split archives or cloud storage only when compression isn't enough. Third, use local compression tools for sensitive business documents — don't upload them to online compression websites. Choose the right strategy, and even the largest email attachments can be sent.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Typical File&lt;/th&gt;
&lt;th&gt;Original Size&lt;/th&gt;
&lt;th&gt;Recommended Strategy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Business contract signing&lt;/td&gt;
&lt;td&gt;Scanned PDF&lt;/td&gt;
&lt;td&gt;20–80MB&lt;/td&gt;
&lt;td&gt;File compression: scan pages downsampled + grayscale JPEG, 90%+ compression&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Project report delivery&lt;/td&gt;
&lt;td&gt;Image/text PDF/Word&lt;/td&gt;
&lt;td&gt;50–200MB&lt;/td&gt;
&lt;td&gt;File compression: image downsampling + font subsetting, 80%–90% compression&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Design draft review&lt;/td&gt;
&lt;td&gt;PSD/AI/PNG&lt;/td&gt;
&lt;td&gt;100–500MB&lt;/td&gt;
&lt;td&gt;File compression + split archive: export JPEG then compress, split for sending&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Video material delivery&lt;/td&gt;
&lt;td&gt;MP4/MOV&lt;/td&gt;
&lt;td&gt;200MB–2GB&lt;/td&gt;
&lt;td&gt;Cloud storage relay: compress video then upload to cloud and send link&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data report sending&lt;/td&gt;
&lt;td&gt;Excel/PDF&lt;/td&gt;
&lt;td&gt;5–30MB&lt;/td&gt;
&lt;td&gt;File compression: Excel redundancy cleanup + PDF optimization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bid document submission&lt;/td&gt;
&lt;td&gt;Word/PDF&lt;/td&gt;
&lt;td&gt;30–80MB&lt;/td&gt;
&lt;td&gt;File compression: image compression + font subsetting + redundancy cleanup&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;Q: What are the attachment size limits for major email providers?&lt;br&gt;
A: QQ Mail: 50MB for free, 2GB for VIP. WeCom (Enterprise WeChat): 100MB. Outlook/Hotmail: 34MB. Gmail: 25MB. 163 Mail: 50MB for free, 100MB for VIP. If your file exceeds these limits, use compression first, then split archives, or switch to cloud storage relay. SmartSlim can compress files to fit within provider limits.&lt;/p&gt;

&lt;p&gt;Q: How to send files over 100MB via email?&lt;br&gt;
A: Files over 100MB cannot be sent directly via email (most providers limit to 25-50MB). Three solutions: 1) Compress heavily — use 7Z with ultra compression to minimize size. 2) Split archive — use volume splitting in WinRAR/7-Zip (e.g., 20MB volumes). 3) Cloud relay — upload to cloud storage (Baidu Netdisk, WeTransfer, Google Drive) and share the link. SmartSlim integrates with cloud storage services for seamless large-file sharing.&lt;/p&gt;

&lt;p&gt;Q: What is the best compression format for email attachments?&lt;br&gt;
A: ZIP is the most compatible format for email attachments — all recipients can open it without additional software. If the recipient has 7-Zip or WinRAR, 7Z offers 30-50% better compression. For maximum compression, use 7Z with LZMA2 algorithm. For encrypted files, use ZIP with AES-256 encryption (supported by Windows, macOS, and major archivers).&lt;/p&gt;

&lt;p&gt;Q: How to split a large file into smaller volumes for email?&lt;br&gt;
A: Use WinRAR or 7-Zip's volume splitting feature: in WinRAR, select 'Split to volumes' and set size (e.g., 20MB). In 7-Zip, use '-v20m' parameter. The tool creates multiple numbered files (.part1.rar, .part2.rar, etc.). The recipient needs all parts in the same folder to extract. SmartSlim supports automatic volume splitting with customizable size limits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The key to email attachment too large? mail... lies in identifying the sources of bloat and handling them accordingly. Choose the right compression strategy based on your scenario, prioritizing the largest contributors. SmartSlim can handle all compression steps in one click.&lt;/p&gt;

&lt;p&gt;Related:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/file-compression-complete-guide.html" rel="noopener noreferrer"&gt;Complete Guide to File Compression&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/zip-vs-7z-vs-rar.html" rel="noopener noreferrer"&gt;ZIP vs 7Z vs RAR: Which Compression Format Is Best?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/free-compression-software-review.html" rel="noopener noreferrer"&gt;Free Compression Software: 7 Tools Reviewed&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>emailattachmentcompression</category>
      <category>gmailattachment</category>
      <category>outlookattachment</category>
      <category>splitarchive</category>
    </item>
    <item>
      <title>What's the Difference Between DPI and PPI? Essential for Scan Compression</title>
      <dc:creator>Uglypear Data</dc:creator>
      <pubDate>Wed, 12 Aug 2026 02:39:46 +0000</pubDate>
      <link>https://dev.to/uglypeardata/whats-the-difference-between-dpi-and-ppi-essential-for-scan-compression-28dp</link>
      <guid>https://dev.to/uglypeardata/whats-the-difference-between-dpi-and-ppi-essential-for-scan-compression-28dp</guid>
      <description>&lt;p&gt;Original URL: &lt;a href="https://www.uglypear.com/en/blog/dpi-vs-ppi-guide.html" rel="noopener noreferrer"&gt;https://www.uglypear.com/en/blog/dpi-vs-ppi-guide.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What's the difference between DPI and PPI? This article explains from three angles: definition, usage scenarios, and conversion relationships, with a scan DPI selection guide — comparing size and sharpness for screen reading at 150 DPI, printing at 300 DPI, and archiving at 600 DPI. Understanding this distinction is essential for effective scanned document compression.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. DPI vs PPI Definition Comparison
&lt;/h2&gt;

&lt;p&gt;DPI and PPI are the two most easily confused concepts in document scanning and image processing. Although both units are "dots/pixels per inch," they describe resolution in different domains. Getting the distinction clear is the prerequisite for making the right choices in scanning and compression.&lt;/p&gt;

&lt;p&gt;Simple mnemonic: DPI governs the "physical world" (ink dots on paper), PPI governs the "digital world" (pixels on screen). A scanner's advertised "600DPI scan resolution" means it samples 600 dots per inch; once stored as a digital image, those dots become pixels. An A4 page scanned at 600DPI has a digital image pixel dimension of 4961x7016.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Comparison Item&lt;/th&gt;
&lt;th&gt;DPI&lt;/th&gt;
&lt;th&gt;PPI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Full name&lt;/td&gt;
&lt;td&gt;Dots Per Inch&lt;/td&gt;
&lt;td&gt;Pixels Per Inch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Meaning&lt;/td&gt;
&lt;td&gt;Physical dots per inch&lt;/td&gt;
&lt;td&gt;Pixels per inch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Application domain&lt;/td&gt;
&lt;td&gt;Printing, scanning&lt;/td&gt;
&lt;td&gt;Screen display, digital images&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Devices&lt;/td&gt;
&lt;td&gt;Printers, scanners&lt;/td&gt;
&lt;td&gt;Monitors, phone screens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Affects&lt;/td&gt;
&lt;td&gt;Print clarity, scan precision&lt;/td&gt;
&lt;td&gt;Screen display fineness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical values&lt;/td&gt;
&lt;td&gt;150/300/600/1200&lt;/td&gt;
&lt;td&gt;72/96/150/326&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Modifiable?&lt;/td&gt;
&lt;td&gt;Set at scan time, not after&lt;/td&gt;
&lt;td&gt;Digital images can be resampled&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  2. Scanned File Size by DPI
&lt;/h2&gt;

&lt;p&gt;The relationship between scanned file size and DPI follows the square law: pixel count is proportional to DPI squared, and so is file size. This is the key formula for understanding scanned file size changes.&lt;/p&gt;

&lt;p&gt;DPI-size relationship formula: File size ≈ (DPI / baseline DPI)^2 × baseline size. Taking an A4 page (8.27x11.69 inches) as an example, grayscale JPEG quality 80:&lt;/p&gt;

&lt;p&gt;The table above clearly shows: doubling DPI from 150 to 300 quadruples size; doubling from 300 to 600 quadruples again. A 1200DPI A4 color page reaches 136MB — 64x that of 150DPI. This is why blindly chasing high DPI causes file size to explode.&lt;/p&gt;

&lt;p&gt;Now real-world data for different page types, comparing grayscale and color modes:&lt;/p&gt;

&lt;p&gt;Typical PPI values by device, to help understand PPI in real devices:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;DPI&lt;/th&gt;
&lt;th&gt;Pixel Dimensions&lt;/th&gt;
&lt;th&gt;Total Pixels&lt;/th&gt;
&lt;th&gt;Grayscale JPEG&lt;/th&gt;
&lt;th&gt;Color JPEG&lt;/th&gt;
&lt;th&gt;Relative to 150DPI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;72&lt;/td&gt;
&lt;td&gt;595x842&lt;/td&gt;
&lt;td&gt;500K&lt;/td&gt;
&lt;td&gt;0.2MB&lt;/td&gt;
&lt;td&gt;0.5MB&lt;/td&gt;
&lt;td&gt;0.23x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;150&lt;/td&gt;
&lt;td&gt;1240x1754&lt;/td&gt;
&lt;td&gt;2.17M&lt;/td&gt;
&lt;td&gt;0.8MB&lt;/td&gt;
&lt;td&gt;2.1MB&lt;/td&gt;
&lt;td&gt;1x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;1654x2339&lt;/td&gt;
&lt;td&gt;3.87M&lt;/td&gt;
&lt;td&gt;1.4MB&lt;/td&gt;
&lt;td&gt;3.8MB&lt;/td&gt;
&lt;td&gt;1.78x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;300&lt;/td&gt;
&lt;td&gt;2480x3508&lt;/td&gt;
&lt;td&gt;8.70M&lt;/td&gt;
&lt;td&gt;3.2MB&lt;/td&gt;
&lt;td&gt;8.5MB&lt;/td&gt;
&lt;td&gt;4x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;600&lt;/td&gt;
&lt;td&gt;4961x7016&lt;/td&gt;
&lt;td&gt;34.81M&lt;/td&gt;
&lt;td&gt;12.8MB&lt;/td&gt;
&lt;td&gt;34.0MB&lt;/td&gt;
&lt;td&gt;16x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1200&lt;/td&gt;
&lt;td&gt;9922x14032&lt;/td&gt;
&lt;td&gt;139M&lt;/td&gt;
&lt;td&gt;51.2MB&lt;/td&gt;
&lt;td&gt;136.0MB&lt;/td&gt;
&lt;td&gt;64x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  3. Case Study: DPI Selection for an 80-Page Contract Archive
&lt;/h2&gt;

&lt;p&gt;An enterprise needed to scan and archive 80 pages of paper contracts, while also emailing an electronic version. We compared three DPI approaches.&lt;/p&gt;

&lt;p&gt;Document characteristics: 80-page A4 contracts, with handwritten signatures and stamped pages, mostly plain text, no color images. Goal: clear, readable archive + emailable version (25MB limit).&lt;/p&gt;

&lt;p&gt;The final approach was a dual-version strategy: scan at 300DPI grayscale as the master (25.6MB), then use SmartSlim to downsample to 150DPI for the email version (6.4MB). The master was archived to the server, and the email version was sent via enterprise WeChat. The entire process was done locally — contract content was never uploaded to any third-party server, meeting commercial confidentiality requirements.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Document Type&lt;/th&gt;
&lt;th&gt;Pages&lt;/th&gt;
&lt;th&gt;150DPI Grayscale&lt;/th&gt;
&lt;th&gt;300DPI Grayscale&lt;/th&gt;
&lt;th&gt;300DPI Color&lt;/th&gt;
&lt;th&gt;600DPI Grayscale&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Plain-text contract&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;1.8MB&lt;/td&gt;
&lt;td&gt;7.2MB&lt;/td&gt;
&lt;td&gt;19.0MB&lt;/td&gt;
&lt;td&gt;28.8MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mixed text/image report&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;6.5MB&lt;/td&gt;
&lt;td&gt;26.0MB&lt;/td&gt;
&lt;td&gt;68.5MB&lt;/td&gt;
&lt;td&gt;104.0MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Engineering drawing A1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;3.2MB&lt;/td&gt;
&lt;td&gt;12.8MB&lt;/td&gt;
&lt;td&gt;34.0MB&lt;/td&gt;
&lt;td&gt;51.2MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ID card scan&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0.15MB&lt;/td&gt;
&lt;td&gt;0.6MB&lt;/td&gt;
&lt;td&gt;1.6MB&lt;/td&gt;
&lt;td&gt;2.4MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  4. Scenario Recommendations: How to Choose DPI
&lt;/h2&gt;

&lt;p&gt;Different use scenarios have different clarity requirements. The core principle for choosing DPI is "enough is enough" — too high wastes storage and bandwidth, too low affects usability. The table below gives DPI recommendations for common scenarios.&lt;/p&gt;

&lt;p&gt;A practical tip: when SmartSlim processes scanned files, its Rust compression engine automatically analyzes document type — downsampling plain-text pages to 150DPI, keeping image-containing pages at 300DPI, and preserving original DPI for signature/stamp pages. This per-page dispatch strategy works better than uniform DPI reduction, maximizing compression ratio while ensuring clarity.&lt;/p&gt;

&lt;p&gt;For more image compression methods, see Image Compression Guide: JPG/PNG/WebP Format Comparison and PDF Compression Principles and Methods in Depth.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Device Type&lt;/th&gt;
&lt;th&gt;Screen Size&lt;/th&gt;
&lt;th&gt;Resolution&lt;/th&gt;
&lt;th&gt;Typical PPI&lt;/th&gt;
&lt;th&gt;Clarity Assessment&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Phone (flagship)&lt;/td&gt;
&lt;td&gt;6.1 in&lt;/td&gt;
&lt;td&gt;2532x1170&lt;/td&gt;
&lt;td&gt;460PPI&lt;/td&gt;
&lt;td&gt;Retina-level, extremely fine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phone (mid-range)&lt;/td&gt;
&lt;td&gt;6.5 in&lt;/td&gt;
&lt;td&gt;2400x1080&lt;/td&gt;
&lt;td&gt;405PPI&lt;/td&gt;
&lt;td&gt;Clear, sufficient for daily use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tablet&lt;/td&gt;
&lt;td&gt;11 in&lt;/td&gt;
&lt;td&gt;2360x1640&lt;/td&gt;
&lt;td&gt;264PPI&lt;/td&gt;
&lt;td&gt;Clear for document reading&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Laptop&lt;/td&gt;
&lt;td&gt;14 in&lt;/td&gt;
&lt;td&gt;1920x1080&lt;/td&gt;
&lt;td&gt;157PPI&lt;/td&gt;
&lt;td&gt;Office-standard clarity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Monitor&lt;/td&gt;
&lt;td&gt;27 in&lt;/td&gt;
&lt;td&gt;2560x1440&lt;/td&gt;
&lt;td&gt;109PPI&lt;/td&gt;
&lt;td&gt;Mainstream desktop office&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Large monitor&lt;/td&gt;
&lt;td&gt;32 in&lt;/td&gt;
&lt;td&gt;3840x2160&lt;/td&gt;
&lt;td&gt;138PPI&lt;/td&gt;
&lt;td&gt;4K clarity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  5. Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;Q1: What exactly is the difference between DPI and PPI?&lt;/p&gt;

&lt;p&gt;DPI (Dots Per Inch) is a printing/scanning concept — dots per inch printed or scanned, used for physical output devices. PPI (Pixels Per Inch) is a digital image concept — pixels per inch, used for screen display and digital images. The units are the same but the domains differ: scanners use DPI to describe scan precision, monitors use PPI to describe screen clarity. Casual mixing doesn't cause serious misunderstanding, but in professional contexts they must be strictly distinguished.&lt;/p&gt;

&lt;p&gt;Q2: What DPI is best for scanned files?&lt;/p&gt;

&lt;p&gt;Depends on the use. For screen reading and email, 150DPI is sufficient — small size and clearly readable text; for print output, 300DPI ensures print quality; for long-term archiving, 600DPI preserves maximum detail but is larger; for OCR, 300DPI or above gives the highest recognition rate. General advice: 150-200DPI for ordinary documents, 300DPI for important contracts, 600DPI for historical archives.&lt;/p&gt;

&lt;p&gt;Q3: Does higher DPI mean larger file size?&lt;/p&gt;

&lt;p&gt;Yes — DPI and file size have a square relationship. Size is proportional to DPI squared — doubling DPI quadruples size. For example, an A4 page at 150DPI is about 0.8MB, at 300DPI about 3.2MB, at 600DPI about 12.8MB. So when choosing DPI, balance clarity and size — higher is not always better. SmartSlim can automatically recommend the best DPI by use and compress.&lt;/p&gt;

&lt;p&gt;Q4: Does higher PPI mean a clearer screen?&lt;/p&gt;

&lt;p&gt;Within a certain range, yes. Above 300PPI, the human eye can barely distinguish higher pixel density (Apple's Retina standard is 326PPI). But PPI is also affected by screen size, viewing distance, and content type. A phone screen (5-7 inches) at 300PPI is sufficient; a monitor (24-32 inches) at 100-150PPI is fine, because the viewing distance is greater. Blindly chasing high PPI increases GPU load and power consumption, with diminishing returns.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Scan DPI&lt;/th&gt;
&lt;th&gt;Color Mode&lt;/th&gt;
&lt;th&gt;Total Size&lt;/th&gt;
&lt;th&gt;Clarity Assessment&lt;/th&gt;
&lt;th&gt;Applicable Scenario&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Approach A&lt;/td&gt;
&lt;td&gt;150DPI&lt;/td&gt;
&lt;td&gt;Grayscale&lt;/td&gt;
&lt;td&gt;6.4MB&lt;/td&gt;
&lt;td&gt;Clear for screen, slightly blurry for print&lt;/td&gt;
&lt;td&gt;Email&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Approach B&lt;/td&gt;
&lt;td&gt;300DPI&lt;/td&gt;
&lt;td&gt;Grayscale&lt;/td&gt;
&lt;td&gt;25.6MB&lt;/td&gt;
&lt;td&gt;Clear for both screen and print&lt;/td&gt;
&lt;td&gt;Daily archive + print&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Approach C&lt;/td&gt;
&lt;td&gt;600DPI&lt;/td&gt;
&lt;td&gt;Grayscale&lt;/td&gt;
&lt;td&gt;102.4MB&lt;/td&gt;
&lt;td&gt;Perfect detail, zoomable&lt;/td&gt;
&lt;td&gt;Long-term archive&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  6. Summary
&lt;/h2&gt;

&lt;p&gt;Although DPI and PPI share the same unit, they belong to two domains — physical printing and digital display. The core of scanned file compression is choosing the right DPI: 150DPI for screen reading, 300DPI for printing, 600DPI for archiving. Remember the square relationship "doubling DPI quadruples size," and you can find the best balance between clarity and file size.&lt;/p&gt;

&lt;p&gt;Practical advice: determine the use first, then choose DPI — don't blindly chase high resolution. If you already have a high-DPI scan that needs shrinking, use SmartSlim for downsampling compression — built on its self-developed Rust compression engine with per-page intelligent dispatch, supporting 10 categories and 40+ formats including PDF/images/video/Office/OFD, with local compression and data staying on-prem.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Recommended DPI&lt;/th&gt;
&lt;th&gt;Color Mode&lt;/th&gt;
&lt;th&gt;Per-Page Size (A4)&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Screen reading/email&lt;/td&gt;
&lt;td&gt;150DPI&lt;/td&gt;
&lt;td&gt;Grayscale&lt;/td&gt;
&lt;td&gt;0.8MB&lt;/td&gt;
&lt;td&gt;Clearly readable text, small size&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Daily printing&lt;/td&gt;
&lt;td&gt;300DPI&lt;/td&gt;
&lt;td&gt;Grayscale&lt;/td&gt;
&lt;td&gt;3.2MB&lt;/td&gt;
&lt;td&gt;Print quality meets office needs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High-quality printing&lt;/td&gt;
&lt;td&gt;300DPI&lt;/td&gt;
&lt;td&gt;Color&lt;/td&gt;
&lt;td&gt;8.5MB&lt;/td&gt;
&lt;td&gt;Recommended for color documents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long-term archiving&lt;/td&gt;
&lt;td&gt;600DPI&lt;/td&gt;
&lt;td&gt;Grayscale&lt;/td&gt;
&lt;td&gt;12.8MB&lt;/td&gt;
&lt;td&gt;Maximum detail, for important files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OCR&lt;/td&gt;
&lt;td&gt;300DPI&lt;/td&gt;
&lt;td&gt;Grayscale&lt;/td&gt;
&lt;td&gt;3.2MB&lt;/td&gt;
&lt;td&gt;300DPI gives highest recognition (99%+)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Engineering drawings&lt;/td&gt;
&lt;td&gt;400DPI&lt;/td&gt;
&lt;td&gt;Grayscale&lt;/td&gt;
&lt;td&gt;5.7MB&lt;/td&gt;
&lt;td&gt;Line detail needs higher DPI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Photos/albums&lt;/td&gt;
&lt;td&gt;600DPI&lt;/td&gt;
&lt;td&gt;Color&lt;/td&gt;
&lt;td&gt;34.0MB&lt;/td&gt;
&lt;td&gt;Color photos need high DPI for color&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web publishing&lt;/td&gt;
&lt;td&gt;96DPI&lt;/td&gt;
&lt;td&gt;Color&lt;/td&gt;
&lt;td&gt;0.9MB&lt;/td&gt;
&lt;td&gt;Matches screen, fast loading&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;Q: What is the difference between DPI and PPI?&lt;br&gt;
A: DPI (Dots Per Inch) refers to the number of ink dots a printer produces per inch, affecting print quality. PPI (Pixels Per Inch) refers to the number of pixels per inch in a digital image, affecting screen display resolution. In practice, the terms are often used interchangeably, but they describe different domains: DPI for output (print), PPI for input (digital). For scanning, the scanner's DPI setting determines the pixel dimensions of the resulting digital image.&lt;/p&gt;

&lt;p&gt;Q: What DPI should I use for scanning documents?&lt;br&gt;
A: 150 DPI: Suitable for screen reading and email (small file, clear text). 300 DPI: Standard for printing and OCR (good quality, moderate file size). 600 DPI: Recommended for archival and important documents (highest quality, large file). A 100-page document at 150 DPI is about 30MB, at 300 DPI about 120MB, at 600 DPI about 480MB. SmartSlim can compress high-DPI scans to much smaller sizes while maintaining readability.&lt;/p&gt;

&lt;p&gt;Q: How does DPI affect scanned file size?&lt;br&gt;
A: File size increases with the square of DPI. Doubling DPI quadruples the pixel count and file size. For example, an A4 page at 150 DPI (1240x1754 pixels) is about 300KB as JPEG. At 300 DPI (2480x3508 pixels) it's about 1.2MB (4x larger). At 600 DPI (4960x7016 pixels) it's about 4.8MB (16x larger than 150 DPI). SmartSlim allows you to reduce DPI for non-critical documents while maintaining readability.&lt;/p&gt;

&lt;p&gt;Q: Can I change DPI after scanning?&lt;br&gt;
A: Yes, you can downsample (reduce) DPI after scanning, but you cannot increase it without quality loss. Downsampling from 600 DPI to 300 DPI preserves quality. Upsampling from 150 DPI to 300 DPI creates pixelated results. Best practice: scan at a higher DPI for archival, then create lower-DPI copies for distribution. SmartSlim supports batch DPI adjustment for scanned documents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The key to what's the difference between dpi... lies in identifying the sources of bloat and handling them accordingly. Choose the right compression strategy based on your scenario, prioritizing the largest contributors. SmartSlim can handle all compression steps in one click.&lt;/p&gt;

&lt;p&gt;Related:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/scanned-pdf-compression.html" rel="noopener noreferrer"&gt;Scanned PDF Too Large? Downsample DPI + JPEG Conversion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/pdf-font-subsetting-principle.html" rel="noopener noreferrer"&gt;PDF Font Subsetting: Why Can It Reduce Size by 90%?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/tiff-vs-png-scanning.html" rel="noopener noreferrer"&gt;TIFF vs PNG: Which Format for Scanning Documents?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dpivsppi</category>
      <category>scandpi</category>
      <category>unsplash</category>
      <category>imagesharpness</category>
    </item>
    <item>
      <title>Compression Task Queue Design: Celery + Redis Async Processing</title>
      <dc:creator>Uglypear Data</dc:creator>
      <pubDate>Tue, 11 Aug 2026 04:44:16 +0000</pubDate>
      <link>https://dev.to/uglypeardata/compression-task-queue-design-celery-redis-async-processing-nal</link>
      <guid>https://dev.to/uglypeardata/compression-task-queue-design-celery-redis-async-processing-nal</guid>
      <description>&lt;p&gt;Original URL: &lt;a href="https://www.uglypear.com/en/blog/compression-task-queue-design.html" rel="noopener noreferrer"&gt;https://www.uglypear.com/en/blog/compression-task-queue-design.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzeel017r58hbzfgymqbu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzeel017r58hbzfgymqbu.png" alt=" " width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How to process compression tasks asynchronously? This article details Celery + Redis task queue design — task sharding, priority queues, retry mechanisms, and dead letter queues, with a 10,000-file async compression architecture plan and complete Celery configuration examples. Async task queues are essential for handling large-scale batch compression workloads.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Why Compression Tasks Need Async Queues
&lt;/h2&gt;

&lt;p&gt;File compression is a typical CPU-intensive + IO-intensive task. Compressing a 100MB PDF may take 5–15 seconds — if handled with a synchronous interface, the HTTP connection hangs for a long time, and single-machine concurrency is very poor. Async queues decouple "submission" and "execution": the client submits a task and immediately gets a task_id, the Worker compresses in the background, and returns the result via callback or polling when done.&lt;/p&gt;

&lt;p&gt;SmartSlim Network Edition uses a FastAPI + Celery + Redis + MinIO architecture, with 12 concurrent tasks running stably on a single machine. In Kubernetes deployments, HPA can auto-scale between 3–10 replicas. This architecture has supported multiple enterprise customers with daily volumes of tens of thousands of file compression requests.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Processing Method&lt;/th&gt;
&lt;th&gt;Concurrency&lt;/th&gt;
&lt;th&gt;Response Latency&lt;/th&gt;
&lt;th&gt;Failure Handling&lt;/th&gt;
&lt;th&gt;Applicable Scale&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Synchronous processing&lt;/td&gt;
&lt;td&gt;Poor (blocks HTTP connections)&lt;/td&gt;
&lt;td&gt;5–60s&lt;/td&gt;
&lt;td&gt;No retry, direct error&lt;/td&gt;
&lt;td&gt;&amp;lt;10 files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thread pool&lt;/td&gt;
&lt;td&gt;Medium (limited by thread count)&lt;/td&gt;
&lt;td&gt;1–5s&lt;/td&gt;
&lt;td&gt;Manual implementation needed&lt;/td&gt;
&lt;td&gt;10–100 files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Celery async queue&lt;/td&gt;
&lt;td&gt;High (Worker horizontal scaling)&lt;/td&gt;
&lt;td&gt;&amp;lt;200ms&lt;/td&gt;
&lt;td&gt;Auto retry + dead letter queue&lt;/td&gt;
&lt;td&gt;100–100000 files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kubernetes + queue&lt;/td&gt;
&lt;td&gt;Very high (HPA elastic scaling)&lt;/td&gt;
&lt;td&gt;&amp;lt;100ms&lt;/td&gt;
&lt;td&gt;Complete fault tolerance system&lt;/td&gt;
&lt;td&gt;&amp;gt;100000 files&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  2. Celery Task Queue Architecture Explained
&lt;/h2&gt;

&lt;p&gt;The Celery task queue consists of four core roles: Producer, Broker, Worker, and Backend. Understanding the responsibilities of these four layers is essential for correctly configuring a compression task queue.&lt;/p&gt;

&lt;p&gt;Celery's configuration directly determines the queue's throughput and stability. The table below shows recommended configurations for compression scenarios, verified in SmartSlim's production environment.&lt;/p&gt;

&lt;p&gt;Compression tasks have different priorities: user real-time compression requests need fast response, while scheduled archiving tasks can run slowly. Use Redis priority queues for differentiated scheduling — high-priority tasks are consumed by Workers first.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Technology Choice&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;th&gt;Key Configuration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Producer&lt;/td&gt;
&lt;td&gt;FastAPI&lt;/td&gt;
&lt;td&gt;Receives HTTP requests, constructs tasks, delivers to Broker&lt;/td&gt;
&lt;td&gt;task.apply_async(queue=...)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Broker&lt;/td&gt;
&lt;td&gt;Redis 7.x&lt;/td&gt;
&lt;td&gt;Stores pending task messages, supports priority queues&lt;/td&gt;
&lt;td&gt;broker_url, visibility_timeout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Worker&lt;/td&gt;
&lt;td&gt;Celery 5.x&lt;/td&gt;
&lt;td&gt;Consumes tasks, calls Rust compression engine to execute compression&lt;/td&gt;
&lt;td&gt;concurrency, prefork pool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;Redis&lt;/td&gt;
&lt;td&gt;Stores task status and return results&lt;/td&gt;
&lt;td&gt;result_backend, result_expires&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage Layer&lt;/td&gt;
&lt;td&gt;MinIO&lt;/td&gt;
&lt;td&gt;Stores original files and compressed files&lt;/td&gt;
&lt;td&gt;S3-compatible protocol, multipart upload&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  3. Practical Case: 10000 Files Async Compression
&lt;/h2&gt;

&lt;p&gt;This is an enterprise data archiving scenario: 10000 historical documents (mixed PDF/Word/images, average 8MB per file, total about 80GB) need unified compression and archiving. Requirement: complete within 1 hour, compression ratio no less than 60%.&lt;/p&gt;

&lt;p&gt;Solution design: Split into 100 subtasks by 100 files per shard, batch submit using Celery group, with 12 Workers consuming concurrently. Each subtask serially calls the Rust compression engine to compress 100 files.&lt;/p&gt;

&lt;p&gt;Result: Completed 10000 file compression in 44 minutes, compression ratio 67.3%, 17 corrupted files automatically entered the dead letter queue for manual handling. The overall architecture was stable, with peak CPU utilization of 89%, peak memory usage of 4.2GB, and no OOM or task loss.&lt;/p&gt;

&lt;p&gt;Compression task failures fall into two categories: temporary errors (IO timeout, insufficient memory, excessive concurrency) and deterministic errors (file corruption, unsupported format). Temporary errors have a high probability of success on retry, while deterministic errors are meaningless to retry. The table below provides retry and dead letter decision strategies.&lt;/p&gt;

&lt;p&gt;Retry configuration uses Celery's autoretry_for and retry_backoff, with initial backoff of 60 seconds, maximum 600 seconds, and random jitter to avoid avalanches. Tasks in the dead letter queue are periodically scanned by an independent monitoring task, triggering WeChat Work/DingTalk alerts to notify operations for handling.&lt;/p&gt;

&lt;p&gt;For the complete compression API calling method, refer to Compression API Guide: REST Interface Design.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Recommended Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;broker_url&lt;/td&gt;
&lt;td&gt;redis://:password@redis:6379/0&lt;/td&gt;
&lt;td&gt;Redis as message broker, independent DB to avoid conflicts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;result_backend&lt;/td&gt;
&lt;td&gt;redis://:password@redis:6379/1&lt;/td&gt;
&lt;td&gt;Result storage uses independent DB, isolated from Broker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;task_serializer&lt;/td&gt;
&lt;td&gt;json&lt;/td&gt;
&lt;td&gt;JSON serialization, cross-language compatible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;result_serializer&lt;/td&gt;
&lt;td&gt;json&lt;/td&gt;
&lt;td&gt;Results also use JSON&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;accept_content&lt;/td&gt;
&lt;td&gt;['json']&lt;/td&gt;
&lt;td&gt;Only accept JSON, security hardening&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;timezone&lt;/td&gt;
&lt;td&gt;Asia/Shanghai&lt;/td&gt;
&lt;td&gt;Unified timezone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;task_acks_late&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;ACK only after task completion, no task loss on crash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;worker_prefetch_multiplier&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Each Worker prefetches only 1 task, avoiding long task starvation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;task_time_limit&lt;/td&gt;
&lt;td&gt;600&lt;/td&gt;
&lt;td&gt;Hard timeout 600s per task&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;task_soft_time_limit&lt;/td&gt;
&lt;td&gt;540&lt;/td&gt;
&lt;td&gt;Soft timeout 540s, triggers SoftTimeLimitExceeded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;task_reject_on_worker_lost&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;Reject task on Worker abnormal exit, re-queue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;result_expires&lt;/td&gt;
&lt;td&gt;86400&lt;/td&gt;
&lt;td&gt;Results auto-cleaned after 24 hours&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  4. Queue Configuration Recommendations for Different Scenarios
&lt;/h2&gt;

&lt;p&gt;Different business scenarios have different requirements for throughput, latency, and reliability, requiring differentiated queue configurations. The table below provides recommended configurations for common scenarios.&lt;/p&gt;

&lt;p&gt;A general principle: real-time scenarios use high-priority queues + small shards + fast retry, batch scenarios use normal queues + large shards + exponential backoff, and classified scenarios use strict auditing + small shards + multi-level retry. For the complete enterprise batch compression solution, refer to Enterprise Batch Compression Solution: 10000 File Processing in Practice.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Queue Name&lt;/th&gt;
&lt;th&gt;Priority&lt;/th&gt;
&lt;th&gt;Routing Rule&lt;/th&gt;
&lt;th&gt;Typical Tasks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;compression_high&lt;/td&gt;
&lt;td&gt;9 (highest)&lt;/td&gt;
&lt;td&gt;User real-time requests&lt;/td&gt;
&lt;td&gt;Single file instant compression&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;compression_normal&lt;/td&gt;
&lt;td&gt;5 (default)&lt;/td&gt;
&lt;td&gt;Batch tasks&lt;/td&gt;
&lt;td&gt;Batch compression 100–500 files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;compression_low&lt;/td&gt;
&lt;td&gt;1 (lowest)&lt;/td&gt;
&lt;td&gt;Scheduled archiving&lt;/td&gt;
&lt;td&gt;Nightly full archive compression&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dlq_queue&lt;/td&gt;
&lt;td&gt;— (dead letter)&lt;/td&gt;
&lt;td&gt;Tasks that failed retry&lt;/td&gt;
&lt;td&gt;Manual investigation or compensation handling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  5. Frequently Asked Questions (FAQ)
&lt;/h2&gt;

&lt;p&gt;Q1: How to implement async processing for Celery compression tasks?&lt;/p&gt;

&lt;p&gt;Use Celery + Redis to build an async task queue: FastAPI receives requests and delivers tasks to the Redis Broker, Celery Workers consume tasks from the Broker and call the Rust compression engine to execute compression, writing results to Backend and MinIO storage. A single task.apply_async executes asynchronously, and status is polled via task.id. With 12 Workers concurrent on a single machine, 10000 files sharded into 100 batches can complete in 40 minutes.&lt;/p&gt;

&lt;p&gt;Q2: How to auto-retry failed compression tasks?&lt;/p&gt;

&lt;p&gt;Use Celery's autoretry_for parameter to configure auto-retry, setting max_retries=3, retry_backoff=True (exponential backoff, initial 60 seconds), retry_backoff_max=600 seconds, retry_jitter=True (random jitter to avoid avalanches). Tasks that still fail after 3 retries are automatically routed to the dead letter queue dlq_queue for manual or compensation task handling. It's recommended to retry temporary errors (IO timeout/insufficient memory) and send deterministic errors (file corruption/unsupported format) directly to dead letter.&lt;/p&gt;

&lt;p&gt;Q3: How to shard 10000 files for batch compression?&lt;/p&gt;

&lt;p&gt;Shard by 100 files per shard, totaling 100 subtasks. Batch submit using Celery group or chord, with 12 Workers consuming in parallel, each subtask serially compressing 100 files. Average compression time per file is 3 seconds, about 5 minutes per shard, and 100 shards in parallel complete in about 40 minutes overall. Too small a shard size (e.g., 1 per shard) has high scheduling overhead, too large (e.g., 1000 per shard) has high retry cost on failure — 100 is the empirical optimal value.&lt;/p&gt;

&lt;p&gt;Q4: Which is more suitable for compression task queues — Celery or RQ?&lt;/p&gt;

&lt;p&gt;Celery is recommended for compression tasks. Celery supports task sharding (group/chord), priority queues, scheduled tasks, task chains, and dead letter queues — complete functionality; RQ is lighter but lacks sharding and priority. Compression scenarios commonly require batch sharding, priority scheduling, and failure retry, all natively supported by Celery. Performance-wise, both are based on Redis with comparable throughput. SmartSlim Network Edition uses a FastAPI + Celery + Redis + MinIO architecture, running stably with 12 concurrent tasks on a single machine.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Measured Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Total files&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;Mixed formats, average 8MB each&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shard granularity&lt;/td&gt;
&lt;td&gt;100 files/shard&lt;/td&gt;
&lt;td&gt;100 shard subtasks&lt;/td&gt;
&lt;td&gt;Balance scheduling overhead and retry cost&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Worker concurrency&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;prefork mode&lt;/td&gt;
&lt;td&gt;Single machine 12-core CPU&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Single file compression time&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;Average 3.2s&lt;/td&gt;
&lt;td&gt;Rust engine medium level&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Single shard time&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;About 5.3 min&lt;/td&gt;
&lt;td&gt;100 files serial&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Overall time&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;About 44 min&lt;/td&gt;
&lt;td&gt;100 shards/12 concurrent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compression ratio&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;67.3%&lt;/td&gt;
&lt;td&gt;80GB→26.2GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failures&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;File corruption, entered dead letter after retry&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  6. Summary
&lt;/h2&gt;

&lt;p&gt;The standard solution for compression task async processing is the Celery + Redis task queue, with the core being the four-layer decoupling of Producer/Broker/Worker/Backend. For 10000-file batch compression, sharding by 100 files with 12 Workers concurrent, completion in about 40 minutes, compression ratio 60%–70%. Retry strategies should distinguish temporary errors (exponential backoff retry) from deterministic errors (direct to dead letter), combined with 6 monitoring metrics to ensure queue stability.&lt;/p&gt;

&lt;p&gt;Remember three points: first, task_acks_late=True ensures no task loss on crash; second, worker_prefetch_multiplier=1 avoids long task starvation; third, the dead letter queue must be configured with monitoring alerts. Choose the right queue architecture and sharding strategy, and both throughput and stability of the compression service can reach a new level.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error Type&lt;/th&gt;
&lt;th&gt;Typical Exception&lt;/th&gt;
&lt;th&gt;Handling Strategy&lt;/th&gt;
&lt;th&gt;Retry Count&lt;/th&gt;
&lt;th&gt;Final Destination&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Temporary-IO&lt;/td&gt;
&lt;td&gt;ConnectionError, TimeoutError&lt;/td&gt;
&lt;td&gt;Exponential backoff retry&lt;/td&gt;
&lt;td&gt;3 times&lt;/td&gt;
&lt;td&gt;Success or dead letter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Temporary-Resource&lt;/td&gt;
&lt;td&gt;MemoryError, OOMKilled&lt;/td&gt;
&lt;td&gt;Extended backoff + downgrade&lt;/td&gt;
&lt;td&gt;2 times&lt;/td&gt;
&lt;td&gt;Success or dead letter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deterministic-File&lt;/td&gt;
&lt;td&gt;FileCorrupted, ParseError&lt;/td&gt;
&lt;td&gt;No retry, direct dead letter&lt;/td&gt;
&lt;td&gt;0 times&lt;/td&gt;
&lt;td&gt;dlq_queue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deterministic-Format&lt;/td&gt;
&lt;td&gt;UnsupportedFormat&lt;/td&gt;
&lt;td&gt;No retry, direct dead letter&lt;/td&gt;
&lt;td&gt;0 times&lt;/td&gt;
&lt;td&gt;dlq_queue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deterministic-Permission&lt;/td&gt;
&lt;td&gt;PermissionDenied&lt;/td&gt;
&lt;td&gt;No retry, alert&lt;/td&gt;
&lt;td&gt;0 times&lt;/td&gt;
&lt;td&gt;dlq_queue + alert&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Monitoring Metric&lt;/th&gt;
&lt;th&gt;Collection Method&lt;/th&gt;
&lt;th&gt;Alert Threshold&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Queue backlog&lt;/td&gt;
&lt;td&gt;Redis LLEN&lt;/td&gt;
&lt;td&gt;&amp;gt;500&lt;/td&gt;
&lt;td&gt;Trigger Worker scaling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Task failure rate&lt;/td&gt;
&lt;td&gt;Celery events&lt;/td&gt;
&lt;td&gt;&amp;gt;5%&lt;/td&gt;
&lt;td&gt;Investigate logs + pause submission&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dead letter queue length&lt;/td&gt;
&lt;td&gt;Redis LLEN dlq&lt;/td&gt;
&lt;td&gt;&amp;gt;10&lt;/td&gt;
&lt;td&gt;WeChat Work alert&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Worker alive count&lt;/td&gt;
&lt;td&gt;Celery inspect&lt;/td&gt;
&lt;td&gt;&amp;lt;10&lt;/td&gt;
&lt;td&gt;Auto-restart Worker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Average task duration&lt;/td&gt;
&lt;td&gt;Flower monitoring&lt;/td&gt;
&lt;td&gt;&amp;gt;30s&lt;/td&gt;
&lt;td&gt;Check large files + downgrade&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU utilization&lt;/td&gt;
&lt;td&gt;node_exporter&lt;/td&gt;
&lt;td&gt;&amp;gt;95%&lt;/td&gt;
&lt;td&gt;Throttle + scale&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Worker Count&lt;/th&gt;
&lt;th&gt;Shard Granularity&lt;/th&gt;
&lt;th&gt;Priority Queue&lt;/th&gt;
&lt;th&gt;Retry Strategy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Personal instant compression&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;No sharding&lt;/td&gt;
&lt;td&gt;high&lt;/td&gt;
&lt;td&gt;Fast retry 3 times&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enterprise batch archiving&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;100 files/shard&lt;/td&gt;
&lt;td&gt;normal/low&lt;/td&gt;
&lt;td&gt;Exponential backoff 3 times&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Government classified processing&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;50 files/shard&lt;/td&gt;
&lt;td&gt;high&lt;/td&gt;
&lt;td&gt;Strict retry + audit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E-commerce platform images&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;200 files/shard&lt;/td&gt;
&lt;td&gt;normal&lt;/td&gt;
&lt;td&gt;Fast retry 2 times&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nightly scheduled archiving&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;500 files/shard&lt;/td&gt;
&lt;td&gt;low&lt;/td&gt;
&lt;td&gt;Slow backoff 5 times&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real-time video transcoding&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;Single file&lt;/td&gt;
&lt;td&gt;high&lt;/td&gt;
&lt;td&gt;No retry, alert on failure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;Q: How to design a Celery-based compression task queue?&lt;br&gt;
A: Architecture: 1) Celery workers — consume compression tasks from Redis/RabbitMQ. 2) Task definitions — each compression job is a Celery task with retry logic. 3) Result backend — store task results in Redis or database. 4) Monitoring — use Flower for real-time worker monitoring. SmartSlim provides a reference Celery configuration with task routing, rate limiting, and priority queues.&lt;/p&gt;

&lt;p&gt;Q: How to implement task sharding for large batches?&lt;br&gt;
A: Task sharding splits a large batch into smaller chunks for parallel processing: 1) Group tasks into chunks of 50-100 files. 2) Submit each chunk as a separate Celery task. 3) Use Celery groups to track completion of all chunks. 4) Implement a chord callback for post-processing. SmartSlim's sharding implementation scales linearly with worker count, processing 10,000 files in ~30 minutes with 8 workers.&lt;/p&gt;

&lt;p&gt;Q: How to handle failed compression tasks?&lt;br&gt;
A: Failure handling strategy: 1) Automatic retry — Celery's task.retry() with exponential backoff (retry 3 times, delays: 60s, 300s, 900s). 2) Max retries exceeded — move to dead letter queue. 3) Dead letter processing — log failure details, notify admin, store for manual review. 4) Partial success — complete remaining tasks, report failures in final summary. SmartSlim's Celery configuration includes comprehensive failure handling.&lt;/p&gt;

&lt;p&gt;Q: What monitoring and alerting should be set up?&lt;br&gt;
A: Monitoring stack: 1) Celery monitoring — Flower dashboard for worker status and task queues. 2) Application metrics — Prometheus metrics for task throughput, success rate, processing time. 3) Log aggregation — ELK stack (Elasticsearch, Logstash, Kibana) for compression logs. 4) Alerting — Grafana alerts for queue depth &amp;gt; 1000, failure rate &amp;gt; 5%, worker downtime. SmartSlim provides a complete monitoring configuration with pre-built Grafana dashboards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The key to compression task queue design: celery... lies in identifying the sources of bloat and handling them accordingly. Choose the right compression strategy based on your scenario, prioritizing the largest contributors. SmartSlim can handle all compression steps in one click.&lt;/p&gt;

&lt;p&gt;Related:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/docker-compression-service-deploy.html" rel="noopener noreferrer"&gt;Deploy Compression Service with Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/compression-api-guide.html" rel="noopener noreferrer"&gt;Compression API Guide: RESTful Interface Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/enterprise-batch-compression.html" rel="noopener noreferrer"&gt;Enterprise Batch Compression: How to Process 10,000 Files&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>compression</category>
      <category>tutorial</category>
      <category>productivity</category>
      <category>ai</category>
    </item>
    <item>
      <title>Top 10 Best PDF Compression Tools in 2026 (Including Free)</title>
      <dc:creator>Uglypear Data</dc:creator>
      <pubDate>Mon, 10 Aug 2026 06:07:29 +0000</pubDate>
      <link>https://dev.to/uglypeardata/top-10-best-pdf-compression-tools-in-2026-including-free-1amo</link>
      <guid>https://dev.to/uglypeardata/top-10-best-pdf-compression-tools-in-2026-including-free-1amo</guid>
      <description>&lt;h1&gt;
  
  
  Top 10 Best PDF Compression Tools in 2026 (Including Free)
&lt;/h1&gt;

&lt;p&gt;Original URL: &lt;a href="https://www.uglypear.com/en/blog/best-pdf-compression-tools-2026.html" rel="noopener noreferrer"&gt;https://www.uglypear.com/en/blog/best-pdf-compression-tools-2026.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What are the best PDF compression tools in 2026? This article reviews 10 PDF compression tools — including SmartSlim, Adobe Acrobat, and ILovePDF — scoring them across 5 dimensions: compression ratio, quality retention, batch processing, security, and price. Whether you need desktop software, online service, or enterprise solution, this comprehensive comparison helps you make the right choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Overview of 10 PDF Compression Tools
&lt;/h2&gt;

&lt;p&gt;PDF compression tools on the market fall into four categories: desktop software, online tools, enterprise solutions, and open-source CLI tools. We selected 10 representative products for cross-review, covering free and paid, local and online, personal and enterprise scenarios.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Tool Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Execution&lt;/th&gt;
&lt;th&gt;Free?&lt;/th&gt;
&lt;th&gt;Target User&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;SmartSlim&lt;/td&gt;
&lt;td&gt;Desktop software&lt;/td&gt;
&lt;td&gt;Local compression&lt;/td&gt;
&lt;td&gt;Free + paid&lt;/td&gt;
&lt;td&gt;Personal/Enterprise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Adobe Acrobat Pro&lt;/td&gt;
&lt;td&gt;Desktop software&lt;/td&gt;
&lt;td&gt;Local compression&lt;/td&gt;
&lt;td&gt;Paid (subscription)&lt;/td&gt;
&lt;td&gt;Professional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;ILovePDF&lt;/td&gt;
&lt;td&gt;Online tool&lt;/td&gt;
&lt;td&gt;Cloud upload&lt;/td&gt;
&lt;td&gt;Free (limited) + paid&lt;/td&gt;
&lt;td&gt;Personal occasional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Smallpdf&lt;/td&gt;
&lt;td&gt;Online tool&lt;/td&gt;
&lt;td&gt;Cloud upload&lt;/td&gt;
&lt;td&gt;Free (2/day) + paid&lt;/td&gt;
&lt;td&gt;Personal occasional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Compress PDF (online)&lt;/td&gt;
&lt;td&gt;Online tool&lt;/td&gt;
&lt;td&gt;Cloud upload&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Personal occasional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Nitro PDF Pro&lt;/td&gt;
&lt;td&gt;Desktop software&lt;/td&gt;
&lt;td&gt;Local compression&lt;/td&gt;
&lt;td&gt;Paid (one-time)&lt;/td&gt;
&lt;td&gt;Enterprise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Foxit PDF Editor&lt;/td&gt;
&lt;td&gt;Desktop software&lt;/td&gt;
&lt;td&gt;Local compression&lt;/td&gt;
&lt;td&gt;Paid (subscription)&lt;/td&gt;
&lt;td&gt;Enterprise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Wondershare PDFelement&lt;/td&gt;
&lt;td&gt;Desktop software&lt;/td&gt;
&lt;td&gt;Local compression&lt;/td&gt;
&lt;td&gt;Paid (one-time + sub)&lt;/td&gt;
&lt;td&gt;SMB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;PDF24 Creator&lt;/td&gt;
&lt;td&gt;Desktop software&lt;/td&gt;
&lt;td&gt;Local compression&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Personal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Ghostscript&lt;/td&gt;
&lt;td&gt;CLI tool&lt;/td&gt;
&lt;td&gt;Local compression&lt;/td&gt;
&lt;td&gt;Free open source&lt;/td&gt;
&lt;td&gt;Developer&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  2. 5-Dimension Score Comparison
&lt;/h2&gt;

&lt;p&gt;We scored the 10 tools across 5 dimensions — compression ratio, quality retention, batch processing, security, and price (5-point scale) — each backed by test data.&lt;/p&gt;

&lt;p&gt;Scoring basis: compression ratio based on tested ratio (SmartSlim 92.5% highest); quality retention based on text and image clarity after compression; batch processing based on multi-file simultaneous support; security based on local processing (online tools lose points for requiring file upload); price based on free quota and paid price.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Compression Ratio&lt;/th&gt;
&lt;th&gt;Quality Retention&lt;/th&gt;
&lt;th&gt;Batch Processing&lt;/th&gt;
&lt;th&gt;Security&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Overall&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SmartSlim&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;td&gt;24/25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adobe Acrobat Pro&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;td&gt;20/25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ILovePDF&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;15/25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Smallpdf&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;td&gt;★☆☆☆☆&lt;/td&gt;
&lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;td&gt;12/25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compress PDF&lt;/td&gt;
&lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;td&gt;★☆☆☆☆&lt;/td&gt;
&lt;td&gt;★☆☆☆☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;9/25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nitro PDF Pro&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;td&gt;20/25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Foxit PDF Editor&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;td&gt;20/25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wondershare PDFelement&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;td&gt;17/25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PDF24 Creator&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;18/25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ghostscript&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;21/25&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  3. Test Data: Same PDF File Compression Comparison
&lt;/h2&gt;

&lt;p&gt;We tested all 10 tools with the same test PDF (80MB, 120 pages, with HD images and scanned pages), comparing compressed size and duration.&lt;/p&gt;

&lt;p&gt;Test conclusion: SmartSlim has the highest compression ratio (92.5%), 80MB down to 6MB; Ghostscript is second (86.9%) but requires CLI operation; Adobe Acrobat's 85% ratio preserves quality best. Online tools generally have lower ratios (65%–77%) and require file upload and waiting, with durations 3–5x local tools.&lt;/p&gt;

&lt;p&gt;Platform compatibility and feature coverage comparison:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Original Size&lt;/th&gt;
&lt;th&gt;Compressed&lt;/th&gt;
&lt;th&gt;Ratio&lt;/th&gt;
&lt;th&gt;Quality Assessment&lt;/th&gt;
&lt;th&gt;Duration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SmartSlim&lt;/td&gt;
&lt;td&gt;80.0MB&lt;/td&gt;
&lt;td&gt;6.0MB&lt;/td&gt;
&lt;td&gt;92.5%&lt;/td&gt;
&lt;td&gt;Text clear, images slightly reduced&lt;/td&gt;
&lt;td&gt;8 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adobe Acrobat Pro&lt;/td&gt;
&lt;td&gt;80.0MB&lt;/td&gt;
&lt;td&gt;12.0MB&lt;/td&gt;
&lt;td&gt;85.0%&lt;/td&gt;
&lt;td&gt;Text clear, images intact&lt;/td&gt;
&lt;td&gt;15 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ILovePDF (high compression)&lt;/td&gt;
&lt;td&gt;80.0MB&lt;/td&gt;
&lt;td&gt;18.5MB&lt;/td&gt;
&lt;td&gt;76.9%&lt;/td&gt;
&lt;td&gt;Visible image blur&lt;/td&gt;
&lt;td&gt;45 s (incl. upload)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Smallpdf&lt;/td&gt;
&lt;td&gt;80.0MB&lt;/td&gt;
&lt;td&gt;22.0MB&lt;/td&gt;
&lt;td&gt;72.5%&lt;/td&gt;
&lt;td&gt;Obvious image blur&lt;/td&gt;
&lt;td&gt;60 s (incl. upload)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compress PDF&lt;/td&gt;
&lt;td&gt;80.0MB&lt;/td&gt;
&lt;td&gt;28.0MB&lt;/td&gt;
&lt;td&gt;65.0%&lt;/td&gt;
&lt;td&gt;Weak compression&lt;/td&gt;
&lt;td&gt;30 s (incl. upload)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nitro PDF Pro&lt;/td&gt;
&lt;td&gt;80.0MB&lt;/td&gt;
&lt;td&gt;13.5MB&lt;/td&gt;
&lt;td&gt;83.1%&lt;/td&gt;
&lt;td&gt;Good quality retention&lt;/td&gt;
&lt;td&gt;18 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Foxit PDF Editor&lt;/td&gt;
&lt;td&gt;80.0MB&lt;/td&gt;
&lt;td&gt;14.2MB&lt;/td&gt;
&lt;td&gt;82.3%&lt;/td&gt;
&lt;td&gt;Good quality retention&lt;/td&gt;
&lt;td&gt;20 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wondershare PDFelement&lt;/td&gt;
&lt;td&gt;80.0MB&lt;/td&gt;
&lt;td&gt;16.8MB&lt;/td&gt;
&lt;td&gt;79.0%&lt;/td&gt;
&lt;td&gt;Medium quality&lt;/td&gt;
&lt;td&gt;22 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PDF24 Creator&lt;/td&gt;
&lt;td&gt;80.0MB&lt;/td&gt;
&lt;td&gt;20.5MB&lt;/td&gt;
&lt;td&gt;74.4%&lt;/td&gt;
&lt;td&gt;Medium quality&lt;/td&gt;
&lt;td&gt;12 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ghostscript&lt;/td&gt;
&lt;td&gt;80.0MB&lt;/td&gt;
&lt;td&gt;10.5MB&lt;/td&gt;
&lt;td&gt;86.9%&lt;/td&gt;
&lt;td&gt;Text clear, image loss&lt;/td&gt;
&lt;td&gt;6 s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  4. Free vs Paid Comparison
&lt;/h2&gt;

&lt;p&gt;Many users wonder whether free tools are sufficient. We compared each tool's free quota and paid price.&lt;/p&gt;

&lt;p&gt;SmartSlim Free offers 10 times/day, 10MB per file — fully sufficient for personal daily office use. The annual paid plan is only 98 yuan (unlimited, 1GB per file), far better value than Adobe Acrobat's 1580 yuan/year.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Windows&lt;/th&gt;
&lt;th&gt;macOS&lt;/th&gt;
&lt;th&gt;Linux&lt;/th&gt;
&lt;th&gt;Xinchuang Compatible&lt;/th&gt;
&lt;th&gt;API/SDK&lt;/th&gt;
&lt;th&gt;Batch Processing&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SmartSlim&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes (Kylin/UOS)&lt;/td&gt;
&lt;td&gt;Yes (C ABI)&lt;/td&gt;
&lt;td&gt;Yes (drag-drop/API)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adobe Acrobat Pro&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Limited (JS API)&lt;/td&gt;
&lt;td&gt;Yes (limited)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ILovePDF&lt;/td&gt;
&lt;td&gt;Web&lt;/td&gt;
&lt;td&gt;Web&lt;/td&gt;
&lt;td&gt;Web&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (REST API)&lt;/td&gt;
&lt;td&gt;Paid edition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Smallpdf&lt;/td&gt;
&lt;td&gt;Web&lt;/td&gt;
&lt;td&gt;Web&lt;/td&gt;
&lt;td&gt;Web&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nitro PDF Pro&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Foxit PDF Editor&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PDF24 Creator&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ghostscript&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes (CLI)&lt;/td&gt;
&lt;td&gt;Yes (script)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  5. Scenario Recommendations: Different Needs, Different Tools
&lt;/h2&gt;

&lt;p&gt;Different user scenarios emphasize different needs — the table below gives targeted recommendations.&lt;/p&gt;

&lt;p&gt;Core principle for choosing a tool: classified documents must be compressed locally (online tools prohibited); enterprise batch uses API; personal daily use, the free edition suffices; developers choose SDK or CLI tools. For more selection dimensions, see File Compression Tool Selection Guide: 7 Evaluation Dimensions and Free Compression Software Review.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Free Quota&lt;/th&gt;
&lt;th&gt;Paid Price&lt;/th&gt;
&lt;th&gt;Free Edition Limits&lt;/th&gt;
&lt;th&gt;Value Assessment&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SmartSlim&lt;/td&gt;
&lt;td&gt;Images 5MB / docs 10MB, 10/day&lt;/td&gt;
&lt;td&gt;Monthly 9.9 yuan / annual 98 yuan&lt;/td&gt;
&lt;td&gt;Single-file size limit&lt;/td&gt;
&lt;td&gt;★★★★★ Free enough for daily use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adobe Acrobat Pro&lt;/td&gt;
&lt;td&gt;7-day trial&lt;/td&gt;
&lt;td&gt;Annual sub ~1580 yuan&lt;/td&gt;
&lt;td&gt;Unusable after trial&lt;/td&gt;
&lt;td&gt;★★☆☆☆ Pricey&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ILovePDF&lt;/td&gt;
&lt;td&gt;2/day, 10MB per file&lt;/td&gt;
&lt;td&gt;~50 yuan/month, ~400 yuan/year&lt;/td&gt;
&lt;td&gt;Count and size limits&lt;/td&gt;
&lt;td&gt;★★★☆☆ Enough occasionally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Smallpdf&lt;/td&gt;
&lt;td&gt;2/day, 5MB per file&lt;/td&gt;
&lt;td&gt;~75 yuan/month, ~600 yuan/year&lt;/td&gt;
&lt;td&gt;Many limits&lt;/td&gt;
&lt;td&gt;★★☆☆☆ Free too little&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nitro PDF Pro&lt;/td&gt;
&lt;td&gt;14-day trial&lt;/td&gt;
&lt;td&gt;One-time ~1200 yuan&lt;/td&gt;
&lt;td&gt;Trial watermark&lt;/td&gt;
&lt;td&gt;★★★☆☆ One-time payment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Foxit PDF Editor&lt;/td&gt;
&lt;td&gt;14-day trial&lt;/td&gt;
&lt;td&gt;Annual sub ~980 yuan&lt;/td&gt;
&lt;td&gt;Trial watermark&lt;/td&gt;
&lt;td&gt;★★★☆☆ Enterprise common&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PDF24 Creator&lt;/td&gt;
&lt;td&gt;Fully free&lt;/td&gt;
&lt;td&gt;No payment&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;td&gt;★★★★☆ Free top pick&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ghostscript&lt;/td&gt;
&lt;td&gt;Fully free open source&lt;/td&gt;
&lt;td&gt;No payment&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;td&gt;★★★★☆ Technical user top pick&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  6. Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;Q1: Which PDF compression tool has the highest ratio?&lt;/p&gt;

&lt;p&gt;SmartSlim has the highest compression ratio — tested 80MB scanned file compressed to 6MB, a 92.5% ratio. Based on its self-developed Rust compression engine, it automatically identifies PDF content type (text/image/scanned) and dispatches the optimal strategy — image downsampling + format conversion, font subsetting, redundancy cleanup — three steps stacked for deep compression. Adobe Acrobat is second (~85% ratio), Ghostscript third (~80%).&lt;/p&gt;

&lt;p&gt;Q2: What free PDF compression tools do you recommend?&lt;/p&gt;

&lt;p&gt;Three free recommendations: SmartSlim Free (images 5MB / docs 10MB, 10/day, local compression with privacy security); ILovePDF online (2 free/day, requires file upload); Ghostscript CLI (fully free open source, but requires technical background). For occasional personal use, SmartSlim Free is recommended — data stays on-prem, most secure; for frequent use, upgrade to a paid edition.&lt;/p&gt;

&lt;p&gt;Q3: Online PDF compression vs local compression — which is better?&lt;/p&gt;

&lt;p&gt;Documents involving sensitive information must use local compression. Online compression requires uploading files to third-party servers, posing data leakage risk — unsuitable for contracts, financial reports, and other classified documents. Local compression (e.g., SmartSlim Desktop) performs all processing on the local machine — data never leaves. Online compression's advantage is no installation and cross-platform, suited for temporary compression of non-sensitive documents.&lt;/p&gt;

&lt;p&gt;Q4: What tool for enterprise batch PDF compression?&lt;/p&gt;

&lt;p&gt;For enterprises, SmartSlim Server or Network edition is recommended. The Server edition supports single-machine deployment, with API-based automated batch compression, 12 concurrent tasks, daily processing of tens of thousands of documents. The Network edition supports Docker/K8s distributed deployment, 10GB per file, suited for large-scale document archiving. Both support Xinchuang environments (Kylin OS/DM database), with privatized data staying on-prem.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Core Need&lt;/th&gt;
&lt;th&gt;Recommended Tool&lt;/th&gt;
&lt;th&gt;Rationale&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Personal daily office&lt;/td&gt;
&lt;td&gt;Free, easy, local compression&lt;/td&gt;
&lt;td&gt;SmartSlim Free&lt;/td&gt;
&lt;td&gt;10 free/day, drag-and-drop, data stays on-prem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Classified document compression&lt;/td&gt;
&lt;td&gt;Absolute security, local processing&lt;/td&gt;
&lt;td&gt;SmartSlim Desktop&lt;/td&gt;
&lt;td&gt;Local compression, 5-level security&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enterprise batch archiving&lt;/td&gt;
&lt;td&gt;API automation, high concurrency&lt;/td&gt;
&lt;td&gt;SmartSlim Server&lt;/td&gt;
&lt;td&gt;12 concurrent, API integration, 10k/day&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Professional PDF editing&lt;/td&gt;
&lt;td&gt;Edit + compress integrated&lt;/td&gt;
&lt;td&gt;Adobe Acrobat Pro&lt;/td&gt;
&lt;td&gt;Most feature-complete, edit + compress in one&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Temporary one-time compression&lt;/td&gt;
&lt;td&gt;No install, fast&lt;/td&gt;
&lt;td&gt;ILovePDF online&lt;/td&gt;
&lt;td&gt;No install, drag-drop upload&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Developer integration&lt;/td&gt;
&lt;td&gt;CLI/SDK&lt;/td&gt;
&lt;td&gt;Ghostscript/SmartSlim SDK&lt;/td&gt;
&lt;td&gt;Ghostscript free open source, SDK easier to integrate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Xinchuang environment deployment&lt;/td&gt;
&lt;td&gt;Domestic compatibility&lt;/td&gt;
&lt;td&gt;SmartSlim Server&lt;/td&gt;
&lt;td&gt;Supports Kylin OS/DM database/Phytium CPU&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zero budget&lt;/td&gt;
&lt;td&gt;Fully free&lt;/td&gt;
&lt;td&gt;PDF24 Creator&lt;/td&gt;
&lt;td&gt;Fully free, unlimited, local compression&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  7. Summary
&lt;/h2&gt;

&lt;p&gt;The top PDF compression tool in 2026 is SmartSlim — 92.5% compression ratio, the highest in the industry; local compression with data staying on-prem; the free edition meets daily needs; annual paid only 98 yuan, outstanding value. Adobe Acrobat suits professional PDF editing needs; ILovePDF suits temporary one-time compression; Ghostscript suits developer CLI scenarios. Three principles for choosing a tool: classified documents use local; batch processing uses API; personal daily use uses the free edition.&lt;/p&gt;

&lt;p&gt;SmartSlim is built on the Rust compression engine, supports 10 categories and 40+ formats including PDF/images/video/Office/OFD, and offers four forms — Desktop/Server/Network/SDK — covering all scenarios from personal to enterprise.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;Q: What is the best PDF compression tool in 2026?&lt;br&gt;
A: SmartSlim is the top recommendation for 2026 — it offers the best compression ratio (80-95% reduction), maintains high quality, supports batch processing, runs locally (no privacy concerns), and is available in free and paid versions. For enterprise users, SmartSlim Enterprise provides SDK integration, API access, and deployment options. Adobe Acrobat Pro is good for individual use but expensive. Online tools like ILovePDF are convenient but have file size limits and privacy risks.&lt;/p&gt;

&lt;p&gt;Q: Are free PDF compression tools effective?&lt;br&gt;
A: Yes, several free tools are effective: SmartSlim Free (best compression ratio, local processing), Smallpdf (convenient, 2 files/day free), and PDF24 Tools (feature-rich, desktop version). Free tools can typically reduce PDF size by 50-80%. For sensitive documents, always use local processing tools. SmartSlim Free offers unlimited compression without file size limits, making it the best free option for most users.&lt;/p&gt;

&lt;p&gt;Q: How do online PDF compression tools compare to desktop software?&lt;br&gt;
A: Online tools: convenient, no installation, accessible from any device. Limitations: file size limits (typically 50-100MB), privacy concerns (files uploaded to third-party servers), internet dependency, and slower processing. Desktop software: no file size limits, 100% local processing (no privacy risks), faster processing, batch processing, and more advanced features. SmartSlim offers both — desktop app for daily use and cloud API for automated workflows.&lt;/p&gt;

&lt;p&gt;Q: What security considerations are important for PDF compression?&lt;br&gt;
A: Key security considerations: 1) Never upload sensitive documents to unknown online tools. 2) Use local processing for confidential documents (contracts, financial reports, legal documents). 3) Verify that the tool properly handles encrypted PDFs. 4) Check if the tool modifies digital signatures. 5) Ensure the tool maintains PDF/A compliance when required. SmartSlim processes all files locally without any network transmission, ensuring complete data security.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The key to top 10 best pdf compression... lies in identifying the sources of bloat and handling them accordingly. Choose the right compression strategy based on your scenario, prioritizing the largest contributors. SmartSlim can handle all compression steps in one click.&lt;/p&gt;

&lt;p&gt;Related:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/free-compression-software-review.html" rel="noopener noreferrer"&gt;Free Compression Software: 7 Tools Reviewed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/batch-compression-tool-selection.html" rel="noopener noreferrer"&gt;Batch Compression Tool Selection: CLI vs GUI vs API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/pdf-compression-guide.html" rel="noopener noreferrer"&gt;PDF Compression Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>pdfcompressor</category>
      <category>filecompressor</category>
      <category>pdfsoftware</category>
    </item>
    <item>
      <title>AVIF Format Guide: The Next-Generation Image Compression STD</title>
      <dc:creator>Uglypear Data</dc:creator>
      <pubDate>Thu, 06 Aug 2026 13:44:48 +0000</pubDate>
      <link>https://dev.to/uglypeardata/avif-format-guide-the-next-generation-image-compression-std-4oa5</link>
      <guid>https://dev.to/uglypeardata/avif-format-guide-the-next-generation-image-compression-std-4oa5</guid>
      <description>&lt;p&gt;Original URL: &lt;a href="https://www.uglypear.com/en/blog/avif-format-guide.html" rel="noopener noreferrer"&gt;https://www.uglypear.com/en/blog/avif-format-guide.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What is AVIF? This article provides a complete guide to the AVIF image format — based on AV1 encoding, 50% smaller than JPEG and 20% smaller than WebP, with a 4-format comparison test of AVIF vs WebP vs JPEG vs PNG and a browser compatibility migration guide. AVIF represents the next generation of image compression, offering superior compression efficiency for modern web applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. What is AVIF
&lt;/h2&gt;

&lt;p&gt;AVIF (AV1 Image File Format) is an image format released by the Alliance for Open Media (AOMedia) in 2019, based on the intra-frame coding technology of the AV1 video encoder. AV1 itself is an open-source, royalty-free coding standard designed for next-generation video (8K/120fps), and its intra-frame coding tools are equally applicable to static image compression. AVIF essentially packages AV1's intra-frame coding into a standalone image container format.&lt;/p&gt;

&lt;p&gt;The core advancements of AVIF over the previous-generation WebP include: support for 12-bit color depth and HDR (High Dynamic Range), while WebP only supports 8-bit SDR; higher compression ratios (10%–30% smaller at equivalent quality); and support for richer coding tools (directional prediction, more flexible block partitioning). The tradeoff is slower encoding speed — AVIF encoding takes about 3–5 times longer than WebP.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;AVIF&lt;/th&gt;
&lt;th&gt;WebP&lt;/th&gt;
&lt;th&gt;JPEG&lt;/th&gt;
&lt;th&gt;PNG&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Release Year&lt;/td&gt;
&lt;td&gt;2019&lt;/td&gt;
&lt;td&gt;2010&lt;/td&gt;
&lt;td&gt;1992&lt;/td&gt;
&lt;td&gt;1996&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Underlying Codec&lt;/td&gt;
&lt;td&gt;AV1 Intra&lt;/td&gt;
&lt;td&gt;VP8 Intra&lt;/td&gt;
&lt;td&gt;DCT&lt;/td&gt;
&lt;td&gt;DEFLATE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lossy Compression&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lossless Compression&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alpha Channel&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HDR/Wide Color Gamut&lt;/td&gt;
&lt;td&gt;Yes (12-bit)&lt;/td&gt;
&lt;td&gt;No (8-bit)&lt;/td&gt;
&lt;td&gt;No (8-bit)&lt;/td&gt;
&lt;td&gt;No (8/16-bit)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Animation Support&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;APNG extension&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Licensing&lt;/td&gt;
&lt;td&gt;Free &amp;amp; Open Source&lt;/td&gt;
&lt;td&gt;Free &amp;amp; Open Source&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  2. AVIF Technical Principles Explained
&lt;/h2&gt;

&lt;p&gt;AVIF's compression pipeline consists of three core stages: partition prediction, transform coding, and loop filtering. Each stage inherits the advanced tools from AV1 video coding, which is the fundamental reason AVIF's compression efficiency far exceeds that of JPEG.&lt;/p&gt;

&lt;p&gt;AV1 divides the image into coding blocks (up to 128×128), and each block can be recursively subdivided into smaller sub-blocks (down to 4×4), adaptively selecting partitioning based on image content. Predictive coding uses already-reconstructed pixels to predict the current block, encoding only the residual (the difference between actual and predicted values).&lt;/p&gt;

&lt;p&gt;The residual after prediction is transformed from the spatial domain to the frequency domain using transform coding, and high-frequency coefficients are quantized to achieve compression. AV1 supports multiple transform types, offering more flexibility than JPEG's single DCT.&lt;/p&gt;

&lt;p&gt;The reconstructed image after quantization produces blocking artifacts and ringing artifacts, which AV1 repairs using multi-level loop filtering. This is the key reason AVIF's image quality at low bitrates is significantly better than JPEG.&lt;/p&gt;

&lt;p&gt;For a comprehensive overview of image compression, refer to the Image Compression Guide: JPG/PNG/WebP Format Comparison.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prediction Type&lt;/th&gt;
&lt;th&gt;Principle&lt;/th&gt;
&lt;th&gt;Applicable Regions&lt;/th&gt;
&lt;th&gt;vs JPEG&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Intra Prediction&lt;/td&gt;
&lt;td&gt;Predicts using adjacent encoded pixels&lt;/td&gt;
&lt;td&gt;Smooth areas/gradients&lt;/td&gt;
&lt;td&gt;JPEG has no prediction, encodes everything&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Directional Prediction&lt;/td&gt;
&lt;td&gt;56 directional angle predictions&lt;/td&gt;
&lt;td&gt;Edges/texture directions&lt;/td&gt;
&lt;td&gt;JPEG has no directional prediction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Palette Prediction&lt;/td&gt;
&lt;td&gt;Uses color palette indexing&lt;/td&gt;
&lt;td&gt;Text/icons/animation&lt;/td&gt;
&lt;td&gt;JPEG lacks this tool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block Copy&lt;/td&gt;
&lt;td&gt;Copies other regions within the image&lt;/td&gt;
&lt;td&gt;Repeated textures&lt;/td&gt;
&lt;td&gt;JPEG lacks this tool&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  3. Practical Case: Four-Format Comparison Test
&lt;/h2&gt;

&lt;p&gt;We compare the file size, image quality, and encoding time of AVIF, WebP, JPEG, and PNG using the same test image. Test sample: 1920×1080 natural landscape photo, 24-bit true color, original BMP approximately 5.93MB.&lt;/p&gt;

&lt;p&gt;Document characteristics: 1920×1080, 24-bit color, containing sky gradients, foliage textures, and building edges, original BMP 5.93MB.&lt;/p&gt;

&lt;p&gt;File size and quality comparison (target SSIM 0.92):&lt;/p&gt;

&lt;p&gt;Results: At equivalent quality (SSIM 0.92+), AVIF is only 210KB — 50% smaller than JPEG and 29.5% smaller than WebP. PNG has the highest lossless quality but the largest file size (4.82MB), making it unsuitable for photo content. AVIF performs particularly well in foliage texture and sky gradient areas — JPEG shows visible color blocking at low bitrates, while AVIF has almost no visible artifacts.&lt;/p&gt;

&lt;p&gt;AVIF's encoding time is 15 times that of JPEG and 4 times that of WebP, because AV1's partition prediction and transform selection require extensive rate-distortion optimization calculations. However, AVIF's decoding speed is only 2 times slower than JPEG — minimal impact on the browsing experience. It is recommended to pre-generate AVIF images on the server side (encode at build time) rather than encoding in real time.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Transform Type&lt;/th&gt;
&lt;th&gt;Block Size&lt;/th&gt;
&lt;th&gt;Applicable Scenarios&lt;/th&gt;
&lt;th&gt;Advantage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DCT&lt;/td&gt;
&lt;td&gt;4×4 to 64×64&lt;/td&gt;
&lt;td&gt;General purpose&lt;/td&gt;
&lt;td&gt;Classic transform, energy compaction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ADST (Asymmetric Discrete Sine Transform)&lt;/td&gt;
&lt;td&gt;4×4 to 32×32&lt;/td&gt;
&lt;td&gt;Directional edges&lt;/td&gt;
&lt;td&gt;Better for edge residuals&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Identity Transform&lt;/td&gt;
&lt;td&gt;4×4 to 32×32&lt;/td&gt;
&lt;td&gt;Lossless/low-loss&lt;/td&gt;
&lt;td&gt;Skips transform, direct quantization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recursive Transform&lt;/td&gt;
&lt;td&gt;Combined&lt;/td&gt;
&lt;td&gt;Complex textures&lt;/td&gt;
&lt;td&gt;Two-level transform improves energy compaction&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  4. Browser Compatibility and Migration Strategy
&lt;/h2&gt;

&lt;p&gt;AVIF's browser compatibility has essentially matured after 2023, but fallback solutions are still needed for older browsers. The table below lists the support status of major browsers.&lt;/p&gt;

&lt;p&gt;Global browser support for AVIF is approximately 96%, with only IE and very old browser versions lacking support. The recommended migration strategy uses the HTML5 picture tag for progressive enhancement.&lt;/p&gt;

&lt;p&gt;Recommended picture tag syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"photo.avif"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/avif"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"photo.webp"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"photo.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Landscape photo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser selects the first supported format by priority: if AVIF is supported, it uses AVIF (smallest); otherwise, it tries WebP, and finally falls back to JPEG. This approach enjoys AVIF's compression advantages while ensuring normal display on older browsers. For a complete web image optimization solution, refer to Web Image Optimization: 50% Performance Improvement in Practice.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Filter Stage&lt;/th&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Processing Order&lt;/th&gt;
&lt;th&gt;Effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CDEF (Constrained Directional Enhancement Filter)&lt;/td&gt;
&lt;td&gt;Removes block boundary artifacts&lt;/td&gt;
&lt;td&gt;Stage 1&lt;/td&gt;
&lt;td&gt;Smooths block boundaries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LR (Loop Restoration Filter)&lt;/td&gt;
&lt;td&gt;Wiener filter/Self-guided filter&lt;/td&gt;
&lt;td&gt;Stage 2&lt;/td&gt;
&lt;td&gt;Restores detail textures&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Super-resolution Reconstruction&lt;/td&gt;
&lt;td&gt;Reconstructs from low-resolution frames&lt;/td&gt;
&lt;td&gt;Stage 3&lt;/td&gt;
&lt;td&gt;Enhances high-frequency details&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  5. Format Selection Guide for Different Scenarios
&lt;/h2&gt;

&lt;p&gt;While AVIF is excellent, it's not suitable for all scenarios. Format selection for different scenarios requires comprehensive consideration of compression ratio, compatibility, encoding speed, and feature requirements.&lt;/p&gt;

&lt;p&gt;A general principle: for static content pre-generation, choose AVIF (optimal size); for real-time generation, choose JPEG/WebP (speed priority); for lossless requirements, choose PNG; for HDR content, choose AVIF (the only option). When using SmartSlim for batch conversion, you can automatically generate multiple formats (AVIF+WebP+JPEG), covering all compatibility scenarios in one pass.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;th&gt;Parameters&lt;/th&gt;
&lt;th&gt;File Size&lt;/th&gt;
&lt;th&gt;vs Original&lt;/th&gt;
&lt;th&gt;SSIM Quality&lt;/th&gt;
&lt;th&gt;vs JPEG&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PNG (Lossless)&lt;/td&gt;
&lt;td&gt;DEFLATE Maximum&lt;/td&gt;
&lt;td&gt;4.82MB&lt;/td&gt;
&lt;td&gt;-18.7%&lt;/td&gt;
&lt;td&gt;1.000&lt;/td&gt;
&lt;td&gt;+938%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JPEG&lt;/td&gt;
&lt;td&gt;Quality 85&lt;/td&gt;
&lt;td&gt;420KB&lt;/td&gt;
&lt;td&gt;-92.9%&lt;/td&gt;
&lt;td&gt;0.921&lt;/td&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebP&lt;/td&gt;
&lt;td&gt;Quality 80&lt;/td&gt;
&lt;td&gt;298KB&lt;/td&gt;
&lt;td&gt;-95.0%&lt;/td&gt;
&lt;td&gt;0.923&lt;/td&gt;
&lt;td&gt;-29.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AVIF&lt;/td&gt;
&lt;td&gt;Quality 55 (CRF)&lt;/td&gt;
&lt;td&gt;210KB&lt;/td&gt;
&lt;td&gt;-96.5%&lt;/td&gt;
&lt;td&gt;0.925&lt;/td&gt;
&lt;td&gt;-50.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  6. Frequently Asked Questions (FAQ)
&lt;/h2&gt;

&lt;p&gt;Q1: What is the AVIF format?&lt;/p&gt;

&lt;p&gt;AVIF (AV1 Image File Format) is an image format based on AV1 video coding, released by the Alliance for Open Media (AOMedia) in 2019. AVIF leverages AV1's intra-frame coding technology to compress static images, achieving 50% smaller files than JPEG and 20% smaller than WebP, while supporting lossless compression, HDR, wide color gamut, and alpha channels. AVIF is an open-source, royalty-free next-generation image compression standard, natively supported by major browsers including Chrome and Firefox.&lt;/p&gt;

&lt;p&gt;Q2: How much smaller is AVIF compared to JPEG?&lt;/p&gt;

&lt;p&gt;At equivalent quality (SSIM 0.9 or above), AVIF is approximately 50% smaller than JPEG. For example, a 1920×1080 photo: JPEG at quality 85 is about 420KB, while AVIF at equivalent quality is about 210KB. Compared to WebP, AVIF is about 20% smaller at medium quality, with even greater advantages at high quality (30%+ smaller). AVIF's compression advantage comes from AV1's more advanced predictive coding and transform tools, performing particularly well in areas with complex textures.&lt;/p&gt;

&lt;p&gt;Q3: How is AVIF's browser compatibility?&lt;/p&gt;

&lt;p&gt;As of 2026, AVIF is supported by major browsers: Chrome 85+ (September 2020), Firefox 93+ (October 2021), Edge 92+ (2021), and Safari 16.4+ (March 2023). Global browser support rate is approximately 96%. Older browsers that don't support AVIF can be provided with JPEG/WebP fallback via the picture tag. It's recommended to use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;'img.avif'&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'image/avif'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;'img.jpg'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;for progressive enhancement.&lt;/p&gt;

&lt;p&gt;Q4: Which is better, AVIF or WebP?&lt;/p&gt;

&lt;p&gt;Overall, AVIF is superior to WebP. Compression ratio: AVIF is 10%–30% smaller than WebP; Features: AVIF supports HDR and 12-bit color depth, while WebP only supports 8-bit SDR; Encoding speed: WebP is faster than AVIF (AVIF encoding is slower); Compatibility: WebP support rate is about 98%, AVIF about 96%. If you pursue ultimate compression ratio and HDR support, choose AVIF; if you prioritize encoding speed and broad compatibility, choose WebP. It's recommended to provide both formats simultaneously using the picture tag.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;th&gt;Encoding Time&lt;/th&gt;
&lt;th&gt;Decoding Time&lt;/th&gt;
&lt;th&gt;Speed Rating&lt;/th&gt;
&lt;th&gt;Applicable Scenarios&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JPEG&lt;/td&gt;
&lt;td&gt;18ms&lt;/td&gt;
&lt;td&gt;8ms&lt;/td&gt;
&lt;td&gt;Extremely fast&lt;/td&gt;
&lt;td&gt;Real-time encoding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebP&lt;/td&gt;
&lt;td&gt;65ms&lt;/td&gt;
&lt;td&gt;15ms&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;td&gt;Web real-time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AVIF&lt;/td&gt;
&lt;td&gt;280ms&lt;/td&gt;
&lt;td&gt;22ms&lt;/td&gt;
&lt;td&gt;Slow (encoding)/Fast (decoding)&lt;/td&gt;
&lt;td&gt;Pre-generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PNG&lt;/td&gt;
&lt;td&gt;120ms&lt;/td&gt;
&lt;td&gt;12ms&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Lossless scenarios&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  7. Summary
&lt;/h2&gt;

&lt;p&gt;AVIF is the next-generation image compression standard, based on AV1 intra-frame coding, 50% smaller than JPEG and 20% smaller than WebP, while also supporting HDR, 12-bit color depth, and alpha channels. Its technical leadership comes from partition prediction (56 directional predictions), multiple transform coding types (DCT/ADST/Identity Transform), and multi-level loop filtering (CDEF+LR). The tradeoff is slower encoding speed (about 4 times that of WebP), making it suitable for pre-generation scenarios rather than real-time encoding.&lt;/p&gt;

&lt;p&gt;The recommended migration strategy is the picture tag multi-format approach: AVIF first, WebP second, JPEG fallback, balancing compression ratio and 100% compatibility. Remember three points: first, AVIF encoding is slow but decoding is fast, suitable for server-side pre-generation; second, HDR content can only use AVIF (WebP/JPEG don't support it); third, use the picture tag to provide all three formats simultaneously, letting the browser automatically select the optimal one.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Browser&lt;/th&gt;
&lt;th&gt;Supported Version&lt;/th&gt;
&lt;th&gt;Release Date&lt;/th&gt;
&lt;th&gt;Global Share&lt;/th&gt;
&lt;th&gt;Support Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Chrome&lt;/td&gt;
&lt;td&gt;85+&lt;/td&gt;
&lt;td&gt;September 2020&lt;/td&gt;
&lt;td&gt;65%&lt;/td&gt;
&lt;td&gt;Native support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Safari&lt;/td&gt;
&lt;td&gt;16.4+&lt;/td&gt;
&lt;td&gt;March 2023&lt;/td&gt;
&lt;td&gt;18%&lt;/td&gt;
&lt;td&gt;Native support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edge&lt;/td&gt;
&lt;td&gt;92+&lt;/td&gt;
&lt;td&gt;2021&lt;/td&gt;
&lt;td&gt;5%&lt;/td&gt;
&lt;td&gt;Native support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Firefox&lt;/td&gt;
&lt;td&gt;93+&lt;/td&gt;
&lt;td&gt;October 2021&lt;/td&gt;
&lt;td&gt;3%&lt;/td&gt;
&lt;td&gt;Native support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opera&lt;/td&gt;
&lt;td&gt;71+&lt;/td&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;2%&lt;/td&gt;
&lt;td&gt;Native support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IE&lt;/td&gt;
&lt;td&gt;Not supported&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;&amp;lt;1%&lt;/td&gt;
&lt;td&gt;Fallback required&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Migration Approach&lt;/th&gt;
&lt;th&gt;Implementation&lt;/th&gt;
&lt;th&gt;Compatibility&lt;/th&gt;
&lt;th&gt;Maintenance Cost&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;picture tag&lt;/td&gt;
&lt;td&gt;Multi-format source + img fallback&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AVIF only&lt;/td&gt;
&lt;td&gt;Use avif directly&lt;/td&gt;
&lt;td&gt;96%&lt;/td&gt;
&lt;td&gt;Very low&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accept header negotiation&lt;/td&gt;
&lt;td&gt;Server returns based on Accept&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JPEG only&lt;/td&gt;
&lt;td&gt;No migration&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;Very low&lt;/td&gt;
&lt;td&gt;★☆☆☆☆&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Recommended Format&lt;/th&gt;
&lt;th&gt;Reason&lt;/th&gt;
&lt;th&gt;Size Reference&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;E-commerce product images&lt;/td&gt;
&lt;td&gt;AVIF (primary)+JPEG (fallback)&lt;/td&gt;
&lt;td&gt;Pursues ultimate size, improves loading speed&lt;/td&gt;
&lt;td&gt;JPEG 420KB→AVIF 210KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;News content&lt;/td&gt;
&lt;td&gt;WebP (primary)+JPEG (fallback)&lt;/td&gt;
&lt;td&gt;Fast encoding, good compatibility&lt;/td&gt;
&lt;td&gt;JPEG 420KB→WebP 298KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HDR photography&lt;/td&gt;
&lt;td&gt;AVIF&lt;/td&gt;
&lt;td&gt;Only mainstream format supporting 12-bit HDR&lt;/td&gt;
&lt;td&gt;Lossless HDR only available with AVIF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UI icons/screenshots&lt;/td&gt;
&lt;td&gt;PNG&lt;/td&gt;
&lt;td&gt;Lossless requirement, sharp edges&lt;/td&gt;
&lt;td&gt;Size not a concern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Social media&lt;/td&gt;
&lt;td&gt;AVIF or WebP&lt;/td&gt;
&lt;td&gt;Small size, fast sharing&lt;/td&gt;
&lt;td&gt;Both work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Email embedding&lt;/td&gt;
&lt;td&gt;JPEG&lt;/td&gt;
&lt;td&gt;Email client compatibility priority&lt;/td&gt;
&lt;td&gt;AVIF not recommended (poor compatibility)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Video thumbnails&lt;/td&gt;
&lt;td&gt;AVIF&lt;/td&gt;
&lt;td&gt;Natural pairing with AV1 video&lt;/td&gt;
&lt;td&gt;50% smaller than JPEG&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real-time generation (CAPTCHA, etc.)&lt;/td&gt;
&lt;td&gt;JPEG&lt;/td&gt;
&lt;td&gt;Encoding speed priority&lt;/td&gt;
&lt;td&gt;18ms vs AVIF 280ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;Q: What is AVIF and why is it better than JPEG?&lt;br&gt;
A: AVIF (AV1 Image File Format) is a next-generation image format based on the AV1 video codec. It achieves 50% smaller files than JPEG at equivalent visual quality, and 20% smaller than WebP. It supports HDR (High Dynamic Range), wide color gamut (BT.2020), 10/12-bit color depth, transparency, and lossless compression. AVIF is the successor to JPEG, offering dramatically better compression efficiency for modern web and mobile applications.&lt;/p&gt;

&lt;p&gt;Q: How does AVIF compare to WebP?&lt;br&gt;
A: AVIF is 20-30% more efficient than WebP at equivalent quality. For a typical photo: WebP at quality 80 produces a 40KB file. AVIF at equivalent quality produces a 30-32KB file. AVIF also supports HDR and 10-bit color, which WebP does not. However, WebP has broader browser support (95%+ vs 90%+ for AVIF). AVIF encoding is also slower than WebP. For new projects, AVIF is recommended for forward compatibility.&lt;/p&gt;

&lt;p&gt;Q: What is the browser compatibility of AVIF?&lt;br&gt;
A: AVIF is supported by: Chrome 85+ (2020), Firefox 93+ (2021), Opera 71+ (2020), Safari 16.1+ (2022). Edge 121+ (2024). Overall support: ~90% of global browser users. For older browsers, use the  element with fallback to WebP or JPEG. SmartSlim automatically generates AVIF with fallbacks, ensuring compatibility across all browsers while delivering AVIF to modern browsers.&lt;/p&gt;

&lt;p&gt;Q: How to migrate existing images to AVIF?&lt;br&gt;
A: Migration steps: 1) Use SmartSlim or avifenc to convert JPEG/PNG to AVIF. 2) Update HTML with  elements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"image.avif"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/avif"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"image.webp"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"image.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;. 3) Test on all browsers. 4) For CDN delivery, enable automatic AVIF conversion. SmartSlim's batch conversion tool handles the entire migration process, generating AVIF + WebP + JPEG variants with responsive markup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The key to avif format guide: the next-generation... lies in identifying the sources of bloat and handling them accordingly. Choose the right compression strategy based on your scenario, prioritizing the largest contributors. SmartSlim can handle all compression steps in one click.&lt;/p&gt;

&lt;p&gt;Related:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/webp-vs-png-vs-jpg.html" rel="noopener noreferrer"&gt;WebP vs PNG vs JPG: Which Web Image Format to Choose?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/png-compression-principle.html" rel="noopener noreferrer"&gt;PNG Compression Principle: Why Is DEFLATE Lossless?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/web-image-optimization.html" rel="noopener noreferrer"&gt;Web Image Optimization: Compression Strategies&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>compression</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Word Document Too Large? 3 Compression Methods Tested</title>
      <dc:creator>Uglypear Data</dc:creator>
      <pubDate>Wed, 05 Aug 2026 07:21:20 +0000</pubDate>
      <link>https://dev.to/uglypeardata/word-document-too-large-3-compression-methods-tested-50jb</link>
      <guid>https://dev.to/uglypeardata/word-document-too-large-3-compression-methods-tested-50jb</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.uglypear.com%2Fassets%2Fimages%2Fblog%2Fword-document-compression-cover.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.uglypear.com%2Fassets%2Fimages%2Fblog%2Fword-document-compression-cover.jpg" alt="Cover" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bottom line first: Word documents become too large mainly because embedded images and embedded fonts account for the vast majority of their size. The solution is a three-step approach: compress embedded images (downsample DPI + convert to JPEG), apply font subsetting (keep only the characters actually used), and save as .docx to clear redundancy. A 50MB tender document packed with high-resolution images can be compressed to under 5MB with this workflow, with virtually no loss of text or chart clarity. Below, we start from what causes document bloat, compare 3 tested methods, and include a complete case study.&lt;/p&gt;

&lt;p&gt;If you're not yet familiar with the overall concept of file compression, we recommend reading the &lt;a href="https://www.uglypear.com/en/blog/file-compression-complete-guide.html" rel="noopener noreferrer"&gt;Complete Guide to File Compression&lt;/a&gt; first.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Why Are Word Documents So Large?
&lt;/h2&gt;

&lt;p&gt;A Word document (.docx/.doc) is essentially a container that packages text, images, fonts, styles, revision history, and more together. Size bloat almost always comes from non-text content. Understanding the sources of size is the key to targeted compression.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Size Source&lt;/th&gt;
&lt;th&gt;Typical Share&lt;/th&gt;
&lt;th&gt;Cause&lt;/th&gt;
&lt;th&gt;Compression Potential&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Embedded images&lt;/td&gt;
&lt;td&gt;60%–85%&lt;/td&gt;
&lt;td&gt;High-res originals pasted directly, uncompressed; multiple images stacked&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Embedded fonts&lt;/td&gt;
&lt;td&gt;10%–25%&lt;/td&gt;
&lt;td&gt;Full Chinese font files embedded (10–20MB each)&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Revisions and comments&lt;/td&gt;
&lt;td&gt;3%–10%&lt;/td&gt;
&lt;td&gt;Revision history and comments left from multi-user collaboration&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Document redundancy&lt;/td&gt;
&lt;td&gt;2%–8%&lt;/td&gt;
&lt;td&gt;Redundant XML and obsolete styles from repeated save-as operations&lt;/td&gt;
&lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pure text content&lt;/td&gt;
&lt;td&gt;1%–5%&lt;/td&gt;
&lt;td&gt;The body text itself&lt;/td&gt;
&lt;td&gt;★☆☆☆☆&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As the table above shows, embedded images and embedded fonts together account for over 80%, making them the main battleground for compression. A 50MB tender document might contain 40MB of images and 8MB of fonts, with less than 2MB of pure text — once you compress the images and fonts, the document naturally shrinks.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Three Compression Methods Tested and Compared
&lt;/h2&gt;

&lt;p&gt;Based on the size sources of Word documents, there are 3 mainstream compression methods. Each method differs in principle, applicable scenarios, and effect. The table below gives an overall comparison first, followed by detailed explanations.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Principle&lt;/th&gt;
&lt;th&gt;Applicable Scenario&lt;/th&gt;
&lt;th&gt;Expected Compression Rate&lt;/th&gt;
&lt;th&gt;Clarity Impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Embedded image compression&lt;/td&gt;
&lt;td&gt;Downsample DPI + format conversion&lt;/td&gt;
&lt;td&gt;Image-heavy documents (tenders/reports)&lt;/td&gt;
&lt;td&gt;70%–90%&lt;/td&gt;
&lt;td&gt;Virtually no difference on screen&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Font subsetting&lt;/td&gt;
&lt;td&gt;Keep only used characters&lt;/td&gt;
&lt;td&gt;Documents with embedded Chinese fonts&lt;/td&gt;
&lt;td&gt;80%–95%&lt;/td&gt;
&lt;td&gt;No impact&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Save-as optimization&lt;/td&gt;
&lt;td&gt;Clear redundancy + format conversion&lt;/td&gt;
&lt;td&gt;Old documents / repeatedly edited files&lt;/td&gt;
&lt;td&gt;10%–30%&lt;/td&gt;
&lt;td&gt;No impact&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  1. Embedded Image Compression (Highest Return)
&lt;/h3&gt;

&lt;p&gt;Embedded images are the number one source of Word document size. The compression method has two steps: downsampling DPI and format conversion. DPI (dots per inch) determines image pixel density — screen reading only needs 96–150DPI, yet many documents paste in 300DPI or even 600DPI originals. Format conversion means turning lossless formats (PNG/BMP) into lossy formats (JPEG), drastically reducing size with virtually no perceptible difference to the naked eye.&lt;/p&gt;

&lt;p&gt;In practice: open the Word document with SmartSlim, and the engine automatically identifies the embedded image types and assigns compression strategies — scanned documents are downsampled to 150DPI and converted to grayscale JPEG, photos are downsampled to 200DPI and converted to color JPEG at quality 80, and wireframe/screenshots stay as PNG but undergo PNG optimization. This type-based dispatching works better than uniform parameters — scanned documents compress by 90% while screenshots remain virtually untouched.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Image Type&lt;/th&gt;
&lt;th&gt;Original Parameters&lt;/th&gt;
&lt;th&gt;Compression Parameters&lt;/th&gt;
&lt;th&gt;Size Reduction&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;High-res photo&lt;/td&gt;
&lt;td&gt;300DPI, PNG, 8MB&lt;/td&gt;
&lt;td&gt;200DPI, JPEG q80, 0.8MB&lt;/td&gt;
&lt;td&gt;90%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scanned document&lt;/td&gt;
&lt;td&gt;600DPI, BMP, 15MB&lt;/td&gt;
&lt;td&gt;150DPI, JPEG q72 grayscale, 0.5MB&lt;/td&gt;
&lt;td&gt;97%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wireframe/screenshot&lt;/td&gt;
&lt;td&gt;96DPI, PNG, 2MB&lt;/td&gt;
&lt;td&gt;96DPI, PNG optimized, 1.2MB&lt;/td&gt;
&lt;td&gt;40%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chart/flowchart&lt;/td&gt;
&lt;td&gt;200DPI, PNG, 3MB&lt;/td&gt;
&lt;td&gt;150DPI, JPEG q85, 0.6MB&lt;/td&gt;
&lt;td&gt;80%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For more detailed principles on image compression, see the &lt;a href="https://www.uglypear.com/en/blog/image-compression-guide.html" rel="noopener noreferrer"&gt;Image Compression Guide: JPG/PNG/WebP Format Comparison&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Font Subsetting (Essential for Chinese Documents)
&lt;/h3&gt;

&lt;p&gt;Many Word documents embed complete font files to ensure consistent display across devices. A complete Chinese font (such as Source Han Serif) easily reaches 10–20MB, and embedding both Regular and Bold weights starts at 30MB. But the document may actually use only a thousand or two distinct characters — font subsetting keeps only the characters that are used and discards the rest.&lt;/p&gt;

&lt;p&gt;The size after font subsetting depends on character usage. A 50-page tender typically uses 800–1500 distinct characters; the full Source Han Serif file is 18MB, but after subsetting it drops to just 0.3–0.8MB, a reduction of over 95%. This operation has zero impact on display — the retained characters are exactly the same as before; it simply removes the characters that weren't used.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Font&lt;/th&gt;
&lt;th&gt;Full File&lt;/th&gt;
&lt;th&gt;After Subsetting (1200 characters)&lt;/th&gt;
&lt;th&gt;Reduction&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Source Han Serif Regular&lt;/td&gt;
&lt;td&gt;18.2MB&lt;/td&gt;
&lt;td&gt;0.42MB&lt;/td&gt;
&lt;td&gt;97.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Source Han Sans Regular&lt;/td&gt;
&lt;td&gt;16.8MB&lt;/td&gt;
&lt;td&gt;0.38MB&lt;/td&gt;
&lt;td&gt;97.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft YaHei Regular&lt;/td&gt;
&lt;td&gt;15.6MB&lt;/td&gt;
&lt;td&gt;0.35MB&lt;/td&gt;
&lt;td&gt;97.8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Arial Regular&lt;/td&gt;
&lt;td&gt;0.8MB&lt;/td&gt;
&lt;td&gt;0.06MB&lt;/td&gt;
&lt;td&gt;92.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  3. Save-As Optimization (Essential Finishing Step)
&lt;/h3&gt;

&lt;p&gt;After a Word document has been edited, revised, and saved multiple times, it accumulates redundant XML, obsolete style definitions, old revision history, and other junk data. Saving a .doc as .docx is itself an effective cleanup — .docx is based on the Open XML zip compression structure, which is typically 30%–50% smaller than the .doc binary format. When saving, Word rebuilds the document structure and automatically clears some redundancy.&lt;/p&gt;

&lt;p&gt;Going further, when processed by SmartSlim, the Rust compression engine unpacks the docx zip archive, cleans up obsolete resources (unreferenced images, duplicate style definitions, old revision records), and repackages the compressed file. This step typically squeezes out another 10%–15% of size, with no impact on display.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Case Study: Compressing a 50MB Tender to 4.6MB
&lt;/h2&gt;

&lt;p&gt;This is a construction engineering tender in .docx format, with an original size of 50.3MB. The document contains 48 pages of body text, 32 high-resolution site photos (1–2MB each), 8 CAD-exported drawings, and embedded Source Han Serif Regular+Bold. It needs to be sent via WeCom (20MB limit), with a target of under 5MB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Document characteristics:&lt;/strong&gt; 48 pages A4, 32 photos at 300DPI PNG (42MB total), 8 CAD drawings at 200DPI PNG (6MB total), embedded fonts 28MB, with extensive revision history from 5 rounds of edits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Execution parameters and size changes:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Key Parameters&lt;/th&gt;
&lt;th&gt;Size Change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Photo compression&lt;/td&gt;
&lt;td&gt;300DPI→200DPI, PNG→JPEG q80&lt;/td&gt;
&lt;td&gt;50.3→12.1MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Drawing compression&lt;/td&gt;
&lt;td&gt;200DPI→150DPI, PNG→JPEG q85&lt;/td&gt;
&lt;td&gt;12.1→8.3MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Font subsetting&lt;/td&gt;
&lt;td&gt;Keep 1342 used characters&lt;/td&gt;
&lt;td&gt;8.3→5.1MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Clean redundancy + repackage&lt;/td&gt;
&lt;td&gt;Clear revision history + obsolete styles&lt;/td&gt;
&lt;td&gt;5.1→4.6MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; 4.6MB, a compression ratio of about 10.9:1, well below the WeCom 20MB limit. The photos show virtually no perceptible difference on screen, the CAD drawing lines remain clearly distinguishable, the text layout is unchanged, and the fonts display normally. The entire process was completed locally — the tender never passed through any third-party server, meeting the confidentiality requirements for business documents.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Compression Recommendations for Different Scenarios
&lt;/h2&gt;

&lt;p&gt;Different types of Word documents have different size sources and compression priorities. The table below offers recommendations for common scenarios.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Document Type&lt;/th&gt;
&lt;th&gt;Typical Size&lt;/th&gt;
&lt;th&gt;Main Size Source&lt;/th&gt;
&lt;th&gt;Recommended Strategy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tender / project report&lt;/td&gt;
&lt;td&gt;30–80MB&lt;/td&gt;
&lt;td&gt;High-res site photos&lt;/td&gt;
&lt;td&gt;Downsample photos + convert to JPEG, font subsetting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Academic paper&lt;/td&gt;
&lt;td&gt;5–20MB&lt;/td&gt;
&lt;td&gt;Charts + embedded fonts&lt;/td&gt;
&lt;td&gt;PNG optimization for charts, font subsetting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Product manual&lt;/td&gt;
&lt;td&gt;10–50MB&lt;/td&gt;
&lt;td&gt;Product images + layout styles&lt;/td&gt;
&lt;td&gt;Tiered image compression, clean redundant styles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Contract / agreement&lt;/td&gt;
&lt;td&gt;2–10MB&lt;/td&gt;
&lt;td&gt;Scanned signature pages&lt;/td&gt;
&lt;td&gt;Downsample scans + grayscale JPEG&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Meeting minutes&lt;/td&gt;
&lt;td&gt;1–5MB&lt;/td&gt;
&lt;td&gt;Mostly plain text&lt;/td&gt;
&lt;td&gt;Save as .docx, clean revision history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Training materials&lt;/td&gt;
&lt;td&gt;20–100MB&lt;/td&gt;
&lt;td&gt;Screenshots + animated screenshots&lt;/td&gt;
&lt;td&gt;PNG optimization for screenshots, convert large images to JPEG&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A general principle: for image-heavy documents, compress images first (highest return); for documents with embedded fonts, font subsetting is a must; for old documents, save as .docx first to clear redundancy. With all three steps combined, the vast majority of Word documents can be compressed to 10%–20% of their original size.&lt;/p&gt;

&lt;p&gt;If you need to compare the effectiveness of different compression tools, see the &lt;a href="https://www.uglypear.com/en/blog/compression-tool-selection.html" rel="noopener noreferrer"&gt;File Compression Tool Selection Guide: 7 Dimensions Evaluated&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q1: How do I compress a Word document to under 5MB?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First use a compression tool to extract embedded images and downsample them to 150DPI, convert to JPEG at quality 80, then apply font subsetting (keep only used characters), and finally save as .docx to clear redundancy. A 50MB tender with lots of high-res images can be compressed to under 5MB in three steps, with virtually no loss of text or chart clarity. The key is to prioritize image compression (the largest share), then do font subsetting (highly effective for Chinese documents), and finish with redundancy cleanup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q2: Which is smaller, .docx or .doc?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;.docx is typically 30%–50% smaller than .doc. .docx is based on the Open XML zip compression structure and is compressed natively; .doc is a binary format that does not compress embedded resources. Saving the same document as .docx noticeably reduces the size, so we recommend using .docx uniformly. In addition, .docx is an open standard with better compatibility, and various compression tools can parse and process it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q3: What if images become blurry after Word compression?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Image blur is usually caused by overly aggressive downsampling. 150DPI is sufficient for screen reading, while printing requires 200–300DPI. JPEG quality should be set to 80 or above; below 70, noticeable color blocking appears. If the document contains wireframes or screenshots, use PNG instead of JPEG to avoid edge artifacts. SmartSlim automatically identifies image types and dispatches strategies — photos convert to JPEG, screenshots stay as PNG — avoiding the blur caused by a one-size-fits-all approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q4: Is there a way to batch compress Word documents?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can use SmartSlim desktop edition for batch drag-and-drop processing, supporting 5 Word formats including .docx/.doc/.docm/.odt/.rtf, and batch compress hundreds of files at once. Enterprise users can use the server edition API for automated batch processing, with parallel compression via a Celery task queue — 12 concurrent tasks per machine and a daily throughput of tens of thousands of documents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Word documents become too large because embedded images and embedded fonts account for over 80% of the size — the solution is targeted compression. The logic of the 3 methods is clear: image compression offers the highest return (downsample DPI + convert to JPEG, 70%–90% reduction), font subsetting is highly effective for Chinese documents (keep only used characters, 80%–95% reduction), and save-as optimization finishes the job by clearing redundancy (10%–30% reduction). With all three steps combined, a 50MB tender can be reliably compressed to under 5MB.&lt;/p&gt;

&lt;p&gt;Remember three points: first, diagnose the size source before acting — compress images first if there are many, and do font subsetting if fonts are large; second, dispatch strategies by image type — convert photos to JPEG and keep screenshots as PNG, avoiding a one-size-fits-all approach; third, use local compression for sensitive documents and don't upload them to online tools. With the right tools and methods, slimming down Word documents is actually quite simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/file-compression-complete-guide.html" rel="noopener noreferrer"&gt;Complete Guide to File Compression&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/image-compression-guide.html" rel="noopener noreferrer"&gt;Image Compression Guide: JPG/PNG/WebP Format Comparison&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.uglypear.com/en/blog/compression-tool-selection.html" rel="noopener noreferrer"&gt;File Compression Tool Selection Guide: 7 Dimensions Evaluated&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  About SmartSlim
&lt;/h2&gt;

&lt;p&gt;SmartSlim is the core product of Guangzhou Uglypear Data Technology Co., Ltd. Built on a self-developed Rust compression engine, it provides efficient and secure file compression solutions for individual and enterprise users. It supports 10 major categories and 40+ formats, including PDF, images, video, Office (Word/Excel/PPT), and OFD, covering mainstream document, image, and audio-video file types.&lt;/p&gt;

&lt;p&gt;Core advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local compression, data never leaves your domain&lt;/strong&gt;: All compression is performed locally, so sensitive files never need to be uploaded to third-party servers, meeting the confidentiality and compliance requirements of business, government, and financial scenarios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type-based compression strategy dispatching&lt;/strong&gt;: The engine automatically identifies file types and matches optimal compression parameters — photos convert to JPEG, screenshots stay as PNG, fonts undergo subsetting — avoiding the quality loss caused by a one-size-fits-all approach.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch processing and automation&lt;/strong&gt;: The desktop edition supports drag-and-drop batch compression, processing hundreds of files at once; the server edition provides an API for automated batch processing via a Celery task queue, with 12 concurrent tasks per machine and a daily throughput of tens of thousands of documents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-form product matrix&lt;/strong&gt;: Offers desktop, server, network editions, and a Rust compression SDK, adapting to personal office, team collaboration, and enterprise integration scenarios.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try SmartSlim now and make file compression simpler and more secure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free desktop download: &lt;a href="https://www.uglypear.com/en/download.html" rel="noopener noreferrer"&gt;https://www.uglypear.com/en/download.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Enterprise solution inquiry: &lt;a href="https://www.uglypear.com/en/contact.html" rel="noopener noreferrer"&gt;https://www.uglypear.com/en/contact.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;View SDK documentation: &lt;a href="https://www.uglypear.com/en/products/sdk.html" rel="noopener noreferrer"&gt;https://www.uglypear.com/en/products/sdk.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>productivity</category>
      <category>compression</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Evaluate File Compression Tools: 7-Dimension Framework</title>
      <dc:creator>Uglypear Data</dc:creator>
      <pubDate>Tue, 04 Aug 2026 03:26:29 +0000</pubDate>
      <link>https://dev.to/uglypeardata/how-to-evaluate-file-compression-tools-7-dimension-framework-2cii</link>
      <guid>https://dev.to/uglypeardata/how-to-evaluate-file-compression-tools-7-dimension-framework-2cii</guid>
      <description>&lt;h2&gt;
  
  
  The Selection Dilemma: Too Many Tools, Too Few Criteria
&lt;/h2&gt;

&lt;p&gt;There are hundreds of file compression tools on the market. From command-line utilities like &lt;code&gt;gzip&lt;/code&gt;, &lt;code&gt;xz&lt;/code&gt;, and &lt;code&gt;7-Zip&lt;/code&gt;, to graphical applications like WinRAR and Bandizip, to various online compression services and specialized transcoding tools, each one claims to be "faster, smaller, better." But when you face a concrete need—halving the size of a batch of PDFs, or transcoding hundreds of videos to save storage—you discover that no single tool is optimal in every scenario.&lt;/p&gt;

&lt;p&gt;The root cause is that &lt;strong&gt;a compression tool's capabilities are multidimensional&lt;/strong&gt;. Compression ratio and speed are often at odds, quality retention and size control require trade-offs, and local processing versus cloud services each have their own costs. If you focus solely on "compression ratio," you may end up with a tool that performs poorly in real-world use.&lt;/p&gt;

&lt;p&gt;This article proposes a &lt;strong&gt;7-dimension evaluation framework&lt;/strong&gt; to help you structurally assess any compression tool. Whether you are evaluating an open-source CLI, a commercial GUI, or a SaaS service, you can use the same yardstick and make a selection decision that fits your actual scenario.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisite: Archive vs. Content Compression
&lt;/h2&gt;

&lt;p&gt;Before diving into the 7-dimension evaluation, one fundamental distinction must be clarified: &lt;strong&gt;compression tools fall into two major categories&lt;/strong&gt;, with completely different working principles, applicable scenarios, and evaluation priorities.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Archive compression tools&lt;/strong&gt; (e.g., 7-Zip, gzip, Zstandard): Package files at the container level and eliminate redundancy. Lossless and reversible, but largely ineffective on already-compressed files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content compression tools&lt;/strong&gt; (e.g., FFmpeg, ImageMagick, Ghostscript): Dive into the internal structure of files for re-encoding. Mostly lossy and irreversible, but can dramatically reduce file size at the source.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This distinction is crucial—stuffing a 50MB PDF into a 7-Zip archive might only shrink it to 49MB, while using Ghostscript to downsample internal images can compress it to 6.8MB. Their "compression ratios" are not on the same level at all, and direct horizontal comparison can be seriously misleading.&lt;/p&gt;

&lt;p&gt;For a detailed explanation of the essential difference between the two types of compression, process comparison, and real-world examples, see &lt;a href="https://www.uglypear.com/en/blog/archive-vs-content-compression.html" rel="noopener noreferrer"&gt;Why Zipping Files Doesn't Actually Compress Them&lt;/a&gt;. The 7-dimension framework in this article applies to both types of tools, but when comparing specific tools below, their category will be clearly labeled to avoid confusion from cross-category comparison.&lt;/p&gt;




&lt;h2&gt;
  
  
  Framework Overview
&lt;/h2&gt;

&lt;p&gt;The flowchart below shows the relationships among the 7 evaluation dimensions and how they map to different usage scenarios:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fksy7ldxg1z6docqk0wwi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fksy7ldxg1z6docqk0wwi.png" alt="Framework Overview" width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Dimension 1: Compression Ratio
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Evaluation Criteria
&lt;/h3&gt;

&lt;p&gt;Compression ratio is the most intuitive metric, usually expressed as "ratio" (original size / compressed size) or "space savings" (1 − compressed size / original size). But a single number can be misleading, because &lt;strong&gt;compressibility varies dramatically across file types&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Text and source code&lt;/strong&gt;: High redundancy, highly compressible. Lossless algorithms typically achieve 3x to 10x ratios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uncompressed bitmaps (BMP, RAW)&lt;/strong&gt;: Strong inter-pixel correlation, large compression potential.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Already-compressed data (JPEG, MP4, ZIP)&lt;/strong&gt;: Statistical redundancy already removed; re-compression yields almost nothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mixed-content archives&lt;/strong&gt;: Contain both text and already-compressed media; overall ratio depends on the proportion of each part.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, when evaluating compression ratio, you must &lt;strong&gt;test by file type separately&lt;/strong&gt;, rather than relying on a tool's claimed "average ratio."&lt;/p&gt;

&lt;h3&gt;
  
  
  Tool Comparison (Archive Compression Tools)
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;The table below covers archive compression tools only. The "compression ratio" of content compression tools depends on the target format and quality parameters, which are not on the same dimension and cannot be directly compared.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool/Algorithm&lt;/th&gt;
&lt;th&gt;Text Ratio&lt;/th&gt;
&lt;th&gt;Bitmap Ratio&lt;/th&gt;
&lt;th&gt;Already-compressed Media&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;gzip (DEFLATE)&lt;/td&gt;
&lt;td&gt;3x ~ 5x&lt;/td&gt;
&lt;td&gt;2x ~ 4x&lt;/td&gt;
&lt;td&gt;~1x&lt;/td&gt;
&lt;td&gt;Fast, best compatibility&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xz (LZMA2)&lt;/td&gt;
&lt;td&gt;5x ~ 8x&lt;/td&gt;
&lt;td&gt;3x ~ 5x&lt;/td&gt;
&lt;td&gt;~1x&lt;/td&gt;
&lt;td&gt;High ratio, slow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7-Zip (LZMA2)&lt;/td&gt;
&lt;td&gt;5x ~ 8x&lt;/td&gt;
&lt;td&gt;3x ~ 5x&lt;/td&gt;
&lt;td&gt;~1x&lt;/td&gt;
&lt;td&gt;Supports solid compression&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zstandard&lt;/td&gt;
&lt;td&gt;4x ~ 6x&lt;/td&gt;
&lt;td&gt;3x ~ 4x&lt;/td&gt;
&lt;td&gt;~1x&lt;/td&gt;
&lt;td&gt;Best speed/ratio balance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Brotli&lt;/td&gt;
&lt;td&gt;4x ~ 7x&lt;/td&gt;
&lt;td&gt;3x ~ 4x&lt;/td&gt;
&lt;td&gt;~1x&lt;/td&gt;
&lt;td&gt;Optimized for web text&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It must be emphasized that for already-compressed media like JPEG or H.264, &lt;strong&gt;lossless archive tools (gzip, 7z) cannot compress them further&lt;/strong&gt;. To reduce the size of such files, you must turn to lossy re-encoding tools designed for that media type.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recommendations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;For text, source code, and logs, prioritize LZMA2-based tools (7-Zip, xz) for the highest ratio.&lt;/li&gt;
&lt;li&gt;For a balance of speed and ratio, Zstandard is the modern default, offering adjustable levels from 1 to 22.&lt;/li&gt;
&lt;li&gt;To shrink already-compressed media, do not rely on archive tools—use lossy re-encoding solutions for the corresponding type.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Dimension 2: Compression Speed
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Evaluation Criteria
&lt;/h3&gt;

&lt;p&gt;Compression speed refers to the amount of data processed per unit of time, commonly expressed in MB/s. But two details are often overlooked:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Speed is strongly correlated with compression level&lt;/strong&gt;. The same algorithm may be 10x faster at its lowest level than at its highest, while the ratio improvement is only a few percentage points. Evaluation must fix the compression level.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single-threaded vs. multi-threaded differences&lt;/strong&gt;. Modern tools like Zstandard, LZMA2, and xz all support multi-threading, and throughput can multiply on multi-core machines.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Time cost is a key selection consideration. For one-time archiving, slower is acceptable; but for real-time transmission or CI/CD pipelines, speed is often more important than the maximum compression ratio.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tool Comparison
&lt;/h3&gt;

&lt;p&gt;The table below shows approximate throughput under typical conditions (text data, mid-range compression level) (archive compression tools only):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;Single-thread Throughput&lt;/th&gt;
&lt;th&gt;Multi-thread Support&lt;/th&gt;
&lt;th&gt;Decompression Speed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;gzip&lt;/td&gt;
&lt;td&gt;-6&lt;/td&gt;
&lt;td&gt;~50 MB/s&lt;/td&gt;
&lt;td&gt;Limited (pigz)&lt;/td&gt;
&lt;td&gt;~200 MB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xz&lt;/td&gt;
&lt;td&gt;-6&lt;/td&gt;
&lt;td&gt;~10 MB/s&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;~50 MB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zstandard&lt;/td&gt;
&lt;td&gt;-3&lt;/td&gt;
&lt;td&gt;~400 MB/s&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;~1000 MB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zstandard&lt;/td&gt;
&lt;td&gt;-19&lt;/td&gt;
&lt;td&gt;~10 MB/s&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;~1000 MB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Brotli&lt;/td&gt;
&lt;td&gt;-6&lt;/td&gt;
&lt;td&gt;~70 MB/s&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;~400 MB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A notable phenomenon: &lt;strong&gt;Zstandard at level 3 approaches gzip's compression ratio at level 6, but is nearly 10x faster&lt;/strong&gt;. This is the core advantage of modern algorithms over classic DEFLATE.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recommendations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;For interactive operations or frequently invoked scenarios, choose high-throughput tools (low-level Zstandard, gzip).&lt;/li&gt;
&lt;li&gt;For offline archiving or cold storage preparation, slower high-compression tools (xz, high-level Zstandard) are acceptable.&lt;/li&gt;
&lt;li&gt;Always enable multi-threading and explicitly record the core count and level in benchmarks.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Dimension 3: Quality Retention
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Evaluation Criteria
&lt;/h3&gt;

&lt;p&gt;For lossy compression tools, "compression ratio" and "quality loss" are two sides of the same coin. When evaluating quality retention, focus on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Granularity of adjustable quality parameters&lt;/strong&gt;: Whether fine-grained quality control is available (e.g., CRF 1~51, or quality 1~100).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Objective quality metrics&lt;/strong&gt;: PSNR, SSIM, VMAF, and similar metrics can quantify the degree of quality loss.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subjective quality performance&lt;/strong&gt;: Some encoders produce better subjective quality at low bitrates than others, even when objective metrics are similar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two-pass encoding support&lt;/strong&gt;: Enables more precise control of target bitrate or file size.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tool Comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool Type&lt;/th&gt;
&lt;th&gt;Typical Tools&lt;/th&gt;
&lt;th&gt;Quality Control&lt;/th&gt;
&lt;th&gt;Subjective Quality&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Lossy image&lt;/td&gt;
&lt;td&gt;libjpeg / mozjpeg&lt;/td&gt;
&lt;td&gt;quality 1~100&lt;/td&gt;
&lt;td&gt;mozjpeg smaller at same quality&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Modern image formats&lt;/td&gt;
&lt;td&gt;libwebp / libavif&lt;/td&gt;
&lt;td&gt;quality 1~100&lt;/td&gt;
&lt;td&gt;AVIF clearly better than JPEG at low quality&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Video encoding&lt;/td&gt;
&lt;td&gt;x264 / x265&lt;/td&gt;
&lt;td&gt;CRF 18~28&lt;/td&gt;
&lt;td&gt;x265 smaller at same CRF but slower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Modern video encoding&lt;/td&gt;
&lt;td&gt;libvpx / SVT-AV1&lt;/td&gt;
&lt;td&gt;CRF + bitrate constraint&lt;/td&gt;
&lt;td&gt;AV1 highest ratio, extremely slow encoding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audio encoding&lt;/td&gt;
&lt;td&gt;libmp3lame / libopus&lt;/td&gt;
&lt;td&gt;bitrate / VBR&lt;/td&gt;
&lt;td&gt;Opus significantly better than MP3 at low bitrates&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Taking video as an example, &lt;code&gt;ffmpeg&lt;/code&gt; with &lt;code&gt;libx265&lt;/code&gt; at CRF 24 typically reduces file size by 30%~50% compared to &lt;code&gt;libx264&lt;/code&gt; at CRF 24, while the VMAF score difference is within 2 points and is subjectively almost imperceptible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recommendations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Image scenarios: For compatibility priority, use mozjpeg; for maximum compression ratio where the environment supports it, use AVIF.&lt;/li&gt;
&lt;li&gt;Video scenarios: For distribution and archiving, choose x265 or SVT-AV1; for real-time communication, choose VP9 or AV1 real-time mode.&lt;/li&gt;
&lt;li&gt;Audio scenarios: Use Opus for speech; AAC for music distribution; consider MP3 only for compatibility needs.&lt;/li&gt;
&lt;li&gt;Always combine objective metrics (VMAF, SSIM) with subjective blind testing—do not rely on bitrate alone.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Dimension 4: Format Support
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Evaluation Criteria
&lt;/h3&gt;

&lt;p&gt;A compression tool's value depends heavily on how many formats it can handle. Evaluation focuses on two layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Archive formats&lt;/strong&gt;: Support for containers and compression algorithms like ZIP, 7Z, TAR, GZ, XZ, ZST.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content formats&lt;/strong&gt;: PDF, images (JPEG/PNG/WebP/AVIF), video (MP4/MKV/MOV), documents (Office), audio (MP3/AAC/FLAC/Opus).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Many tools are strong in only one layer. For example, 7-Zip excels at archive formats but does almost no content re-encoding; FFmpeg excels at audio/video transcoding but does not handle archiving. &lt;strong&gt;True "all-in-one" tools are rare&lt;/strong&gt;, and in most cases a combination is needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tool Comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Archive Formats&lt;/th&gt;
&lt;th&gt;Image Re-encoding&lt;/th&gt;
&lt;th&gt;Video Transcoding&lt;/th&gt;
&lt;th&gt;Audio Transcoding&lt;/th&gt;
&lt;th&gt;PDF Processing&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;7-Zip&lt;/td&gt;
&lt;td&gt;Archive&lt;/td&gt;
&lt;td&gt;Rich&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FFmpeg&lt;/td&gt;
&lt;td&gt;Content&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ImageMagick&lt;/td&gt;
&lt;td&gt;Content&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ghostscript&lt;/td&gt;
&lt;td&gt;Content&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;qpdf / cpdf&lt;/td&gt;
&lt;td&gt;Content&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Online services&lt;/td&gt;
&lt;td&gt;Mixed&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Recommendations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;For single file-type scenarios, choose a specialized tool for that domain (e.g., FFmpeg for video, Ghostscript for PDF).&lt;/li&gt;
&lt;li&gt;For diverse file-type scenarios, build a toolchain: 7-Zip for archiving, FFmpeg/ImageMagick for media, Ghostscript for PDF.&lt;/li&gt;
&lt;li&gt;Online services suit ad-hoc needs but are not suitable for large volumes or sensitive files—see Dimension 5.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Dimension 5: Security and Privacy
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Evaluation Criteria
&lt;/h3&gt;

&lt;p&gt;Compression involves data reading, processing, and storage. The security dimension has three layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Data processing location&lt;/strong&gt;: Local processing vs. cloud upload. Local processing never leaves the device, offering the highest privacy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transmission and storage encryption&lt;/strong&gt;: Whether archives support encryption (AES-256), whether file names can be encrypted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supply chain security&lt;/strong&gt;: Whether the tool is open source, auditable, and has a known vulnerability history.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For enterprises or scenarios involving sensitive information, this dimension is often a &lt;strong&gt;veto factor&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local Processing vs. Online Upload
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Processing Method&lt;/th&gt;
&lt;th&gt;Privacy Risk&lt;/th&gt;
&lt;th&gt;Speed&lt;/th&gt;
&lt;th&gt;Applicable Scenarios&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pure local CLI/GUI&lt;/td&gt;
&lt;td&gt;Very low&lt;/td&gt;
&lt;td&gt;Depends on hardware&lt;/td&gt;
&lt;td&gt;Sensitive files, large batches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Online service (upload)&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Fast (cloud compute)&lt;/td&gt;
&lt;td&gt;Public assets, ad-hoc needs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hybrid (encrypt locally, then upload)&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Teams needing collaboration&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Online services typically store files temporarily on servers. Some claim "deleted after processing," but this is hard for users to verify. For sensitive files like contracts, ID documents, and medical images, local processing should be mandatory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Encryption Capability Comparison
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;7-Zip&lt;/strong&gt;: Supports AES-256 encryption with optional filename encryption; the de facto standard for archive encryption.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ZIP&lt;/strong&gt;: Traditional ZIP encryption (ZipCrypto) is insecure; use WinZip's AES extension instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GPG&lt;/strong&gt;: Asymmetric encryption, suitable for file transfer encryption, but not a compression tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Recommendations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;For classified or compliance scenarios, mandate local open-source tools (7-Zip, GPG).&lt;/li&gt;
&lt;li&gt;When encrypted archiving is needed, use 7-Zip's AES-256 with filename encryption.&lt;/li&gt;
&lt;li&gt;Stay vigilant about online services; use them only for publicly shareable assets.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Dimension 6: Usability
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Evaluation Criteria
&lt;/h3&gt;

&lt;p&gt;Usability determines whether a tool can truly be adopted. Key evaluation points include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Interaction form&lt;/strong&gt;: CLI (command line) vs. GUI (graphical interface) vs. API (programming interface).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch processing capability&lt;/strong&gt;: Whether directory recursion, wildcards, and task queues are supported.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation integration&lt;/strong&gt;: How easily it embeds into scripts, CI/CD pipelines, and scheduled tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability&lt;/strong&gt;: Whether progress, logs, and error codes are provided for troubleshooting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CLI tools are powerful but have a steep learning curve; GUI tools are easy to pick up but hard to automate. The ideal choice depends on the user's technical background and frequency of use.&lt;/p&gt;

&lt;h3&gt;
  
  
  CLI vs. GUI Comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;CLI Tools&lt;/th&gt;
&lt;th&gt;GUI Tools&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Learning cost&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Batch processing&lt;/td&gt;
&lt;td&gt;Strong (script-driven)&lt;/td&gt;
&lt;td&gt;Implementation-dependent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automation&lt;/td&gt;
&lt;td&gt;Natively supported&lt;/td&gt;
&lt;td&gt;Usually unsupported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parameter granularity&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Limited by interface&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Suited for&lt;/td&gt;
&lt;td&gt;Developers, ops&lt;/td&gt;
&lt;td&gt;General office users&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Recommendations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Developers and ops: Use CLI tools primarily (FFmpeg, 7-Zip, zstd), paired with shell scripts for automation.&lt;/li&gt;
&lt;li&gt;General office users: Choose GUI tools that support batch drag-and-drop (e.g., Bandizip, HandBrake's graphical interface).&lt;/li&gt;
&lt;li&gt;Enterprise workflows: Choose solutions that provide APIs or SDKs for easy integration into existing systems.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Dimension 7: Cost and Licensing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Evaluation Criteria
&lt;/h3&gt;

&lt;p&gt;Cost is not just the purchase price; it also includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;License type&lt;/strong&gt;: Open source (GPL, BSD, MIT, LGPL) vs. commercial proprietary vs. free but closed source.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commercial restrictions&lt;/strong&gt;: Some tools are free for personal use but require payment for commercial use (e.g., WinRAR).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Patent risk&lt;/strong&gt;: Some codec formats (e.g., H.264, HEVC) involve patent licensing fees; enterprises distributing them must be careful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintenance and support&lt;/strong&gt;: Open-source tools rely mainly on community support; commercial tools usually offer SLAs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tool Licensing Comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;License&lt;/th&gt;
&lt;th&gt;Commercial Use&lt;/th&gt;
&lt;th&gt;Patent Risk&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;7-Zip&lt;/td&gt;
&lt;td&gt;Archive&lt;/td&gt;
&lt;td&gt;LGPL&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WinRAR&lt;/td&gt;
&lt;td&gt;Archive&lt;/td&gt;
&lt;td&gt;Proprietary&lt;/td&gt;
&lt;td&gt;Commercial requires payment&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zstandard&lt;/td&gt;
&lt;td&gt;Archive&lt;/td&gt;
&lt;td&gt;BSD&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FFmpeg&lt;/td&gt;
&lt;td&gt;Content&lt;/td&gt;
&lt;td&gt;LGPL/GPL (configurable)&lt;/td&gt;
&lt;td&gt;Watch codec licenses&lt;/td&gt;
&lt;td&gt;H.264/HEVC involve patents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;x264/x265&lt;/td&gt;
&lt;td&gt;Content&lt;/td&gt;
&lt;td&gt;GPL&lt;/td&gt;
&lt;td&gt;Commercial requires license&lt;/td&gt;
&lt;td&gt;HEVC patent pool complex&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SVT-AV1&lt;/td&gt;
&lt;td&gt;Content&lt;/td&gt;
&lt;td&gt;BSD&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;AV1 patents open&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Patent risk is the most easily overlooked trap in enterprise selection&lt;/strong&gt;. For example, using x265 to encode and distribute H.265 video in a product may require paying licensing fees to patent pools like MPEG LA and HEVC Advance. AV1, although slow to encode, is safer on the patent front.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recommendations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Personal use: Open-source tools meet the vast majority of needs.&lt;/li&gt;
&lt;li&gt;Enterprise commercial use: Prefer BSD/MIT-licensed tools to avoid GPL contagion; when distributing video, evaluate HEVC patent costs and switch to AV1 if necessary.&lt;/li&gt;
&lt;li&gt;Teams needing official support: Evaluate the total cost of ownership (TCO) of commercial solutions, including license fees and operational costs.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Comprehensive Scoring Matrix
&lt;/h2&gt;

&lt;p&gt;By quantifying the 7 dimensions on a 1~5 scale, you can build a comprehensive scoring matrix. The table below uses several typical tool categories as examples to show how to use this matrix for horizontal comparison (higher scores are better):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;7-Zip&lt;/th&gt;
&lt;th&gt;FFmpeg&lt;/th&gt;
&lt;th&gt;Zstandard&lt;/th&gt;
&lt;th&gt;Online Service&lt;/th&gt;
&lt;th&gt;Commercial GUI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tool Category&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Archive&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Content&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Archive&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Mixed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Mixed&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compression ratio&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;4 (media)&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compression speed&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quality retention&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Format support&lt;/td&gt;
&lt;td&gt;4 (archive)&lt;/td&gt;
&lt;td&gt;5 (media)&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security &amp;amp; privacy&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usability&lt;/td&gt;
&lt;td&gt;3 (CLI)/4 (GUI)&lt;/td&gt;
&lt;td&gt;2 (CLI)&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost &amp;amp; licensing&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Weighted total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;29&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;24&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;23&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;23&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Cross-Category Comparison Note&lt;/strong&gt;: The scores for 7-Zip (archive) and FFmpeg (content) in the table above are not directly comparable—they solve problems at different levels. 7-Zip's "compression ratio 5" refers to its lossless archiving capability for uncompressed data, while FFmpeg's "compression ratio 4" refers to its lossy re-encoding capability for audio/video. The weighted total is only for demonstrating the scoring method; in practice, first determine which type of tool you need, then compare within the same category.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Note: The weighted total is only an example. In practice, weight each dimension according to the scenario. For example, enterprise batch processing should give high weight to "security and privacy," while personal office should give high weight to "usability."&lt;/p&gt;




&lt;h2&gt;
  
  
  Recommended Tools by Scenario
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Scenario 1: Personal Office
&lt;/h3&gt;

&lt;p&gt;Requirements: Diverse file types (PDF, images, Office documents), low frequency, low automation requirements, high usability requirements.&lt;/p&gt;

&lt;p&gt;Recommended combination:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;General archiving: 7-Zip (free, comprehensive formats, strong encryption)&lt;/li&gt;
&lt;li&gt;PDF compression: Ghostscript command line or graphical tools built on it&lt;/li&gt;
&lt;li&gt;Image compression: Local tools based on mozjpeg or libwebp&lt;/li&gt;
&lt;li&gt;Video compression: HandBrake (a graphical front-end for FFmpeg with friendly presets)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Scenario 2: Developer
&lt;/h3&gt;

&lt;p&gt;Requirements: Needs to embed in scripts and CI/CD, pursues controllability and reproducibility, high requirements for CLI and API friendliness.&lt;/p&gt;

&lt;p&gt;Recommended combination:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Text and archiving: Zstandard (balanced speed and ratio, multi-threaded) or xz (extreme ratio)&lt;/li&gt;
&lt;li&gt;Image processing: ImageMagick + mozjpeg&lt;/li&gt;
&lt;li&gt;Video transcoding: FFmpeg + libx264/libx265/SVT-AV1, choosing the encoder as needed&lt;/li&gt;
&lt;li&gt;PDF processing: Ghostscript, qpdf, cpdf&lt;/li&gt;
&lt;li&gt;Automation: Orchestrate with shell or Python, recording logs and exit codes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Scenario 3: Enterprise Batch Processing
&lt;/h3&gt;

&lt;p&gt;Requirements: Large data volumes, strict compliance requirements, need for audit and access control, may involve patents and licensing.&lt;/p&gt;

&lt;p&gt;Recommended combination:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Archiving and encryption: 7-Zip (AES-256) + internal audit process&lt;/li&gt;
&lt;li&gt;Media transcoding: Self-built FFmpeg cluster, prioritizing SVT-AV1 to avoid HEVC patent risk&lt;/li&gt;
&lt;li&gt;PDF processing: Ghostscript cluster + file permission management&lt;/li&gt;
&lt;li&gt;Monitoring: Integrate into a task queue (e.g., Celery, Airflow), recording each task's processing time, compression ratio, and quality metrics&lt;/li&gt;
&lt;li&gt;Security: All processing done locally or in a private cloud; uploading to public network services is prohibited&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Q1: Can free open-source tools really meet enterprise needs?
&lt;/h3&gt;

&lt;p&gt;In most scenarios, yes. Tools like 7-Zip, FFmpeg, Zstandard, and Ghostscript are already widely adopted in enterprise production environments. The key point is that open-source tools are usually powerful enough, but lack official SLAs and commercial support. Enterprises must bear the operational and troubleshooting costs themselves and evaluate the patent licensing risks of relevant codecs. For industries with extremely high compliance requirements (such as finance and healthcare), it is recommended to build internal audit and rollback mechanisms on top of open-source tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q2: Can online compression services be used for work files?
&lt;/h3&gt;

&lt;p&gt;It is not recommended for sensitive work files. Online services carry data leakage risks during transmission and processing, and the promise of "deleted after processing" is hard to verify. Even for public assets, frequently uploading large files consumes bandwidth and time. For work files, local processing should be mandatory; only consider online services when files are explicitly public and the need is a one-off.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q3: Is a higher compression level always better?
&lt;/h3&gt;

&lt;p&gt;No. The higher the compression level, the slower the speed, while the marginal gain in compression ratio diminishes. Taking Zstandard as an example, going from level 3 to level 19 may improve the ratio by only 10%~15%, but compression speed drops by tens of times. When selecting, find the inflection point on the "speed-ratio" curve according to the scenario, rather than blindly pursuing the highest level. Typically, levels 3~6 cover most everyday needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q4: How do you evaluate the quality of a new tool?
&lt;/h3&gt;

&lt;p&gt;Score it on each of the 7 dimensions in this article, and prepare a test set covering multiple file types for benchmarking. Focus on recording: compression ratio for each file type, compression and decompression throughput, quality metrics for lossy compression (PSNR/SSIM/VMAF), multi-threading support, and licensing and patent status. Only by horizontally comparing existing tools with the same test set can you reach an objective conclusion.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;There is no silver bullet for file compression tool selection. A tool that leads in compression ratio may lag in speed or usability; a free open-source tool may hide patent risks; a convenient online service may introduce unacceptable privacy concerns.&lt;/p&gt;

&lt;p&gt;The value of the 7-dimension evaluation framework is that &lt;strong&gt;it forces you to decompose the vague notion of "good or bad" into quantifiable, comparable concrete metrics&lt;/strong&gt;. Compression ratio, compression speed, quality retention, format support, security, usability, cost and licensing—each dimension corresponds to a real engineering constraint, and ignoring any one of them can lead to a selection mistake.&lt;/p&gt;

&lt;p&gt;In practice, first clarify the usage scenario and constraints (file types, data volume, compliance requirements, frequency of use), then assign weights to the 7 dimensions, and finally score horizontally using a uniform test set. This structured approach is more reliable than relying on vendor marketing or a single review article, and it is easier to build consensus within a team. Once you master this framework, you can quickly judge whether any new tool is worth adopting—rather than being led by marketing copy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.uglypear.com/en/blog/archive-vs-content-compression.html" rel="noopener noreferrer"&gt;Why Zipping Files Doesn't Actually Compress Them&lt;/a&gt;—A detailed explanation of the essential difference between archive compression and content compression, with process comparisons and real-world examples. This is prerequisite knowledge for understanding the selection framework in this article.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.uglypear.com/en/blog/file-compression-complete-guide.html" rel="noopener noreferrer"&gt;Complete File Compression Guide&lt;/a&gt;—A comprehensive tutorial from compression principles to practical operations.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>compressiontools</category>
      <category>toolselection</category>
      <category>compressionratio</category>
      <category>compressionspeed</category>
    </item>
    <item>
      <title>Batch Compress 1000 Images with Python Pillow: Complete Guide</title>
      <dc:creator>Uglypear Data</dc:creator>
      <pubDate>Mon, 03 Aug 2026 05:49:52 +0000</pubDate>
      <link>https://dev.to/uglypeardata/batch-compress-1000-images-with-python-pillow-complete-guide-5fka</link>
      <guid>https://dev.to/uglypeardata/batch-compress-1000-images-with-python-pillow-complete-guide-5fka</guid>
      <description>&lt;h2&gt;
  
  
  Why Batch Compress Images
&lt;/h2&gt;

&lt;p&gt;You have 1000 high-resolution photos exported from a camera, each around 8MB, and the entire directory consumes nearly 8GB. If the goal is uploading to a website, embedding into a presentation, or sending via email, that volume is entirely unacceptable. Compressing them one by one in a graphical editor is both inefficient and error-prone—this is exactly where scripted batch processing shines.&lt;/p&gt;

&lt;p&gt;Python's Pillow library is the de facto standard for image processing. It provides read and write support for mainstream formats including JPEG, PNG, WebP, BMP, and TIFF, along with fine-grained control over quality factors, sampling rates, and color modes. With a few dozen lines of Python, you can traverse an entire directory tree, apply a uniform compression strategy, and preserve the original folder structure in the output.&lt;/p&gt;

&lt;p&gt;This article starts from Pillow's basic usage and progressively builds a complete, runnable, multithreaded batch compression script. It also covers practical engineering details such as EXIF preservation, format conversion, and intelligent parameter selection.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pillow Installation and Basic Usage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;Pillow is the actively maintained fork of PIL (Python Imaging Library), but the import name remains &lt;code&gt;PIL&lt;/code&gt;. Install it with pip:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;Pillow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you need to handle a large volume of images or want faster decoding, install the full version with plugin support:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"Pillow[all]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installation, verify the version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;__version__&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__version__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# e.g., 10.4.0
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Basic Operations
&lt;/h3&gt;

&lt;p&gt;The core entry point of Pillow is the &lt;code&gt;Image&lt;/code&gt; class. The three most common operations are open, modify, and save:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;

&lt;span class="c1"&gt;# Open an image (lazy loading; pixel data is read on first access)
&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;photo.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# JPEG (4000, 3000) RGB
&lt;/span&gt;
&lt;span class="c1"&gt;# Get a pixel value
&lt;/span&gt;&lt;span class="n"&gt;pixel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getpixel&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Resize
&lt;/span&gt;&lt;span class="n"&gt;resized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1920&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1080&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Save
&lt;/span&gt;&lt;span class="n"&gt;resized&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;photo_small.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few details are worth noting: the object returned by &lt;code&gt;Image.open()&lt;/code&gt; holds a file reference that is not released until explicitly closed or the &lt;code&gt;with&lt;/code&gt; block exits. In batch processing, always use a context manager or call &lt;code&gt;close()&lt;/code&gt; explicitly, otherwise file handles will leak.&lt;/p&gt;




&lt;h2&gt;
  
  
  Single Image Compression Examples
&lt;/h2&gt;

&lt;p&gt;The foundation of batch compression is single-image processing. We first implement a function that supports JPEG quality adjustment, resolution downscaling, and format conversion.&lt;/p&gt;

&lt;h3&gt;
  
  
  JPEG Quality Adjustment
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;quality&lt;/code&gt; parameter of JPEG ranges from 1 to 100 and directly controls the scaling of the quantization table. It is the primary knob for balancing file size and image quality:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compress_jpeg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Compress a JPEG with the specified quality factor&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# JPEG does not support transparency; RGBA/P modes must be converted first
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGBA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPEG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;optimize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;# Enable Huffman encoding optimization
&lt;/span&gt;            &lt;span class="n"&gt;progressive&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;# Generate progressive JPEG; slightly larger but better loading experience
&lt;/span&gt;        &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Compare different quality factors
&lt;/span&gt;&lt;span class="nf"&gt;compress_jpeg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;photo.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;q95.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;compress_jpeg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;photo.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;q75.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;compress_jpeg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;photo.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;q50.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;optimize=True&lt;/code&gt; makes Pillow scan the data an extra time during saving to rebuild an optimal Huffman encoding table. This typically reduces the file size by another 2-5% at the cost of slightly slower saving.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resolution Adjustment
&lt;/h3&gt;

&lt;p&gt;For web display, a 4000x3000 original is far larger than necessary. Using &lt;code&gt;thumbnail()&lt;/code&gt; to downscale proportionally is the most effective approach—halving the resolution reduces the file size by roughly 75%:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;resize_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1920&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Scale the longest edge to max_size while preserving the aspect ratio&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# thumbnail modifies in place and never exceeds the specified dimensions
&lt;/span&gt;        &lt;span class="c1"&gt;# Image.Resampling.LANCZOS is the best-quality downsampling algorithm
&lt;/span&gt;        &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resampling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LANCZOS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPEG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;optimize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;resize_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;photo.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;photo_1920.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1920&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference between &lt;code&gt;thumbnail()&lt;/code&gt; and &lt;code&gt;resize()&lt;/code&gt; is that &lt;code&gt;thumbnail()&lt;/code&gt; preserves the aspect ratio and never enlarges the image—the final dimensions are always less than or equal to the specified values. &lt;code&gt;resize()&lt;/code&gt; forces the image to the exact target dimensions. In batch processing, you almost always want &lt;code&gt;thumbnail()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Format Conversion
&lt;/h3&gt;

&lt;p&gt;Converting PNG to WebP is a common optimization—WebP is 26% smaller than PNG and 25-35% smaller than JPEG at equivalent quality, while also supporting transparency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;convert_to_webp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lossless&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Convert any format to WebP&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WebP&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;lossless&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;lossless&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# When True, uses lossless mode
&lt;/span&gt;            &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;            &lt;span class="c1"&gt;# Compression effort 0-6; 6 is slowest but smallest
&lt;/span&gt;        &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;convert_to_webp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;icon.png&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;icon.webp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;convert_to_webp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;logo.png&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;logo_lossless.webp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lossless&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;method&lt;/code&gt; parameter controls compression effort, ranging from 0 to 6. Higher values yield better compression ratios but take longer. For batch processing where ultimate file size matters, set it to 6; for speed, 4 is a good balance.&lt;/p&gt;




&lt;h2&gt;
  
  
  Complete Batch Compression Script
&lt;/h2&gt;

&lt;p&gt;Now we assemble the single-image logic into a complete batch script. This script traverses all images in the input directory, preserves the original folder structure in the output, and displays processing progress along with the overall compression results.&lt;/p&gt;

&lt;p&gt;The flowchart below illustrates the overall batch processing workflow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F87a365bpgtfaexzusoll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F87a365bpgtfaexzusoll.png" alt=" " width="800" height="1532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The complete script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
batch_compress.py - Batch image compression script
Usage: python batch_compress.py &amp;lt;input_dir&amp;gt; &amp;lt;output_dir&amp;gt; [--quality 75] [--max-size 1920]
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;

&lt;span class="n"&gt;SUPPORTED_FORMATS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.jpeg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.png&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.webp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.bmp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.tiff&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.tif&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compress_single&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1920&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;target_format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keep_exif&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Compress a single image&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# 1. Extract EXIF data (capture time, camera model, GPS, etc.)
&lt;/span&gt;        &lt;span class="n"&gt;exif_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exif&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;keep_exif&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;

        &lt;span class="c1"&gt;# 2. Color mode conversion: JPEG does not support transparency
&lt;/span&gt;        &lt;span class="n"&gt;out_format&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_format&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPEG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;out_format&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPEG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGBA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="c1"&gt;# Composite onto a white background to avoid black regions after conversion
&lt;/span&gt;            &lt;span class="n"&gt;background&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGBA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;background&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;paste&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGBA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;background&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGBA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;L&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# 3. Resolution adjustment: only downscale, never upscale
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;max_size&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resampling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LANCZOS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# 4. Save
&lt;/span&gt;        &lt;span class="n"&gt;save_kwargs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;optimize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;out_format&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPEG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;save_kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quality&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;
            &lt;span class="n"&gt;save_kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;progressive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;exif_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;save_kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exif&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exif_data&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;out_format&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WEBP&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;save_kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quality&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;
            &lt;span class="n"&gt;save_kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;method&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;out_format&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PNG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;save_kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;optimize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

        &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;out_format&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;save_kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;batch_compress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1920&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="n"&gt;target_format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keep_exif&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Batch compress an entire directory&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;input_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;output_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Collect all files to process
&lt;/span&gt;    &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_dir&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;suffix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;SUPPORTED_FORMATS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;
                &lt;span class="n"&gt;rel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relative_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;dst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;output_dir&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;rel&lt;/span&gt;
                &lt;span class="c1"&gt;# Adjust extension based on target format
&lt;/span&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;target_format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;dst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_suffix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;target_format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No supported image files found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Found &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; images. Starting compression...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;processed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;total_original&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;total_compressed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Ensure output directory exists
&lt;/span&gt;        &lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;original_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;st_size&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;compress_single&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_format&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keep_exif&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;new_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;st_size&lt;/span&gt;
            &lt;span class="n"&gt;total_original&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;original_size&lt;/span&gt;
            &lt;span class="n"&gt;total_compressed&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;new_size&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
            &lt;span class="n"&gt;new_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;original_size&lt;/span&gt;  &lt;span class="c1"&gt;# Count as original size on failure
&lt;/span&gt;
        &lt;span class="n"&gt;processed&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;pct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;processed&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
        &lt;span class="n"&gt;saved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;new_size&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;original_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;original_size&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pct&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;5.1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;%] (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;processed&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;) &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relative_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
              &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;original_size&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;KB -&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;new_size&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;KB  (-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;saved&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;%)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Summary report
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Done: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;processed&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; succeeded, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; failed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;total_original&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;ratio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total_original&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;total_compressed&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;total_compressed&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;saved_mb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total_original&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;total_compressed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Original size: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;total_original&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; MB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Compressed size: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;total_compressed&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; MB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Space saved: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;saved_mb&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; MB (ratio &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ratio&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;x)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  Failed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; - &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ArgumentParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Batch image compression tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_dir&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Input image directory&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output_dir&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Output directory&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--quality&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPEG/WebP quality factor (1-100)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--max-size&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1920&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Maximum longest edge in pixels&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--format&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Target format (JPEG/WebP/PNG)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--no-exif&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;store_true&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Discard EXIF data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse_args&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nf"&gt;batch_compress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;target_format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;keep_exif&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;no_exif&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usage examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Basic usage&lt;/span&gt;
python batch_compress.py ./photos ./output

&lt;span class="c"&gt;# Convert to WebP, quality 80, max longest edge 2560&lt;/span&gt;
python batch_compress.py ./photos ./output &lt;span class="nt"&gt;--quality&lt;/span&gt; 80 &lt;span class="nt"&gt;--max-size&lt;/span&gt; 2560 &lt;span class="nt"&gt;--format&lt;/span&gt; webp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script has three core design principles: it uses &lt;code&gt;os.walk()&lt;/code&gt; to recursively traverse and preserve the directory structure; it uses &lt;code&gt;relative_to()&lt;/code&gt; to compute relative paths ensuring the output layout matches the input; and it uses &lt;code&gt;Path.stat()&lt;/code&gt; to obtain file sizes for calculating the actual compression effect.&lt;/p&gt;




&lt;h2&gt;
  
  
  Advanced Techniques
&lt;/h2&gt;

&lt;h3&gt;
  
  
  EXIF Information Preservation
&lt;/h3&gt;

&lt;p&gt;EXIF data contains capture time, GPS coordinates, camera parameters, aperture, shutter speed, and other metadata. By default, &lt;code&gt;img.save()&lt;/code&gt; discards this information. To preserve it, you must extract it manually and pass it when saving:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compress_with_exif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;exif&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exif&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Extract raw EXIF bytes
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPEG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;exif&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;exif&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;exif&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Pass None when there is no EXIF
&lt;/span&gt;            &lt;span class="n"&gt;optimize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you only need to retain certain EXIF fields (for example, only the orientation tag), use the &lt;code&gt;getexif()&lt;/code&gt; method to pick items individually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ExifTags&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;keep_orientation_only&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;exif&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getexif&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;orientation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exif&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x0112&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Orientation tag
&lt;/span&gt;        &lt;span class="c1"&gt;# Rotate the image based on the orientation tag
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ImageOps&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ImageOps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exif_transpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPEG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;optimize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ImageOps.exif_transpose()&lt;/code&gt; automatically rotates the image according to the EXIF orientation tag. This is especially useful when processing photos taken with smartphones—many phone sensors are mounted in landscape orientation and rely on the EXIF orientation tag to indicate the correct display direction.&lt;/p&gt;

&lt;h3&gt;
  
  
  PNG to WebP
&lt;/h3&gt;

&lt;p&gt;When converting PNG to WebP, you need to choose between lossy and lossless modes based on the image characteristics. For images with text and sharp lines (icons, UI elements), lossless WebP preserves crisp edges. For photographic content, lossy WebP offers a significant size advantage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;png_to_webp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lossless_threshold&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Intelligently choose lossy or lossless WebP based on image characteristics&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Count colors to determine if this is a simple graphic
&lt;/span&gt;        &lt;span class="n"&gt;colors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getcolors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxcolors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;65536&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;is_simple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colors&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_simple&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Few colors, sharp edges: lossless mode
&lt;/span&gt;            &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WebP&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lossless&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Lossless WebP (color count: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Rich colors, photographic: lossy mode
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WebP&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;82&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Lossy WebP (photographic)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;getcolors()&lt;/code&gt; returns a list of colors or &lt;code&gt;None&lt;/code&gt; (when the color count exceeds &lt;code&gt;maxcolors&lt;/code&gt;). A small number of colors usually indicates a simple graphic such as an icon or screenshot, which is better suited for lossless compression.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smart Parameter Selection
&lt;/h3&gt;

&lt;p&gt;Different images are best suited for different compression strategies. The following function automatically selects the format and parameters based on resolution, transparency, and color count:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;smart_compress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Automatically select the optimal compression strategy based on image characteristics&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
        &lt;span class="n"&gt;pixel_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;
        &lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;
        &lt;span class="n"&gt;has_transparency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGBA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;transparency&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Strategy 1: Has transparency -&amp;gt; WebP (balances transparency and size)
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;has_transparency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pixel_count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2_000_000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;88&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WebP&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Lossy WebP (transparent)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

        &lt;span class="c1"&gt;# Strategy 2: Very large photo -&amp;gt; downscale + JPEG medium quality
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pixel_count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8_000_000&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;2560&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2560&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resampling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LANCZOS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPEG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;optimize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPEG (large image downscaled)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

        &lt;span class="c1"&gt;# Strategy 3: Normal photo -&amp;gt; JPEG higher quality
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pixel_count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;500_000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPEG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;82&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;optimize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPEG (high quality)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

        &lt;span class="c1"&gt;# Strategy 4: Small image -&amp;gt; keep as PNG
&lt;/span&gt;        &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PNG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;optimize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PNG (small image preserved)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The core logic of this strategy is: images with transparency go to WebP, large images are downscaled before compression, normal photos use JPEG, and small images use PNG for fidelity. You can adjust the thresholds based on your actual requirements.&lt;/p&gt;




&lt;h2&gt;
  
  
  Performance Optimization
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Multithreaded Processing
&lt;/h3&gt;

&lt;p&gt;Image compression is a task that mixes I/O-bound and CPU-bound work. Disk read/write and encoding each account for a portion of the time. Python's GIL limits pure CPU parallelism, but Pillow releases the GIL when calling the underlying C libraries for JPEG/WebP encoding, so multithreading can bring substantial speedups:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;concurrent.futures&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ThreadPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;as_completed&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;

&lt;span class="n"&gt;SUPPORTED_FORMATS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.jpeg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.png&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.webp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.bmp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.tiff&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;_print_lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compress_single&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1920&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;exif&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exif&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;max_size&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resampling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LANCZOS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;kwargs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quality&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;optimize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;progressive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;exif&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exif&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exif&lt;/span&gt;
        &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPEG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;batch_compress_threaded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1920&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;input_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;output_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Collect tasks
&lt;/span&gt;    &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_dir&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;suffix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;SUPPORTED_FORMATS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;
                &lt;span class="n"&gt;rel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relative_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;dst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;output_dir&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;rel&lt;/span&gt;
                &lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; images total, processing with &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; threads&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;completed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;total_saved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;ThreadPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_workers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;futures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;compress_single&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;future&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;as_completed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="n"&gt;saved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;st_size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;st_size&lt;/span&gt;
                &lt;span class="n"&gt;total_saved&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;saved&lt;/span&gt;
            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;_print_lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Failed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; - &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;completed&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;_print_lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;completed&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;5.1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;%] (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;completed&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;) &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Done. Space saved: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;total_saved&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; MB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;batch_compress_threaded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./photos&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1920&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The empirical rule for thread count is the number of CPU logical cores. On an 8-core machine, 4-6 threads typically achieve near-optimal speedup. Too many threads can actually degrade performance due to disk I/O contention and memory pressure.&lt;/p&gt;

&lt;p&gt;If you need to go further with parallelism, you can use &lt;code&gt;ProcessPoolExecutor&lt;/code&gt; to bypass the GIL. The tradeoff is that processes cannot share memory, each process must independently load the Pillow library, and startup overhead is higher.&lt;/p&gt;

&lt;h3&gt;
  
  
  Memory Management
&lt;/h3&gt;

&lt;p&gt;Memory consumption becomes a concern when processing high-resolution images. A single 6000x4000 RGB image occupies about 72MB of memory after decoding (6000x4000x3 bytes). If 10 are open simultaneously, that is 720MB.&lt;/p&gt;

&lt;p&gt;Several key memory management principles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gc&lt;/span&gt;

&lt;span class="c1"&gt;# 1. Always use the with statement to ensure file handles and pixel buffers are released promptly
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;safe_compress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# 2. Copy the image if you need to modify it, avoiding operations on the original
&lt;/span&gt;        &lt;span class="n"&gt;work&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;# img is released; work is still in scope
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;work&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;work&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;work&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;work&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JPEG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;optimize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;work&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# 3. Close explicitly
&lt;/span&gt;
&lt;span class="c1"&gt;# 4. Trigger garbage collection periodically during batch processing
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;batch_with_gc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, &lt;code&gt;Image.MAX_IMAGE_PIXELS&lt;/code&gt; defaults to a limit of approximately 178 million pixels (about 8900x8900). Exceeding this raises a &lt;code&gt;DecompressionBombError&lt;/code&gt;. If you genuinely need to process very large images, you can raise this threshold, but be mindful of memory consumption:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MAX_IMAGE_PIXELS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;  &lt;span class="c1"&gt;# Disable the limit (use with caution)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Compression Results Comparison
&lt;/h2&gt;

&lt;p&gt;The table below shows measured data from a set of 50 smartphone photos (original average 6.5MB, 4000x3000 pixels). All tests ran on the same hardware, with resolution uniformly downscaled to a longest edge of 1920:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Quality Factor&lt;/th&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;th&gt;Average Size&lt;/th&gt;
&lt;th&gt;Ratio&lt;/th&gt;
&lt;th&gt;Subjective Quality&lt;/th&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Original&lt;/td&gt;
&lt;td&gt;JPEG&lt;/td&gt;
&lt;td&gt;6.5 MB&lt;/td&gt;
&lt;td&gt;1.0x&lt;/td&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;95&lt;/td&gt;
&lt;td&gt;JPEG&lt;/td&gt;
&lt;td&gt;1.8 MB&lt;/td&gt;
&lt;td&gt;3.6x&lt;/td&gt;
&lt;td&gt;Virtually identical&lt;/td&gt;
&lt;td&gt;High-quality archival&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;85&lt;/td&gt;
&lt;td&gt;JPEG&lt;/td&gt;
&lt;td&gt;0.92 MB&lt;/td&gt;
&lt;td&gt;7.1x&lt;/td&gt;
&lt;td&gt;Imperceptible difference&lt;/td&gt;
&lt;td&gt;Website hero images&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;75&lt;/td&gt;
&lt;td&gt;JPEG&lt;/td&gt;
&lt;td&gt;0.58 MB&lt;/td&gt;
&lt;td&gt;11.2x&lt;/td&gt;
&lt;td&gt;Slight artifacts on close inspection&lt;/td&gt;
&lt;td&gt;Thumbnails, listing pages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;65&lt;/td&gt;
&lt;td&gt;JPEG&lt;/td&gt;
&lt;td&gt;0.42 MB&lt;/td&gt;
&lt;td&gt;15.5x&lt;/td&gt;
&lt;td&gt;Visible blocky artifacts&lt;/td&gt;
&lt;td&gt;Not recommended&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;td&gt;JPEG&lt;/td&gt;
&lt;td&gt;0.28 MB&lt;/td&gt;
&lt;td&gt;23.2x&lt;/td&gt;
&lt;td&gt;Obvious distortion&lt;/td&gt;
&lt;td&gt;Tiny previews only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;WebP&lt;/td&gt;
&lt;td&gt;0.51 MB&lt;/td&gt;
&lt;td&gt;12.7x&lt;/td&gt;
&lt;td&gt;Comparable to JPEG 85&lt;/td&gt;
&lt;td&gt;Modern websites&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lossless&lt;/td&gt;
&lt;td&gt;WebP&lt;/td&gt;
&lt;td&gt;4.2 MB&lt;/td&gt;
&lt;td&gt;1.5x&lt;/td&gt;
&lt;td&gt;Perfectly lossless&lt;/td&gt;
&lt;td&gt;When transparency is needed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Several patterns emerge from the data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quality 85 is the cost-effectiveness inflection point&lt;/strong&gt;: it saves nearly half the size compared to 95, with quality differences that are virtually imperceptible to the eye.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Below quality 70, returns diminish rapidly&lt;/strong&gt;: file size continues to decrease, but quality degradation accelerates noticeably.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebP quality factors are not directly equivalent to JPEG&lt;/strong&gt;: WebP 80 produces quality comparable to JPEG 85 but at a smaller size.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lossless WebP only makes sense when transparency is required&lt;/strong&gt;; for photographs, the size advantage is minimal.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Q1: Why do images appear upside down or sideways after compression?
&lt;/h3&gt;

&lt;p&gt;This happens because the EXIF orientation tag from the smartphone is discarded during compression, while the actual pixel data was stored in landscape orientation. The solution is to call &lt;code&gt;ImageOps.exif_transpose(img)&lt;/code&gt; before saving. It rotates the pixel data according to the EXIF orientation tag so the image is correctly oriented before being saved. This way, even if downstream software does not read the EXIF orientation information, the image will display correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q2: Why does memory usage keep growing when processing 1000 images?
&lt;/h3&gt;

&lt;p&gt;The most common cause is failing to close image objects promptly. Always use the &lt;code&gt;with Image.open(...) as img:&lt;/code&gt; context manager to ensure each image is released immediately after processing. Second, in the multithreaded version, if all tasks are submitted at once, the future objects hold references to results until they are consumed, causing memory to accumulate. The solution is to submit tasks in batches using &lt;code&gt;chunksize&lt;/code&gt;, or switch to a producer-consumer queue pattern to control concurrency. Finally, calling &lt;code&gt;gc.collect()&lt;/code&gt; periodically can reclaim memory held by circular references.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q3: Why do transparent areas turn black after converting PNG to JPEG?
&lt;/h3&gt;

&lt;p&gt;The JPEG format does not support transparency. When Pillow converts RGBA to RGB by default, it fills the transparent background with black. The solution is to first create a white-background RGB image, then use &lt;code&gt;paste()&lt;/code&gt; to overlay the original image with the alpha channel as a mask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;background&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;background&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;paste&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;# The 4th channel is alpha
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, convert directly to WebP, which natively supports transparency without any extra handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q4: Why doesn't multithreading deliver a linear speedup?
&lt;/h3&gt;

&lt;p&gt;Image compression involves both disk I/O and CPU encoding. Once the thread count increases beyond a certain point, disk bandwidth becomes the bottleneck—the CPU cannot go faster than the data can be read and written. Additionally, decoded pixel data for high-resolution images is large, and processing multiple large images simultaneously in different threads leads to memory bandwidth contention and reduced cache hit rates. In practice, 4-8 threads typically yield a 2-4x speedup, with diminishing returns beyond that. For mechanical hard drives, 4 threads is recommended; for NVMe SSDs, the count can be increased somewhat.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Batch compressing images with Python Pillow can be broken down into three layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Foundation layer&lt;/strong&gt;: Master the three methods &lt;code&gt;Image.open()&lt;/code&gt;, &lt;code&gt;thumbnail()&lt;/code&gt;, and &lt;code&gt;save()&lt;/code&gt;, combined with the &lt;code&gt;quality&lt;/code&gt; and &lt;code&gt;optimize&lt;/code&gt; parameters, and you can compress a single image. This is the building block for all batch processing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Engineering layer&lt;/strong&gt;: Use &lt;code&gt;os.walk()&lt;/code&gt; to traverse directories, &lt;code&gt;Path.relative_to()&lt;/code&gt; to preserve structure, and &lt;code&gt;concurrent.futures&lt;/code&gt; for parallel processing to scale single-image logic to thousands of images. This layer focuses on correctness, robustness, and throughput.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimization layer&lt;/strong&gt;: Intelligently select formats and parameters based on image characteristics—transparent images go to WebP, large images are downscaled first, small images stay as PNG. Details like EXIF preservation, orientation correction, and memory management determine whether the script can run reliably in a production environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is an empirical rule for quality factor selection: &lt;strong&gt;85 is the threshold of visually lossless quality, 75 is the balance point between size and quality, and below 65 is not recommended for display purposes&lt;/strong&gt;. WebP is now fully supported across modern browsers and should be the preferred format for new projects.&lt;/p&gt;

&lt;p&gt;The value of this script lies not in replacing professional tools but in its customizability. You can adjust every stage according to your actual needs—configure different parameters for specific directories, automatically upload to a CDN after compression, or integrate it into a CI/CD pipeline. Understanding the principles behind each line of code gives you the foundation to handle any image processing scenario.&lt;/p&gt;

</description>
      <category>pythonimagecompression</category>
      <category>pillow</category>
      <category>batchcompress</category>
      <category>imageoptimization</category>
    </item>
    <item>
      <title>Is Using Online Compression Tools a GDPR/PIPL Compliance Risk?</title>
      <dc:creator>Uglypear Data</dc:creator>
      <pubDate>Sat, 01 Aug 2026 03:38:41 +0000</pubDate>
      <link>https://dev.to/uglypeardata/is-using-online-compression-tools-a-gdprpipl-compliance-risk-34g0</link>
      <guid>https://dev.to/uglypeardata/is-using-online-compression-tools-a-gdprpipl-compliance-risk-34g0</guid>
      <description>&lt;h2&gt;
  
  
  Where Compliance Begins
&lt;/h2&gt;

&lt;p&gt;Since China's Data Security Law (DSL) and Personal Information Protection Law (PIPL) took effect in 2021, and with the EU's General Data Protection Regulation (GDPR) in force since 2018, enterprises face unprecedented compliance scrutiny over how they process files. A contract, a financial report, a customer list—each can cross a legal red line during transmission, storage, compression, or conversion.&lt;/p&gt;

&lt;p&gt;File compression and format conversion are routine operations, but legally they all qualify as "data processing activities." The moment data is created, edited, transmitted, or destroyed, it falls under the DSL's scope; the moment a file contains personal information, it also falls under the PIPL's scope (and the GDPR's scope if it concerns EU data subjects). So the answer to "is using an online compression tool a compliance violation?" does not depend on the tool itself. It depends on three variables: the classification level of the file, where the data flows during processing, and whether the enterprise has fulfilled its compliance obligations.&lt;/p&gt;

&lt;p&gt;This article examines the legal requirements, maps out the compliance risks of enterprise file processing, and answers where the compliance boundary of online compression tools lies—across both the Chinese (DSL/PIPL) and international (GDPR) regulatory contexts.&lt;/p&gt;




&lt;h2&gt;
  
  
  I. Core Requirements of the DSL, PIPL, and GDPR
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Data Security Law: Two Core Obligations
&lt;/h3&gt;

&lt;p&gt;China's Data Security Law, effective September 1, 2021, establishes the foundational framework for data security. For enterprise file processing, the core requirements concentrate on two levels:&lt;/p&gt;

&lt;p&gt;The first is &lt;strong&gt;data classification and grading&lt;/strong&gt;. The law requires the state to establish a data classification and grading protection system, and enterprises must classify and grade their own data accordingly. Files must be divided into different levels based on importance and the severity of harm if leaked. Public, internal, sensitive, and core classified information should each receive protection of different intensity. This directly affects tool selection—files of different levels must be matched with processing methods of corresponding security.&lt;/p&gt;

&lt;p&gt;The second is &lt;strong&gt;full-lifecycle secure processing&lt;/strong&gt;. File processing (creation, editing, compression, conversion, transmission, destruction) all constitute data processing activities and must be brought under compliance management. Enterprises must ensure tools themselves do not cause data leakage, and "whether the data flow is controllable" must be the primary evaluation factor.&lt;/p&gt;

&lt;h3&gt;
  
  
  The PIPL: Four Key Constraints
&lt;/h3&gt;

&lt;p&gt;The Personal Information Protection Law, effective November 1, 2021, sets explicit requirements for the collection, storage, use, transmission, and deletion of personal information. Many files enterprises handle contain personal information: employee resumes with ID numbers, customer contracts with contact details, financial statements with bank accounts. The PIPL imposes four main constraints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Minimum necessity&lt;/strong&gt;: Processing personal information shall be limited to the minimum scope necessary to achieve the processing purpose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notice and consent&lt;/strong&gt;: Collecting and using personal information requires informing the individual and obtaining consent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-border transfer restrictions&lt;/strong&gt;: Providing personal information overseas requires meeting statutory conditions such as security assessment, certification, or signing a standard contract.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deletion obligation&lt;/strong&gt;: Once the processing purpose is achieved, personal information should be proactively deleted.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The GDPR: Parallel Obligations
&lt;/h3&gt;

&lt;p&gt;For organizations subject to the GDPR, the obligations overlap significantly with the PIPL, though the legal mechanisms differ:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lawfulness, fairness, and transparency&lt;/strong&gt; (Article 5) mirrors the PIPL's notice-and-consent framework.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data minimization&lt;/strong&gt; (Article 5(1)(c)) is the GDPR equivalent of minimum necessity: collect only what is adequate and necessary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;International data transfers&lt;/strong&gt; (Chapter V) require safeguards such as Standard Contractual Clauses (SCCs), Binding Corporate Rules, or adequacy decisions—functionally similar to the PIPL's cross-border conditions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Records of processing activities&lt;/strong&gt; (Article 30) require controllers and processors to maintain documentation of processing operations, analogous to the DSL's log retention requirement.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The practical takeaway is that an enterprise operating across jurisdictions faces a converging set of obligations: classify data, minimize collection, control cross-border flows, and keep auditable records. The most easily overlooked gap is uploading files containing personal information to online tools hosted on overseas servers. A seemingly ordinary "online compression" operation may already constitute a cross-border transfer, triggering statutory obligations under both the PIPL and the GDPR.&lt;/p&gt;




&lt;h2&gt;
  
  
  II. The Data Classification System and Its Impact on File Processing
&lt;/h2&gt;

&lt;p&gt;Data classification is not only a legal requirement; it is the practical starting point for file processing compliance. Without classification there is no differentiated protection; without differentiated protection, there is no way to judge whether an online compression tool may be used.&lt;/p&gt;

&lt;h3&gt;
  
  
  Classification Logic
&lt;/h3&gt;

&lt;p&gt;Drawing on industry practice, enterprise files can generally be divided into four levels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Public level&lt;/strong&gt;: Information already published or that can be published, such as website announcements. Processing with online tools poses no compliance risk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internal level&lt;/strong&gt;: Information used internally and not disclosed externally, such as internal notices. Using online tools requires evaluating the provider's qualifications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sensitive level&lt;/strong&gt;: Files containing personal information, trade secrets, or important data, such as customer contracts and financial statements. These must be processed locally; uploading to public-network tools is prohibited.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Core level&lt;/strong&gt;: Files involving state secrets or core enterprise assets, such as classified documents. These must be processed in an isolated environment using tools that have passed specialized certification.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Data Classification Processing Flow
&lt;/h3&gt;

&lt;p&gt;The diagram below shows the complete classification flow from file identification to selection of a processing method:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fieisu34n9018rjincgid.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fieisu34n9018rjincgid.png" alt=" " width="800" height="767"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The core logic is: first determine whether the file falls within statutory regulation (personal information, important data, state secrets), then determine the level based on scale and cross-border status, and finally match the processing method. For "sensitive" and "core" level files, the processing method is a hard constraint—once the level is determined, local processing is mandatory with no room for debate about online tools.&lt;/p&gt;




&lt;h2&gt;
  
  
  III. The Three Major Compliance Risks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Risk 1: Cross-Border Data Transfer Risk
&lt;/h3&gt;

&lt;p&gt;When using overseas online file processing tools, file data is transmitted to overseas servers, constituting a cross-border transfer. Under the DSL and PIPL, the export of important data requires passing a security assessment by the national cyberspace administration, and personal information export requires meeting one of the statutory conditions. Under the GDPR (Chapter V), transfers to third countries require appropriate safeguards such as SCCs or an adequacy decision.&lt;/p&gt;

&lt;p&gt;Many employees habitually use foreign online tools to process contracts and reports, unaware that these operations may have triggered cross-border transfer obligations the enterprise never fulfilled. Even when using a domestic provider, if backend servers are deployed overseas or overseas CDN and cloud nodes are used, a cross-border transfer may still occur. The criterion is not "the server the user sees is in their country" but "which jurisdiction the data actually reaches."&lt;/p&gt;

&lt;h3&gt;
  
  
  Risk 2: Third-Party Processing Risk
&lt;/h3&gt;

&lt;p&gt;Online tools typically upload files to third-party servers. Even if the provider promises "immediate deletion after processing," the enterprise still faces three categories of risk:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data leakage risk&lt;/strong&gt;: If the provider's security defenses have vulnerabilities, files may be stolen during storage, transmission, or backup. Several well-known online tool providers have suffered data breaches in recent years.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retention and reuse risk&lt;/strong&gt;: Some providers' privacy policies reserve the right to use uploaded content for service improvement or model training; file contents may be retained and repurposed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lawful compulsion risk&lt;/strong&gt;: The laws of the provider's jurisdiction may authorize local law enforcement to access server data, without the enterprise's knowledge.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For sensitive files, handing them to an uncontrollable third party inherently expands the attack surface. Even without an actual leak, the mere fact that "data has left the enterprise's controllable boundary" puts the enterprise on the defensive during a compliance audit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Risk 3: Log Retention Risk
&lt;/h3&gt;

&lt;p&gt;The DSL requires data processors to retain processing logs for no less than six months. The GDPR similarly requires records of processing activities (Article 30). Enterprises must record "who processed which file and when" to enable tracing if a security incident occurs.&lt;/p&gt;

&lt;p&gt;If employees use personal online tools to process enterprise files, these operations fall outside the enterprise's logging scope, creating a compliance blind spot: the operation time cannot be recorded, the processing target cannot be identified, and the operator cannot be correlated. Once a leakage incident occurs, the enterprise cannot prove it fulfilled its security management obligations. The essence of this risk is "loss of controllability"—the processing occurs outside the enterprise boundary, and the enterprise can neither obtain the logs nor guarantee their authenticity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compliance Risk Assessment Flow
&lt;/h3&gt;

&lt;p&gt;The diagram below shows the decision flow for a compliance risk assessment of file processing operations:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe6xuze7ew3411qrc5cza.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe6xuze7ew3411qrc5cza.png" alt=" " width="800" height="604"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Risk level rises with file level, and for sensitive-level files and above, there is almost no room for "online tools." Enterprises should embed this flow into their tool selection and usage standards rather than relying on individual employees' judgment.&lt;/p&gt;




&lt;h2&gt;
  
  
  IV. Local vs Online Compression: A Compliance Comparison
&lt;/h2&gt;

&lt;p&gt;From a compliance perspective, local and online compression differ fundamentally. The table below shows the differences across seven dimensions:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Local Compression&lt;/th&gt;
&lt;th&gt;Online Compression&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data location&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Stays on the local device; never leaves the enterprise boundary&lt;/td&gt;
&lt;td&gt;Uploaded to third-party servers; leaves controllable scope&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cross-border transfer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not involved; no export-filing obligation&lt;/td&gt;
&lt;td&gt;May constitute a transfer; server location must be assessed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Third-party risk&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No third-party involvement; no leakage or retention risk&lt;/td&gt;
&lt;td&gt;Provider leakage, retention, and lawful-compulsion risks exist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Log controllability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Enterprise can fully record time, target, and operator&lt;/td&gt;
&lt;td&gt;Operations fall outside enterprise logging; compliance blind spot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network dependency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No network required; processing unaffected by network&lt;/td&gt;
&lt;td&gt;Network required; the network link itself is a risk point&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Approval &amp;amp; traceability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Can be incorporated into enterprise workflows; fully traceable&lt;/td&gt;
&lt;td&gt;Hard to incorporate; poor traceability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compliance fit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Suitable for all levels from public to core&lt;/td&gt;
&lt;td&gt;Only suitable for public-level files; prohibited for sensitive and above&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Online compression has compliance shortfalls in four core dimensions—data location, cross-border transfer, third-party risk, and log controllability—while local compression naturally satisfies the legal requirements in all four. This does not mean online compression is entirely unusable; for public-level files, the convenience has value. But for internal-level files and above, local processing is the only reliable way to avoid compliance risk.&lt;/p&gt;




&lt;h2&gt;
  
  
  V. Industry Compliance Recommendations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Government and State-Owned Enterprises
&lt;/h3&gt;

&lt;p&gt;Government agencies and state-owned enterprises often handle files involving state secrets, with the strictest compliance requirements. All file processing must be done on internal networks or locally; using any public-network online tool is prohibited. Classified files must be processed with tools that have passed national confidentiality certification. Electronic official documents should preferably use the OFD format and be compressed and converted through local tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Financial Services
&lt;/h3&gt;

&lt;p&gt;Banks, insurance companies, and securities firms handle files containing large amounts of customer identity and financial information. Compression and conversion of customer data, loan contracts, and account statements should be done locally. Establish a file processing approval workflow recording the operator, time, target, and parameters of each operation, with logs retained for no less than six months. Use a DLP (data loss prevention) system to monitor whether sensitive files are being transmitted externally.&lt;/p&gt;

&lt;h3&gt;
  
  
  Healthcare
&lt;/h3&gt;

&lt;p&gt;Medical institutions handle medical records and examination reports that constitute sensitive personal information. Compression and archiving of medical record files should be done locally within the hospital's system; using any third-party online tool to process patient information is prohibited. Electronic medical record transmission should use encrypted channels. Patient information files must not be uploaded to any third-party online tool, to avoid triggering cross-border transfer obligations.&lt;/p&gt;




&lt;h2&gt;
  
  
  VI. File Processing Tool Selection Compliance Checklist
&lt;/h2&gt;

&lt;p&gt;When selecting a file processing tool, check each of the following compliance points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Does the tool upload data to a server?&lt;/strong&gt; Prefer local processing tools that keep files on the device. This is the fundamental measure for avoiding cross-border transfer and third-party risk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does processing require a network connection?&lt;/strong&gt; Offline processing is safer; it eliminates the data transmission step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is the service provider registered in your jurisdiction?&lt;/strong&gt; This affects cross-border transfer assessment; overseas providers require verification of backend server location.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does the tool support file processing log recording?&lt;/strong&gt; This satisfies the DSL's six-month log retention requirement (and the GDPR's Article 30 obligation). Logs should include time, filename, operator, and parameters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Has the tool passed relevant security certifications?&lt;/strong&gt; Certifications such as ISO 27001 or national cybersecurity level protection assessments reflect the provider's security management capability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is a data processing agreement signed?&lt;/strong&gt; This clarifies the data security responsibilities of both parties, defining data usage, retention period, and deletion method.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does the tool support batch processing and access control?&lt;/strong&gt; This meets enterprise management and audit needs, supporting role-based permissions and unified logging of batch operations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only a tool that passes all of the above checks may be added to an enterprise's whitelist. Any single item failing means the tool may only be used for public-level files.&lt;/p&gt;




&lt;h2&gt;
  
  
  VII. FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Q1: The online compression tool says "files are deleted immediately after processing." Is there still a compliance risk?
&lt;/h3&gt;

&lt;p&gt;Yes. Even if the provider promises deletion, the data has already left your device during transmission and may be intercepted, retained, or lawfully compelled. The transmission link, the provider's logging system, backup mechanisms, and disaster-recovery nodes can all leave traces. For sensitive files, "upload is risk"—once data leaves the enterprise's controllable boundary, there is no guarantee it will be completely deleted. Sensitive files should always be processed with a local compression tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q2: Is it compliant for an employee to send files processed with an online compression tool via personal email?
&lt;/h3&gt;

&lt;p&gt;Generally, no. Personal email is not managed by the enterprise, so the processing behavior cannot be recorded in enterprise logs, violating log retention requirements. The email may also transit through overseas servers, creating a cross-border transfer risk. Enterprises should explicitly prohibit such behavior through policy, provide enterprise email and local processing tools as alternatives, and use a DLP system to monitor whether sensitive files flow out through personal channels.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q3: Does the Data Security Law have specific provisions for file compression?
&lt;/h3&gt;

&lt;p&gt;No. The Data Security Law has no provisions specifically targeting file compression, but file compression constitutes a data processing activity and is subject to general requirements such as data classification, secure processing, and log retention. Whether it is compliant depends on three factors: the data level of the file, whether it involves personal information, and whether the processing involves a cross-border transfer. The law does not distinguish "compression" from other processing methods; it only looks at whether the processing meets general security requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q4: How can a local compression tool meet the log retention requirement?
&lt;/h3&gt;

&lt;p&gt;Enterprises can require local compression tools to provide a processing log feature that records processing time, filename, operator, and compression parameters, with logs retained for no less than six months. A professional tool should support automatic recording and export of logs for security audits. Enterprises should also integrate logs into a unified log management platform, correlated with the identity authentication system to ensure operators are traceable. Note that logs themselves are data processing records and should be managed at the sensitive level to prevent log leakage from creating secondary risk.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The implementation of the DSL, PIPL, and GDPR has shifted enterprise file processing from "whatever is convenient" to "whatever is compliant." Returning to the original question—is using an online compression tool a compliance risk?—the answer depends on three variables: the file's classification level, the data's flow path, and whether processing is logged.&lt;/p&gt;

&lt;p&gt;The core principles can be summarized as three: &lt;strong&gt;classify data, prioritize local processing, keep logs traceable&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data classification&lt;/strong&gt; is the prerequisite. Without classification, there is no way to judge whether an online tool may be used. Enterprises must first build a file classification ledger.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local-first&lt;/strong&gt; is the baseline. For sensitive-level files and above, local processing is the only reliable way to avoid cross-border transfer, third-party, and logging blind-spot risks. Online tools are acceptable only for public-level files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traceable logs&lt;/strong&gt; are the safeguard. All processing activities must be recordable and traceable, with logs retained for no less than six months. This is a necessary means for an enterprise to prove it has met its obligations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Achieve these three, and the basic compliance framework for enterprise file processing is in place. File compression is just one link in the file processing chain, but it reflects the enterprise's overall data security governance maturity—compliant tool selection, a clear classification system, and a complete logging framework. All three are indispensable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related Reading:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.uglypear.com/en/blog/enterprise-file-compliance.html" rel="noopener noreferrer"&gt;Enterprise Compliance Guide&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.uglypear.com/en/blog/file-compression-complete-guide.html" rel="noopener noreferrer"&gt;Complete File Compression Guide&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Need to Compress Files? Try SmartSlim&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Built on a self-developed Rust compression engine, supporting 10 categories and 40+ formats including PDF, images, video, Office, and OFD, with local compression that keeps your data on-premises.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.uglypear.com/en/download.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Free Desktop Download&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.uglypear.com/en/contact.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Enterprise Solutions Inquiry&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.uglypear.com/en/products/sdk.html" rel="noopener noreferrer"&gt;&lt;strong&gt;View SDK Documentation&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dataprocessing</category>
      <category>localcompression</category>
      <category>datasecuritylaw</category>
      <category>gdprcompliance</category>
    </item>
    <item>
      <title>What Is OFD? China's National Document Standard Explained</title>
      <dc:creator>Uglypear Data</dc:creator>
      <pubDate>Fri, 31 Jul 2026 03:51:34 +0000</pubDate>
      <link>https://dev.to/uglypeardata/what-is-ofd-chinas-national-document-standard-explained-3lbp</link>
      <guid>https://dev.to/uglypeardata/what-is-ofd-chinas-national-document-standard-explained-3lbp</guid>
      <description>&lt;h2&gt;
  
  
  The Definition and Background of OFD
&lt;/h2&gt;

&lt;p&gt;OFD (Open Fixed-layout Document) is a fixed-layout document format standard issued by the Standardization Administration of the People's Republic of China, with the standard number &lt;strong&gt;GB/T 33190-2016&lt;/strong&gt;. Unlike PDF, which was created by Adobe and later became the ISO 32000 international standard, OFD is a national standard independently developed by China, designed to address the issue of autonomous control in the fixed-layout document domain.&lt;/p&gt;

&lt;p&gt;The core characteristic of a fixed-layout document is "locked layout"—the document's layout, fonts, and image positions are fixed at creation time, and it renders identically regardless of the device used to open it. This contrasts with "reflowable documents" such as Word and HTML, which reflow based on screen size, font availability, and other factors. Fixed-layout documents lock the layout, ensuring what you see is what you get.&lt;/p&gt;

&lt;p&gt;An OFD file uses XML to describe the document structure and is organized as a ZIP package—essentially a compressed container holding multiple XML files and media resources. It supports text, images, graphics, signatures, seals, and animations, and precisely preserves the document's visual layout. The standard was driven toward industrialization by the Fixed-layout Document Industry Alliance (OFD Alliance) and was published as a national recommended standard in 2016.&lt;/p&gt;

&lt;p&gt;Since 2020, OFD has been widely adopted in the electronic official document systems of Party and government organs, gradually becoming the de facto standard for fixed-layout documents in the government sector. Today, OFD files are increasingly common in scenarios such as electronic invoices, electronic licenses, and electronic contracts. Understanding the technical system of OFD has become prerequisite knowledge for handling government documents and interfacing with government-enterprise systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  OFD vs PDF: A Technical Comparison of Two Fixed-Layout Formats
&lt;/h2&gt;

&lt;p&gt;OFD and PDF are both fixed-layout document formats with similar functional positioning—both are used to precisely preserve document layout and ensure cross-device consistency. However, the two differ significantly in their technical systems and ecosystems. Understanding these differences helps in choosing the right format for different scenarios.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;OFD&lt;/th&gt;
&lt;th&gt;PDF&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Format Standard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Chinese national standard GB/T 33190-2016&lt;/td&gt;
&lt;td&gt;ISO 32000 international standard (originated from Adobe)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;File Structure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;XML + ZIP container, open structure&lt;/td&gt;
&lt;td&gt;Binary/text hybrid, relatively closed structure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Government documents, electronic licenses, bidding&lt;/td&gt;
&lt;td&gt;General documents, contracts, reports, publications&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Supported Tools&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Few, mainly domestic tools like Suke, Foxit&lt;/td&gt;
&lt;td&gt;Mature ecosystem, Adobe, Foxit, and many free tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Seal/Signature Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native electronic seals, compliant with Chinese crypto standards&lt;/td&gt;
&lt;td&gt;Digital signatures supported, Chinese crypto needs extra adaptation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;International Recognition&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Primarily domestic use&lt;/td&gt;
&lt;td&gt;Globally accepted&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The flowchart below compares the technical paths of OFD and PDF across three dimensions: standard origin, file structure, and application ecosystem:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F82qndfv6oaf2ds1l9u3h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F82qndfv6oaf2ds1l9u3h.png" alt=" " width="798" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Format Standard
&lt;/h3&gt;

&lt;p&gt;OFD is a Chinese national standard with publicly transparent technical specifications. Its document structure is based on XML, making it convenient for domestic adaptation and integration with Chinese cryptographic algorithms (SM2, SM3, SM4). PDF is an international standard with the most mature ecosystem and global adoption, but in classified and government scenarios, there are concerns regarding autonomous control. The two are not in a replacement relationship; they are parallel standards addressing different compliance requirements and application domains.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. File Structure
&lt;/h3&gt;

&lt;p&gt;This is the most fundamental technical difference between OFD and PDF. An OFD file is essentially a ZIP archive, with XML internally describing pages, text, images, and other elements—clearly structured and easy to parse. PDF uses a binary/text hybrid format, internally composed of objects, cross-reference tables, and trailer structures—relatively complex. For developers, OFD offers stronger readability and parsability; for end users, the visual appearance of both is similar when opened.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Supported Tools
&lt;/h3&gt;

&lt;p&gt;PDF's tool ecosystem is extremely rich, ranging from free browser-embedded viewers to professional Adobe Acrobat, with editing, conversion, and compression tools of all kinds. By comparison, OFD's toolchain is still in its early stages of development. The number of software applications that can view and edit OFD is limited, and tools that support OFD compression are even scarcer. This is OFD's main shortcoming in its current ecosystem.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Seal and Signature Support
&lt;/h3&gt;

&lt;p&gt;OFD natively supports electronic seals and seal verification compliant with Chinese cryptographic standards. Seal data is embedded as independent nodes in the document structure, meeting the requirements for authenticity, integrity, and non-repudiation in official document workflows. PDF supports digital signatures based on the PKI system, but requires additional development for Chinese cryptographic algorithm adaptation. In government document scenarios, OFD's seal system aligns more closely with the domestic cryptographic infrastructure.&lt;/p&gt;




&lt;h2&gt;
  
  
  OFD File Structure: The XML + ZIP Container
&lt;/h2&gt;

&lt;p&gt;Understanding the OFD file structure is the foundation for understanding its compression methods and tool ecosystem. Unlike PDF's binary format, OFD adopts an "XML + ZIP container" architecture similar to modern office documents (such as OOXML, ODF).&lt;/p&gt;

&lt;h3&gt;
  
  
  Container Organization
&lt;/h3&gt;

&lt;p&gt;An OFD file is essentially a ZIP archive. By changing its file extension to &lt;code&gt;.zip&lt;/code&gt; and extracting it, you can see a clear multi-level directory structure. The outermost layer contains an &lt;code&gt;OFD.xml&lt;/code&gt; entry file, which declares the document's basic information and physical file paths; internally, content is organized in a hierarchy of "Document (Doc)—Page—Object."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frc8i8ueuyu6ty4j0towu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frc8i8ueuyu6ty4j0towu.png" alt=" " width="799" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The XML Description Layer
&lt;/h3&gt;

&lt;p&gt;OFD uses XML files to describe the document's logical structure and page content. &lt;code&gt;Document.xml&lt;/code&gt; defines the document's page tree, outline, metadata, and so on; each page corresponds to a &lt;code&gt;Content.xml&lt;/code&gt; that describes the text, images, graphics, paths, and other layout objects on that page along with their coordinates and styles. This XML-based description approach brings several characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Strong readability&lt;/strong&gt;: Any text editor can view OFD's page descriptions, facilitating debugging and auditing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy to parse&lt;/strong&gt;: Standard XML parsers can read the document structure without specialized binary parsers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Good extensibility&lt;/strong&gt;: Adding new features only requires extending the XML Schema without affecting existing structures&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Comparison with PDF's Binary Format
&lt;/h3&gt;

&lt;p&gt;PDF uses a binary/text hybrid format, internally composed of numbered objects linked together through a Cross-Reference Table, with the Trailer at the end of the file pointing to the root object. This design has advantages in file compactness, but the structure is opaque—ordinary users cannot directly view the internal content.&lt;/p&gt;

&lt;p&gt;The difference between the two is also evident at the compression level: OFD is already a ZIP container, with internal resources having undergone a layer of compression, so re-compressing the whole file yields limited gains—the optimization focus is on internal resources (images, fonts). PDF's compression, on the other hand, is distributed across individual stream objects, where each stream object can independently choose its compression algorithm.&lt;/p&gt;




&lt;h2&gt;
  
  
  OFD Applications in Government Documents
&lt;/h2&gt;

&lt;p&gt;OFD's promotion in the government sector has a practical background. Traditional government documents are primarily paper-based, and electronic transformation requires a fixed-layout format that precisely preserves layout, supports electronic seals, and complies with national cryptographic management requirements. Although PDF is powerful, as a foreign standard it raises autonomous control concerns in classified information systems. OFD, as a national standard, fills this gap.&lt;/p&gt;

&lt;h3&gt;
  
  
  Electronic Official Documents
&lt;/h3&gt;

&lt;p&gt;Electronic official document systems in Party and government organs across many regions of China have adopted OFD as the standard format. The entire workflow of drafting, review, signing, distribution, and archiving uses OFD files as the carrier, combined with Chinese cryptographic electronic seals to achieve tamper resistance and traceability. OFD's fixed-layout characteristic ensures that documents maintain consistent layout across different office systems, without misformatting due to missing fonts or software differences.&lt;/p&gt;

&lt;h3&gt;
  
  
  Electronic Licenses
&lt;/h3&gt;

&lt;p&gt;Electronic business licenses, real estate registration certificates, electronic ID cards, and other electronic licenses are gradually migrating to the OFD format. OFD files can embed license information, holder photos, issuing authority electronic seals, and support anti-forgery verification. Compared to paper licenses, OFD electronic licenses are more convenient for online verification and cross-department sharing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Electronic Invoices
&lt;/h3&gt;

&lt;p&gt;Electronic invoices in some regions have adopted the OFD format. OFD invoices contain structured data such as invoice codes, amounts, and tax amounts, while preserving the visual layout—convenient for both human reading and machine parsing. The seal mechanism of OFD invoices ensures authenticity and non-repudiation.&lt;/p&gt;

&lt;p&gt;As application scale expands, OFD file size has become apparent—large numbers of scanned documents and high-definition seal images embedded in documents cause official documents to reach tens of MB, creating pressure on storage and transmission, and generating demand for OFD compression.&lt;/p&gt;




&lt;h2&gt;
  
  
  OFD Compression Methods
&lt;/h2&gt;

&lt;p&gt;The principle of OFD compression is highly similar to PDF compression—the core is optimizing the parts that occupy the most space within the file. Since OFD is already a ZIP container whose file structure has undergone a layer of DEFLATE compression, the key to OFD compression is not adding another compression layer, but optimizing internal resources (images, fonts).&lt;/p&gt;

&lt;h3&gt;
  
  
  Image Resampling
&lt;/h3&gt;

&lt;p&gt;Scanned documents and seal images in OFD files are typically the largest contributors to file size. A scanned official document may embed multiple 300dpi high-definition scanned pages, each several MB. Reducing high-resolution images to a reasonable resolution (e.g., from 300dpi to 150dpi) can significantly reduce size, with an acceptable impact on screen reading and printing.&lt;/p&gt;

&lt;p&gt;Resampling requires balancing resolution and clarity: text content in government documents remains clearly legible at 150dpi, but the fine details of precision seals may require higher resolution. A sensible approach is to set different target resolutions based on image purpose.&lt;/p&gt;

&lt;h3&gt;
  
  
  Font Subsetting
&lt;/h3&gt;

&lt;p&gt;OFD files embed complete fonts to ensure consistent display across devices, but a document typically uses only a small portion of the characters in a font file. Font subsetting retains only the character glyphs actually used in the document, discarding unused font data.&lt;/p&gt;

&lt;p&gt;This technique is especially effective for Chinese documents. A complete Chinese font file typically contains tens of thousands of Chinese character glyphs and can exceed 10MB in size; however, a government document may use only one or two thousand Chinese characters, and subsetting can reduce font data by over 80%.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cleaning Redundant Objects
&lt;/h3&gt;

&lt;p&gt;An OFD package may contain unreferenced resources and duplicate objects: images deleted during editing may still linger in the resource directory, and multiple saves may produce duplicate metadata. Cleaning redundant objects involves traversing the document structure to remove all resources not referenced by pages, streamlining the document structure tree.&lt;/p&gt;

&lt;h3&gt;
  
  
  Image Format Optimization
&lt;/h3&gt;

&lt;p&gt;OFD supports embedding multiple image formats, including uncompressed bitmaps (BMP) and compressed formats (JPEG, PNG). Converting uncompressed bitmaps to compressed formats like JPEG can directly reduce image resource usage. For seal graphics with large areas of solid color, PNG may be smaller than JPEG; for color-rich scanned photos, JPEG offers a higher compression ratio.&lt;/p&gt;

&lt;p&gt;The following code demonstrates how to unzip an OFD file and analyze its internal resource usage—the first step in compression optimization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;zipfile&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;defaultdict&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;analyze_ofd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ofd_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Unzip and analyze the internal resource usage of an OFD file&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;zipfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ZipFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ofd_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;zf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Tally the size of each file type
&lt;/span&gt;        &lt;span class="n"&gt;type_sizes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;type_counts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;total_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;zf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;infolist&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;type_sizes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compress_size&lt;/span&gt;
            &lt;span class="n"&gt;type_counts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="n"&gt;total_size&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compress_size&lt;/span&gt;

        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Total OFD size: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;total_size&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; MB&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Count&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Size(MB)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Share&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type_sizes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
            &lt;span class="n"&gt;pct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;total_size&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(none)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;type_counts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                  &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mf"&gt;12.2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pct&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;%&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Usage example
# analyze_ofd("sample.ofd")
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running this kind of analysis script, you will typically find that over 80% of an OFD file's size comes from image resources (&lt;code&gt;.jpg&lt;/code&gt;, &lt;code&gt;.png&lt;/code&gt;, &lt;code&gt;.bmp&lt;/code&gt;), with font files (&lt;code&gt;.ttf&lt;/code&gt;, &lt;code&gt;.otf&lt;/code&gt;) second. This confirms the core strategy of OFD compression: prioritize image optimization, then font optimization.&lt;/p&gt;

&lt;p&gt;A 50MB OFD scanned official document, after reasonable image resampling and font subsetting, can typically be compressed to 8-12MB, with text and seals still clearly legible—fully meeting the requirements for government workflow and archiving.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Current State of the OFD Tool Ecosystem
&lt;/h2&gt;

&lt;p&gt;Although OFD's status as a national standard is clear, its tool ecosystem is far less mature than PDF's. Currently, software that can view OFD is mainly domestic tools such as the Suke reader and Foxit OFD; browsers do not natively support OFD preview, and tools that can compress OFD are even scarcer.&lt;/p&gt;

&lt;p&gt;The weakness of the tool ecosystem brings two practical problems. First, ordinary users who receive an OFD file may not find a suitable tool to open it and need to download a dedicated reader. Second, when an OFD file is too large, the lack of ready-made compression tools means many users can only store or transmit it as-is, bearing storage and bandwidth costs.&lt;/p&gt;

&lt;p&gt;From a technical perspective, OFD's open XML + ZIP structure means the barrier to parsing and processing is theoretically lower than PDF's binary format. The lag in the tool ecosystem is more a matter of market promotion and application scale than a technical obstacle. As OFD applications continue to expand in government and finance, the toolchain is expected to gradually mature.&lt;/p&gt;




&lt;h2&gt;
  
  
  Comparison Table: OFD vs PDF Compression Methods
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Compression Method&lt;/th&gt;
&lt;th&gt;OFD Applicability&lt;/th&gt;
&lt;th&gt;PDF Applicability&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Image Resampling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Images dominate size in both; reducing resolution is most effective&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Font Subsetting&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Especially effective for Chinese docs; can cut font data by 80%+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cleaning Redundant Objects&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Remove unreferenced resources and duplicates, streamline structure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Image Format Optimization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Convert bitmaps to JPEG; choose optimal format per image type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Whole-File ZIP Compression&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low (already ZIP)&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;OFD is already a ZIP container; re-compression yields little&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stream Object Compression&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;PDF-specific; each Stream can independently choose compression&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Q1: Can OFD files be converted to PDF?
&lt;/h3&gt;

&lt;p&gt;Yes. Some OFD readers and conversion tools support exporting OFD to PDF. However, note that OFD-specific information such as electronic seals may not be fully preserved during conversion, because OFD's Chinese cryptographic seal system and PDF's PKI signature system do not fully correspond. It is advisable to be cautious when converting in scenarios requiring long-term archiving or legal validity—back up before conversion and verify the seal status of the converted document.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q2: Does OFD compression affect the validity of electronic seals?
&lt;/h3&gt;

&lt;p&gt;Proper OFD compression only optimizes resources such as images and fonts, without modifying seal data or document hash verification information, so it does not affect the validity of electronic seals. However, note that a seal's integrity verification typically covers specific parts of the document—if the compression process modifies content protected by the seal, seal verification will fail. It is recommended to use professional tools and re-verify the seal status after compression to ensure the legal validity of the document is not compromised.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q3: Do I need to use OFD for ordinary office scenarios?
&lt;/h3&gt;

&lt;p&gt;For general business documents, PDF is sufficient. OFD is mainly used for government documents, electronic licenses, and other official scenarios. If you are not involved in government interfacing, there is no need to deliberately use OFD. However, if you need to exchange electronic official documents with government agencies or submit OFD-format bidding documents, you must use OFD. The two are not in a replacement relationship; the choice depends on compliance requirements and application scenarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q4: Which is smaller in size, OFD or PDF?
&lt;/h3&gt;

&lt;p&gt;There is no absolute answer. File size depends primarily on internal resources (images, fonts) rather than the container format itself. For identical content, OFD's XML description may be slightly larger than PDF's binary description, but both use compression, and the difference is usually negligible. The key factors determining size are image resolution and font embedding strategy, not the format choice. An OFD official document embedding many high-definition scanned pages will be far larger than a plain-text PDF, and vice versa.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;OFD and PDF are both fixed-layout document formats, but they represent different technical paths and application ecosystems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OFD&lt;/strong&gt;, as a Chinese national standard (GB/T 33190-2016), adopts an open XML + ZIP container structure, natively supports Chinese cryptographic electronic seals, and holds a stable position in domestic official scenarios such as government documents, electronic licenses, and electronic invoices. Its tool ecosystem is still in early development, but its open structure provides convenience for domestic adaptation and custom development.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PDF&lt;/strong&gt;, as an international standard (ISO 32000), adopts a binary/text hybrid format, with the most mature tool ecosystem globally, and is irreplaceable in general office scenarios.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The two are highly similar in compression methods—the core is optimizing embedded image and font resources. OFD compression's four key techniques (image resampling, font subsetting, cleaning redundant objects, image format optimization) share the same lineage as PDF compression, because the size composition principles of fixed-layout documents are universal.&lt;/p&gt;

&lt;p&gt;The key to understanding OFD is grasping its "XML + ZIP container" essence: an open, parseable, easily adaptable fixed-layout architecture whose compression focus—like PDF's—is on internal resources, not the container itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Related Reading:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.uglypear.com/en/blog/ofd-vs-pdf.html" rel="noopener noreferrer"&gt;OFD vs PDF&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.uglypear.com/en/blog/pdf-compression-guide.html" rel="noopener noreferrer"&gt;PDF Compression Principles&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>python</category>
    </item>
    <item>
      <title>H.264 vs H.265 vs AV1: Video Codec Evolution and Selection Guide</title>
      <dc:creator>Uglypear Data</dc:creator>
      <pubDate>Thu, 30 Jul 2026 02:02:36 +0000</pubDate>
      <link>https://dev.to/uglypeardata/h264-vs-h265-vs-av1-video-codec-evolution-and-selection-guide-of8</link>
      <guid>https://dev.to/uglypeardata/h264-vs-h265-vs-av1-video-codec-evolution-and-selection-guide-of8</guid>
      <description>&lt;h2&gt;
  
  
  1. The Evolution of Video Codecs
&lt;/h2&gt;

&lt;p&gt;The history of video coding stretches back to the late 1980s. From H.261, designed for video conferencing over ISDN lines, to AV1, engineered for ultra-high-definition streaming, codec standards have evolved over nearly three decades. Each generation pursues the same fundamental goal: reproduce the picture using fewer bits while preserving visual quality.&lt;/p&gt;

&lt;p&gt;Video compression is essential because raw, uncompressed video is enormous. A ten-second 1080p clip in raw form can consume several gigabytes—untenable for either storage or transmission. Codecs exploit spatial and temporal redundancy within frames to shrink this data to a manageable size. Spatial redundancy refers to the correlation between neighboring pixels within a single frame; temporal redundancy refers to the similarity between consecutive frames. Virtually every modern codec standard revolves around these two kinds of redundancy.&lt;/p&gt;

&lt;p&gt;Concretely, an encoder classifies pictures into three frame types: I-frames (intra-coded frames) record a full picture and can be decoded independently, offering the lowest compression but the strongest error resilience; P-frames (predictive frames) store only the differences from a preceding frame; B-frames (bidirectional frames) reference both preceding and following frames, achieving the highest compression. The group of frames between two I-frames forms a GOP (Group of Pictures)—a longer GOP yields better compression but weaker random access and error recovery. This inter-frame prediction framework has been in place since H.261; successive standards primarily refine block partitioning, prediction accuracy, and entropy coding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fshymuivk49hmglj4ttci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fshymuivk49hmglj4ttci.png" alt=" " width="800" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;H.261 established the block-based coding framework; MPEG-1 extended it to optical disc storage at roughly 1.5 Mbps, sufficient for VCD-quality video; H.263 optimized for low-bitrate communication, maintaining recognizable pictures below 64 kbps; H.264 opened the era of high-definition streaming; H.265 targeted 4K ultra HD; and AV1 represents the next-generation, royalty-free direction. Each generation attempts to improve compression efficiency over its predecessor while keeping encoding complexity within the reach of real-world hardware.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Technical Breakdown of Mainstream Codecs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  H.264 (AVC)
&lt;/h3&gt;

&lt;p&gt;Released in 2003, H.264 (Advanced Video Coding) uses macroblock partitioning with a 16×16 base block, supporting sub-blocks from 4×4 to 16×16. Motion estimation reaches quarter-pixel precision, and the standard introduces multi-reference frames, in-loop deblocking, Context-Adaptive Variable-Length Coding (CAVLC), and Context-Adaptive Binary Arithmetic Coding (CABAC).&lt;/p&gt;

&lt;p&gt;Compared to its predecessor H.263, H.264 roughly doubles compression efficiency—halving the bitrate at equivalent quality. CABAC saves 5–15% more bitrate than CAVLC but demands more computation, so low-end devices often opt for CAVLC. H.264 also supports multiple slices and Flexible Macroblock Ordering (FMO), facilitating parallel processing and error resilience.&lt;/p&gt;

&lt;p&gt;H.264's strength is its mature ecosystem: virtually every modern device, browser, and player supports it natively. Its weakness is insufficient compression efficiency for 4K and beyond, resulting in higher bitrates. Thanks to ubiquitous hardware decoding, H.264 also excels in power efficiency on mobile devices, making it the most compatible codec available today.&lt;/p&gt;

&lt;h3&gt;
  
  
  H.265 (HEVC)
&lt;/h3&gt;

&lt;p&gt;Released in 2013, H.265 (High Efficiency Video Coding) introduces the Coding Tree Unit (CTU), supporting blocks up to 64×64 with adaptive partitioning down to 8×8 based on picture complexity. At equivalent subjective quality, H.265 reduces bandwidth by roughly 40–50% compared to H.264.&lt;/p&gt;

&lt;p&gt;Key improvements include larger CTU sizes that boost coding efficiency, especially for large flat regions; 35 intra prediction directions (versus 9 in H.264) for finer texture representation; advanced motion vector merging (Merge) and Advanced Motion Vector Prediction (AMVP) that reduce the encoding overhead of motion information; Sample Adaptive Offset (SAO) that further suppresses ringing artifacts after in-loop filtering; and parallel processing tools such as Tiles and WPP that ease multi-core encoding.&lt;/p&gt;

&lt;p&gt;These features make H.265 well-suited for 4K and 8K content distribution, but they also bring significantly higher computational complexity—H.265 encoding can take several times longer than H.264. Larger block sizes can actually increase overhead at low resolutions, so H.265's advantages only fully emerge at higher resolutions.&lt;/p&gt;

&lt;h3&gt;
  
  
  VP9
&lt;/h3&gt;

&lt;p&gt;Developed by Google and released in 2013 as part of the WebM project, VP9 uses 64×64 superblocks and supports 32 intra prediction modes, along with advanced inter prediction and adaptive quantization. Its compression efficiency is comparable to H.265, and it is completely royalty-free.&lt;/p&gt;

&lt;p&gt;VP9 borrows ideas from H.265 but simplifies the syntax and toolset to lower implementation difficulty. It supports up to three reference frames and allows mixing references of different resolutions to handle variable-resolution scenarios. VP9's main advantage is openness: any vendor can implement it without patent concerns. However, its hardware decoding ecosystem is relatively limited, so it is most active on the web, particularly in Chromium-based browsers. VP9 has been widely adopted by major video platforms as an efficient alternative to H.264, performing reliably in web video distribution.&lt;/p&gt;

&lt;h3&gt;
  
  
  AV1
&lt;/h3&gt;

&lt;p&gt;Released in 2018 by the Alliance for Open Media (AOMedia), AV1 extends previous-generation techniques with 128×128 superblocks and more sophisticated prediction and transform tools, including intra block copy, affine motion compensation, palette mode, and 1/8-pixel motion precision. Compared to H.265, AV1 saves an additional 20–30% in bitrate at equivalent quality—roughly 60% savings versus H.264.&lt;/p&gt;

&lt;p&gt;AOMedia was founded jointly by several industry players specifically to circumvent the fragmented patent licensing of H.265. AV1 builds on VP9, incorporates selected advanced tools from H.265, and adds numerous experimental techniques, giving it a far larger toolset than H.265. It is designed to be entirely royalty-free and has been gradually adopted by major streaming platforms. Encoding complexity is extremely high, and real-time encoding still relies on hardware acceleration. The latest GPUs and mobile chips are beginning to integrate AV1 hardware decoding, and hardware-assisted encoding is progressing. Widespread deployment across both on-demand and live streaming is expected over the next few years.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flehfskkmllkhbiy1xadm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flehfskkmllkhbiy1xadm.png" alt=" " width="799" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Patent Licensing Comparison
&lt;/h2&gt;

&lt;p&gt;Licensing is a decisive factor in codec adoption. The table below compares the licensing situation of four mainstream formats:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Codec&lt;/th&gt;
&lt;th&gt;Licensor&lt;/th&gt;
&lt;th&gt;Royalty Cost&lt;/th&gt;
&lt;th&gt;Complexity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;H.264&lt;/td&gt;
&lt;td&gt;MPEG-LA unified pool&lt;/td&gt;
&lt;td&gt;Tiered, with annual cap&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;H.265&lt;/td&gt;
&lt;td&gt;Multiple pools (MPEG-LA, HEVC Advance, etc.)&lt;/td&gt;
&lt;td&gt;High, no unified cap&lt;/td&gt;
&lt;td&gt;Very high&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VP9&lt;/td&gt;
&lt;td&gt;Open source (BSD license)&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AV1&lt;/td&gt;
&lt;td&gt;Alliance for Open Media&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Licensing is the primary reason H.265 adoption has lagged. H.264 is managed by MPEG-LA with a clear fee structure and a cap, so content providers can deploy it with predictable costs; H.265, by contrast, involves multiple competing patent pools with patent holders spread across different organizations, uncertain fees, and no unified ceiling. According to public reports, some content providers delayed H.265 deployment because they could not estimate licensing costs. This uncertainty has driven some browser vendors and open-source communities toward VP9 and AV1, and it directly motivated the formation of AOMedia, giving rise to a royalty-free open-source codec ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Scenario-Based Recommendations
&lt;/h2&gt;

&lt;p&gt;Different use cases have very different codec requirements. The table below summarizes recommendations for common scenarios:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Recommended Codec&lt;/th&gt;
&lt;th&gt;Reason&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Email attachment&lt;/td&gt;
&lt;td&gt;H.264&lt;/td&gt;
&lt;td&gt;Best compatibility, no extra decoder needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web embedding&lt;/td&gt;
&lt;td&gt;VP9 / H.264&lt;/td&gt;
&lt;td&gt;Native browser support; VP9 saves bandwidth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mobile playback&lt;/td&gt;
&lt;td&gt;H.264 / H.265&lt;/td&gt;
&lt;td&gt;Hardware decoding ubiquitous, battery-friendly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Streaming delivery&lt;/td&gt;
&lt;td&gt;AV1 / H.265&lt;/td&gt;
&lt;td&gt;High compression lowers bandwidth cost&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long-term archival&lt;/td&gt;
&lt;td&gt;H.265 / AV1&lt;/td&gt;
&lt;td&gt;Saves storage while preserving quality&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Live streaming&lt;/td&gt;
&lt;td&gt;H.264&lt;/td&gt;
&lt;td&gt;Fastest encoding, controllable latency&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Always verify the decoding capabilities of the target playback environment first, then weigh compression efficiency against encoding cost. For content that must reach the widest possible audience, H.264 remains the fallback; for bandwidth-sensitive distribution, newer codecs should take priority. In practice, many platforms adopt a multi-bitrate, multi-codec strategy: serving H.264 to cover all clients while providing AV1 or H.265 versions for devices that support newer codecs, balancing compatibility and efficiency.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. FFmpeg Compression Comparison
&lt;/h2&gt;

&lt;p&gt;Using the same 1080p source video, compress with each codec. Lower CRF (Constant Rate Factor) values yield higher quality; similar values generally indicate comparable quality.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# H.264 (CRF 23, medium preset)&lt;/span&gt;
ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; input.mp4 &lt;span class="nt"&gt;-c&lt;/span&gt;:v libx264 &lt;span class="nt"&gt;-crf&lt;/span&gt; 23 &lt;span class="nt"&gt;-preset&lt;/span&gt; medium &lt;span class="nt"&gt;-an&lt;/span&gt; output_h264.mp4

&lt;span class="c"&gt;# H.265 (CRF 28, medium preset)&lt;/span&gt;
ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; input.mp4 &lt;span class="nt"&gt;-c&lt;/span&gt;:v libx265 &lt;span class="nt"&gt;-crf&lt;/span&gt; 28 &lt;span class="nt"&gt;-preset&lt;/span&gt; medium &lt;span class="nt"&gt;-x265-params&lt;/span&gt; log-level&lt;span class="o"&gt;=&lt;/span&gt;error &lt;span class="nt"&gt;-an&lt;/span&gt; output_h265.mp4

&lt;span class="c"&gt;# VP9 (CRF 32, unrestricted bitrate)&lt;/span&gt;
ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; input.mp4 &lt;span class="nt"&gt;-c&lt;/span&gt;:v libvpx-vp9 &lt;span class="nt"&gt;-crf&lt;/span&gt; 32 &lt;span class="nt"&gt;-b&lt;/span&gt;:v 0 &lt;span class="nt"&gt;-an&lt;/span&gt; output_vp9.webm

&lt;span class="c"&gt;# AV1 (CRF 30, unrestricted bitrate)&lt;/span&gt;
ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; input.mp4 &lt;span class="nt"&gt;-c&lt;/span&gt;:v libaom-av1 &lt;span class="nt"&gt;-crf&lt;/span&gt; 30 &lt;span class="nt"&gt;-b&lt;/span&gt;:v 0 &lt;span class="nt"&gt;-cpu-used&lt;/span&gt; 4 &lt;span class="nt"&gt;-an&lt;/span&gt; output_av1.mkv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Parameter notes: &lt;code&gt;-crf&lt;/code&gt; controls quality, &lt;code&gt;-preset&lt;/code&gt;/&lt;code&gt;-cpu-used&lt;/code&gt; balance speed against compression ratio, &lt;code&gt;-b:v 0&lt;/code&gt; lets the encoder allocate bitrate based on CRF, and &lt;code&gt;-an&lt;/code&gt; discards audio to focus the comparison on video compression. Note that the CRF scales are not uniform across encoders: H.264's CRF 23 and H.265's CRF 28 are roughly comparable in subjective quality, but not an exact match—rigorous comparisons should rely on objective metrics such as VMAF or SSIM.&lt;/p&gt;

&lt;p&gt;In practice, at equivalent subjective quality, H.265, VP9, and AV1 produce progressively smaller files—but encoding time increases accordingly. AV1 encoding can take tens of times longer than H.264 and requires hardware or parallel optimization to be practical. In production batch transcoding environments, encoding speed is often just as important as compression ratio, so many platforms use AV1 only for offline transcoding while keeping H.264 for real-time scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q1: H.265 is technically superior—why has adoption been slower than H.264?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Primarily due to licensing. H.265 involves multiple patent pools with complex, uncapped fee structures, deterring browser vendors and content platforms. Some browser makers explicitly declined to support H.265 natively because of licensing concerns. Limited early hardware decoding support also slowed mobile adoption. Only in recent years have mainstream chips generally integrated H.265 hardware decoding, but web-side support remains inconsistent. By contrast, H.264 licensing is handled centrally by MPEG-LA with predictable fees, making it the most widely deployed codec standard to date.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q2: When will AV1 fully replace H.265?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AV1 decoding is supported in next-generation hardware and major browsers, but real-time encoding remains computationally expensive. On-demand delivery has begun scaling up, but live streaming demands low encoding latency and still relies mainly on H.264. Widespread use in live streaming is expected only after hardware encoders mature and encoding speed optimizations improve. In the short term, a more likely scenario is AV1 and H.265 coexisting, with adaptive switching based on client decoding capability. AV1 encoding speed is also improving steadily—open-source encoders such as SVT-AV1 have substantially reduced encoding times, and further gains are expected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q3: Why is VP9 mostly confined to the web?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;VP9's hardware decoding coverage is relatively limited, relying mainly on Chromium-based browsers' software decoding. On desktop players and native mobile apps, H.264 and H.265 enjoy better hardware support and lower power consumption. VP9 never built a cross-platform hardware decoding ecosystem like H.264, so it remains primarily a web video format. However, VP9 paved the way for AV1—many of its technical ideas continue and are upgraded in AV1. Some platforms serve both VP9 and AV1 versions simultaneously, gradually transitioning from VP9 to AV1.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Conclusion
&lt;/h2&gt;

&lt;p&gt;Video codec development is a constant balance between compression efficiency and implementation cost. H.264, with its comprehensive compatibility, remains the safest choice today; H.265 excels in bandwidth-sensitive UHD scenarios, though licensing constraints limit adoption; VP9 and AV1 represent the royalty-free direction, with AV1 emerging as the core of next-generation streaming.&lt;/p&gt;

&lt;p&gt;When selecting a codec, consider the target playback environment, bandwidth cost, storage capacity, and computational overhead rather than chasing the newest standard. Finding the right balance between compatibility, efficiency, and cost is the engineering optimum. Understanding the applicable boundaries of each codec is more valuable than remembering which one is newest. As hardware support for AV1 matures and encoding tools continue to optimize, the cost gap between generations will narrow—yet the fundamental tradeoffs between compatibility, efficiency, and licensing will persist. Staying informed about these dynamics is the best way to make sound codec decisions over time.&lt;/p&gt;

&lt;p&gt;More Technology Articles: &lt;a href="https://www.uglypear.com/en/blog/" rel="noopener noreferrer"&gt;Tech Blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>python</category>
    </item>
    <item>
      <title>FFmpeg Video Compression: CRF vs CBR vs VBR Explained</title>
      <dc:creator>Uglypear Data</dc:creator>
      <pubDate>Wed, 29 Jul 2026 08:08:56 +0000</pubDate>
      <link>https://dev.to/uglypeardata/ffmpeg-video-compression-crf-vs-cbr-vs-vbr-explained-2jbi</link>
      <guid>https://dev.to/uglypeardata/ffmpeg-video-compression-crf-vs-cbr-vs-vbr-explained-2jbi</guid>
      <description>&lt;h2&gt;
  
  
  Bitrate Control: Starting From the Basics
&lt;/h2&gt;

&lt;p&gt;To understand the difference between CRF, CBR, and VBR, we first need to talk about bitrate.&lt;/p&gt;

&lt;p&gt;Bitrate is the amount of video data produced per unit of time, usually measured in kbps (kilobits per second) or Mbps (megabits per second). It directly determines the clarity, smoothness, and final file size of a video. With the same resolution, frame rate, and codec, a higher bitrate preserves more detail but produces a larger file, while a lower bitrate shrinks the file at the cost of blur, banding, and blocking artifacts.&lt;/p&gt;

&lt;p&gt;So why do we need bitrate control at all? The reason is that the complexity of video frames is constantly changing. Static backgrounds and flat color areas can be reconstructed losslessly with very little data, whereas fast motion, rich textures, and abrupt changes require far more bits to stay sharp. If you force a constant bitrate across the entire video, simple scenes waste storage space, and complex scenes starve for bits and visibly degrade.&lt;/p&gt;

&lt;p&gt;The core goal of bitrate control is to allocate bits to each frame intelligently, given a fixed storage or bandwidth budget, and to strike the best balance between quality and size. The three modes, CRF, CBR, and VBR, are essentially three different allocation strategies.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three Bitrate Control Modes Explained
&lt;/h2&gt;

&lt;h3&gt;
  
  
  CRF (Constant Rate Factor)
&lt;/h3&gt;

&lt;p&gt;The guiding principle of CRF is constant quality. The encoder dynamically allocates bits based on the complexity of each frame: it spends fewer bits on simple scenes and more bits on complex scenes, keeping the perceived quality consistent throughout the video. Whether the frame is a still landscape or an action-packed sequence, the viewer experiences roughly the same visual quality.&lt;/p&gt;

&lt;p&gt;CRF is controlled by an integer between 0 and 51 (for the x264 and x265 encoders). A lower value means higher quality and a larger file; a higher value means lower quality and a smaller file. A value of 0 produces lossless encoding, 51 is the lowest quality, and 23 is typically the default visually lossless reference point.&lt;/p&gt;

&lt;p&gt;The biggest advantage of CRF is simplicity combined with stable quality. You do not need to set a target bitrate in advance, because the encoder automatically distributes bits according to scene complexity. For this reason, CRF is the preferred mode for most non-real-time tasks such as offline compression, file storage, and web publishing.&lt;/p&gt;

&lt;h3&gt;
  
  
  CBR (Constant Bitrate)
&lt;/h3&gt;

&lt;p&gt;CBR keeps the bitrate fixed for the entire duration. No matter how complex or simple a scene is, the encoder outputs the same amount of data per second. This means that in simple scenes the allocated bits are redundant or even wasted, while in complex scenes the bits may be insufficient, causing visible artifacts.&lt;/p&gt;

&lt;p&gt;The strength of CBR lies in its predictability and buffer friendliness. These properties make it especially suited for live streaming and real-time video transmission, where bandwidth stability is critical. In these scenarios the network bandwidth is often fixed, and large bitrate fluctuations can overflow the buffer or congest the network, causing stutter. CBR sacrifices some quality in exchange for transmission stability.&lt;/p&gt;

&lt;h3&gt;
  
  
  VBR (Variable Bitrate)
&lt;/h3&gt;

&lt;p&gt;VBR allows the bitrate to fluctuate within a specified range. The encoder weighs scene complexity and a target quality, adjusting the bitrate between a configured minimum and maximum. VBR typically requires setting a target bitrate (or target quality) along with upper and lower bounds, making it more flexible than CBR while adding a bitrate constraint that CRF lacks.&lt;/p&gt;

&lt;p&gt;VBR is common in scenarios that need to control overall file size while preserving quality, such as streaming segment encoding. It is worth noting that the x264 encoder also offers a 2-pass VBR mode: the first pass scans the entire video to analyze the complexity distribution, and the second pass allocates bits precisely based on that analysis. This mode controls the target size accurately while optimizing bit distribution, but it takes roughly twice as long as a single-pass encode, making it ideal for offline tasks with strict size requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing Bitrate Fluctuations Across the Three Modes
&lt;/h2&gt;

&lt;p&gt;The chart below visualizes how the three modes behave on the same video. CBR is a flat horizontal line, while CRF and VBR both rise and fall with scene complexity. CRF fluctuates more freely, whereas VBR is bounded by its configured floor and ceiling.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvgepmykakhkzyc0vgz2x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvgepmykakhkzyc0vgz2x.png" alt=" " width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How CRF Value Affects Quality and Size
&lt;/h2&gt;

&lt;p&gt;Choosing the right CRF value is the most important step when using CRF mode. The chart below shows how quality and file size change as the CRF value goes from 18 to 30. A lower CRF means higher quality and a larger file, while a higher CRF means a smaller file at the cost of quality.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fygfj0p6udbpuadr2sbea.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fygfj0p6udbpuadr2sbea.png" alt=" " width="800" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  FFmpeg Command Examples: Three Common Scenarios
&lt;/h2&gt;

&lt;p&gt;Here are three typical compression scenarios, each addressing a different balance of quality and size.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 1: Email (H.264 + 720p + CRF 28)
&lt;/h3&gt;

&lt;p&gt;Email attachments usually have size limits, so the video needs to be compressed aggressively. 720p resolution with CRF 28 keeps the file small while remaining watchable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; input.mp4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-c&lt;/span&gt;:v libx264 &lt;span class="nt"&gt;-preset&lt;/span&gt; medium &lt;span class="nt"&gt;-crf&lt;/span&gt; 28 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-vf&lt;/span&gt; &lt;span class="s2"&gt;"scale=-2:720"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-c&lt;/span&gt;:a aac &lt;span class="nt"&gt;-b&lt;/span&gt;:a 128k &lt;span class="se"&gt;\&lt;/span&gt;
  output.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scenario 2: Web Publishing (H.264 + 1080p + CRF 26)
&lt;/h3&gt;

&lt;p&gt;Web video needs to balance clarity with loading speed. 1080p with CRF 26 is a common combination that also offers the widest compatibility.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; input.mp4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-c&lt;/span&gt;:v libx264 &lt;span class="nt"&gt;-preset&lt;/span&gt; medium &lt;span class="nt"&gt;-crf&lt;/span&gt; 26 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-vf&lt;/span&gt; &lt;span class="s2"&gt;"scale=-2:1080"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-c&lt;/span&gt;:a aac &lt;span class="nt"&gt;-b&lt;/span&gt;:a 128k &lt;span class="se"&gt;\&lt;/span&gt;
  output.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scenario 3: Archival (H.265 + Original Resolution + CRF 20)
&lt;/h3&gt;

&lt;p&gt;Archival prioritizes quality and compression efficiency. Using the H.265 encoder while keeping the original resolution, CRF 20 achieves near-visually-lossless quality at a smaller size than H.264.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; input.mp4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-c&lt;/span&gt;:v libx265 &lt;span class="nt"&gt;-preset&lt;/span&gt; medium &lt;span class="nt"&gt;-crf&lt;/span&gt; 20 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-c&lt;/span&gt;:a aac &lt;span class="nt"&gt;-b&lt;/span&gt;:a 192k &lt;span class="se"&gt;\&lt;/span&gt;
  output.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A quick note on the key parameters: &lt;code&gt;-c:v&lt;/code&gt; sets the video codec, where &lt;code&gt;libx264&lt;/code&gt; maps to H.264 and &lt;code&gt;libx265&lt;/code&gt; maps to H.265; &lt;code&gt;-preset&lt;/code&gt; trades encoding speed for compression efficiency, where slower presets yield better compression; &lt;code&gt;-crf&lt;/code&gt; sets the quality level; &lt;code&gt;-vf "scale=-2:720"&lt;/code&gt; scales the height to 720 pixels while computing the width proportionally and keeping it even; and &lt;code&gt;-c:a aac -b:a 128k&lt;/code&gt; encodes audio as AAC at 128 kbps.&lt;/p&gt;

&lt;h2&gt;
  
  
  CRF Value Selection Guide
&lt;/h2&gt;

&lt;p&gt;The table below lists common CRF ranges for quick reference. In practice, start with the middle of the recommended range for your scenario, test-encode a short clip, and fine-tune from there.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CRF Range&lt;/th&gt;
&lt;th&gt;Quality Level&lt;/th&gt;
&lt;th&gt;File Size&lt;/th&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;18-22&lt;/td&gt;
&lt;td&gt;High quality&lt;/td&gt;
&lt;td&gt;Large&lt;/td&gt;
&lt;td&gt;Archival, source backup, high-quality playback&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;23-26&lt;/td&gt;
&lt;td&gt;Standard&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;Web publishing, on-demand streaming, mobile playback&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;27-30&lt;/td&gt;
&lt;td&gt;Extreme compression&lt;/td&gt;
&lt;td&gt;Small&lt;/td&gt;
&lt;td&gt;Email, instant messaging, bandwidth-constrained delivery&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  CRF vs CBR vs VBR Comparison
&lt;/h2&gt;

&lt;p&gt;The table below compares the three modes across quality, size, encoding speed, and use case to help you choose based on your needs.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;CRF&lt;/th&gt;
&lt;th&gt;CBR&lt;/th&gt;
&lt;th&gt;VBR&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Quality stability&lt;/td&gt;
&lt;td&gt;High (consistent throughout)&lt;/td&gt;
&lt;td&gt;Low (artifacts in complex scenes)&lt;/td&gt;
&lt;td&gt;Medium (bounded by bitrate limits)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File size&lt;/td&gt;
&lt;td&gt;Unpredictable&lt;/td&gt;
&lt;td&gt;Predictable&lt;/td&gt;
&lt;td&gt;Roughly predictable (2-pass more precise)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Encoding speed&lt;/td&gt;
&lt;td&gt;Fast (single pass)&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;td&gt;Slower (2-pass about twice as long)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use case&lt;/td&gt;
&lt;td&gt;Offline compression, storage, web publishing&lt;/td&gt;
&lt;td&gt;Live streaming, real-time transmission&lt;/td&gt;
&lt;td&gt;Streaming delivery, size-constrained tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. How do I choose the right CRF value?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is no universally correct CRF value; it depends on your trade-off between quality and size. A good starting point is CRF 23-26. If the quality looks good, gradually increase the value to shrink the file further; if the quality is insufficient, decrease the value. For archival needs, 18-22 works well, and for size-sensitive delivery, 27-30 is appropriate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. What should I do if the compressed video looks blurry?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Blur is usually caused by insufficient bitrate or over-aggressive downscaling. Check a few things: first, lower the CRF value, for example from 28 to 24, to give the encoder more bits; second, verify that you have not shrunk the resolution too much, and raise it if needed; third, switch to a slower preset (such as slow or slower) to trade encoding time for better compression quality; fourth, confirm that you have not applied overly strong denoise or deinterlace filters, which can also soften the image when misconfigured.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Should I choose H.264 or H.265?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;H.264 has the widest compatibility, supported by virtually all modern devices, operating systems, and browsers, making it ideal for broad distribution such as web and mobile playback. H.265 (HEVC) is more efficient, producing files roughly 30%-50% smaller than H.264 at the same quality, but it encodes more slowly and is not supported by some older devices and browsers. If your goal is archival or distribution to modern devices, prefer H.265; if maximum compatibility is the priority, choose H.264.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Bitrate control is the heart of video compression, and choosing the right mode often matters more than tuning specific parameters. CRF prioritizes constant quality and is the first choice for offline compression and file storage; CBR prioritizes bitrate stability and suits live streaming and real-time transmission; VBR strikes a balance between the two and fits distribution scenarios with overall size constraints.&lt;/p&gt;

&lt;p&gt;In practice, mastering three points covers most needs: choose the bitrate control mode that matches your scenario, pick a sensible CRF value and fine-tune after a test encode, and select between H.264 and H.265 based on compatibility requirements. Combined with the preset knob for trading speed against efficiency, FFmpeg lets you produce videos that balance quality and size across any scenario.&lt;/p&gt;

&lt;p&gt;More Technology Articles: &lt;a href="https://www.uglypear.com/en/blog/" rel="noopener noreferrer"&gt;Tech Blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>python</category>
    </item>
  </channel>
</rss>
