[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-6151":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":15,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":18,"compositeScore":19,"rankGlobal":10,"rankLanguage":10,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":23,"hasPages":21,"topics":24,"createdAt":10,"pushedAt":10,"updatedAt":28,"readmeContent":29,"aiSummary":30,"trendingCount":16,"starSnapshotCount":16,"syncStatus":18,"lastSyncTime":31,"discoverSource":32},6151,"Luban","Curzibn\u002FLuban","Curzibn","Luban 2（鲁班 2） —— 高效简洁的 Android 图片压缩工具库，像素级还原微信朋友圈压缩策略。(An efficient and concise Android image compression library that closely replicates the compression strategy of WeChat Moments.)","",null,"C",13745,2258,357,3,0,18,2,45,"Apache License 2.0",false,"master",true,[25,26,27],"android","image-compression","luban","2026-06-12 02:01:16","# Luban 2\n\n[![License](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicense-Apache%202.0-blue.svg)](LICENSE)\n[![Maven Central](https:\u002F\u002Fimg.shields.io\u002Fmaven-central\u002Fv\u002Ftop.zibin\u002Fluban.svg?label=Maven%20Central)](https:\u002F\u002Fsearch.maven.org\u002Fsearch?q=g:top.zibin%20a:luban)\n[![API](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FAPI-21%2B-brightgreen.svg?style=flat)](https:\u002F\u002Fandroid-arsenal.com\u002Fapi?level=21)\n\n[中文](README.md) | [English](README_EN.md)\n\nLuban 2（鲁班 2） —— 高效简洁的 Android 图片压缩工具库，像素级还原微信朋友圈压缩策略。\n\n## 📑 目录\n\n- [📖 项目描述](#-项目描述)\n- [📊 效果与对比](#-效果与对比)\n  - [🔬 核心算法特性](#-核心算法特性)\n- [📦 导入](#-导入)\n- [💻 使用](#-使用)\n  - [⚡ Kotlin (Coroutines)](#-kotlin-coroutines)\n  - [☕ Java \u002F Builder 模式](#-java--builder-模式)\n- [☕ 捐助](#-捐助)\n- [📄 License](#-license)\n\n# 📖 项目描述\n\n目前做`App`开发总绕不开图片这个元素。但是随着手机拍照分辨率的提升，图片的压缩成为一个很重要的问题。单纯对图片进行裁切，压缩已经有很多文章介绍。但是裁切成多少，压缩成多少却很难控制好，裁切过头图片太小，质量压缩过头则显示效果太差。\n\n于是自然想到`App`巨头\"微信\"会是怎么处理，`Luban`（鲁班）就是通过在微信朋友圈发送近100张不同分辨率图片，对比原图与微信压缩后的图片逆向推算出来的压缩算法。\n\n因为是逆向推算，效果还没法跟微信一模一样，但是已经很接近微信朋友圈压缩后的效果，具体看以下对比！\n\n本库是 `Luban` 的 **Kotlin 重构版本**，在升级核心算法的同时，利用 **Kotlin Coroutines** 和 **TurboJPEG** 进行了深度优化。新算法比原算法更加健壮和高效，提供更高效的异步处理和更优质的压缩效果。\n\n# 📊 效果与对比\n\n| 图片类型 | 原图（分辨率, 大小） | Luban（分辨率, 大小） | Wechat（分辨率, 大小） |\n| :--- | :--- | :--- | :--- |\n| **标准拍照** | 3024×4032, 5.10MB | 1440×1920, 305KB | 1440×1920, 303KB |\n| **高清大图** | 4000×6000, 12.10MB | 1440×2160, 318KB | 1440×2160, 305KB |\n| **2K 截图** | 1440×3200, 2.10MB | 1440×3200, 148KB | 1440×3200, 256KB |\n| **超长记录** | 1242×22080, 6.10MB | 758×13490, 290KB | 744×13129, 256KB |\n| **全景横图** | 12000×5000, 8.10MB | 1440×600, 126KB | 1440×600, 123KB |\n| **设计原稿** | 6000×6000, 6.90MB | 1440×1440, 263KB | 1440×1440, 279KB |\n\n## 🔬 核心算法特性\n\n本库采用**自适应统一图像压缩算法 (Adaptive Unified Image Compression)**，通过原图的分辨率特征，动态应用差异化策略，实现画质与体积的最优平衡。\n\n### 智能分辨率决策\n\n- **高清基准 (1440p)**：默认以 1440px 作为短边基准，确保在现代 2K\u002F4K 屏幕上的视觉清晰度\n- **全景墙策略**：自动识别超大全景图（长边 >10800px），锁定长边为 1440px，保留完整视野\n- **超大像素陷阱**：对超过 4096万像素的超高像素图自动执行 1\u002F4 降采样处理\n- **长图内存保护**：针对超长截图建立 10.24MP 像素上限，通过等比缩放防止 OOM\n\n### 自适应比特率控制\n\n- **极小图 (\u003C0.5MP)**：几乎不进行有损压缩，防止压缩伪影\n- **高频信息图 (0.5-1MP)**：提高编码质量，补偿分辨率损失\n- **标准图片 (1-3MP)**：应用平衡系数，对标主流社交软件体验\n- **超大图\u002F长图 (>3MP)**：应用高压缩率，显著减少体积\n\n### 健壮性保障\n\n- **膨胀回退**：压缩后体积大于原图时，自动透传原图，确保绝不\"负优化\"\n- **智能格式透传**：保留小体积 PNG 的透明通道，大体积 PNG 自动转码为 JPEG\n- **输入防御**：妥善处理极端分辨率输入（0、负数、1px 等），防止崩溃\n\n# 📦 导入\n\n确保项目的 `build.gradle` 或 `build.gradle.kts` 已配置 Maven Central 仓库：\n\n```kotlin\nrepositories {\n    mavenCentral()\n}\n```\n\n在模块的构建文件中添加依赖：\n\n**Kotlin DSL (`build.gradle.kts`):**\n\n```kotlin\ndependencies {\n    implementation(\"top.zibin:luban:2.0.1\")\n}\n```\n\n**Groovy (`build.gradle`):**\n\n```groovy\ndependencies {\n    implementation 'top.zibin:luban:2.0.1'\n}\n```\n\n> 注意：请访问 [Maven Central](https:\u002F\u002Fsearch.maven.org\u002Fsearch?q=g:top.zibin%20a:luban) 查看最新版本号。\n\n# 💻 使用\n\n### ⚡ Kotlin (Coroutines)\n\nLuban 提供了三种 Kotlin 调用方式，从最符合 Kotlin 习惯到传统方式：\n\n#### 1. DSL 风格（推荐）\n\n最符合 Kotlin 习惯的方式是使用 DSL API：\n\n```kotlin\nlifecycleScope.launch {\n    val results = luban(context) {\n        outputDir = File(context.cacheDir, \"compressed\")\n        \n        compress(imageUri1)\n        compress(imageUri2)\n        compress(imageFile1)\n        compress(listOf(imageFile2, imageFile3))\n        compress(listOf(imageUri3, imageUri4))\n    }\n    \n    results.forEach { result ->\n        result.getOrNull()?.let { file ->\n            Log.d(\"Luban\", \"压缩成功: ${file.absolutePath}\")\n        } ?: run {\n            val error = result.exceptionOrNull()\n            Log.e(\"Luban\", \"压缩失败: ${error?.message}\")\n        }\n    }\n}\n```\n\n**注意：** \n- 对于 `Uri` 类型的压缩，如果不指定 `outputDir`，默认使用 `context.cacheDir`。对于 `File` 类型的压缩，必须显式设置 `outputDir`。\n- DSL 配置是声明式的，配置顺序不影响结果。你可以先设置 `outputDir` 再调用 `compress()`，也可以先调用 `compress()` 再设置 `outputDir`。\n\n#### 2. 扩展函数\n\n你也可以使用扩展函数，获得更流畅的 API：\n\n```kotlin\nlifecycleScope.launch {\n    val result = imageUri.compressTo(context)\n    \n    result.getOrElse { error ->\n        Log.e(\"Luban\", \"压缩失败: ${error.message}\")\n        return@launch\n    }.let { file ->\n        Log.d(\"Luban\", \"压缩成功: ${file.absolutePath}\")\n    }\n}\n```\n\n**压缩单个文件：**\n```kotlin\nval result = inputFile.compressTo(outputDir)\n```\n\n**压缩到指定文件：**\n```kotlin\nval result = inputFile.compressToFile(outputFile)\n```\n\n**批量压缩：**\n```kotlin\nval results = fileList.compressTo(outputDir)\nval results = uriList.compressTo(context)\n```\n\n#### 3. 传统静态方法\n\n使用传统静态方法：\n\n```kotlin\nlifecycleScope.launch {\n    val result = Luban.compress(context, inputUri, outputDir)\n    \n    result.getOrElse { error ->\n        Log.e(\"Luban\", \"压缩失败: ${error.message}\")\n        return@launch\n    }.let { file ->\n        Log.d(\"Luban\", \"压缩成功: ${file.absolutePath}\")\n    }\n}\n```\n\n**可用方法：**\n- `Luban.compress(context, input: Uri, outputDir: File = context.cacheDir): Result\u003CFile>`\n- `Luban.compress(input: File, outputDir: File): Result\u003CFile>`\n- `Luban.compressToFile(input: File, output: File): Result\u003CFile>`\n- `Luban.compress(context, inputs: List\u003CUri>, outputDir: File = context.cacheDir): List\u003CResult\u003CFile>>`\n- `Luban.compress(inputs: List\u003CFile>, outputDir: File): List\u003CResult\u003CFile>>`\n\n**在其他协程作用域中使用：**\n```kotlin\nval scope = CoroutineScope(Dispatchers.Main + SupervisorJob())\n\nscope.launch {\n    val result = Luban.compress(context, inputUri)\n    \n    result.getOrElse { error ->\n        \u002F\u002F 处理错误\n        return@launch\n    }.let { file ->\n        \u002F\u002F 处理成功\n    }\n}\n```\n\n### ☕ Java \u002F Builder 模式\n\n对于 Java 项目或偏好回调风格的开发者，可以使用兼容旧版风格的 `Luban.with()` API。\n\n#### 压缩单张图片\n\n```java\nLuban.with(context)\n    .load(imageFile) \u002F\u002F 支持 File, Uri, 或 String 路径\n    .setTargetDir(context.getCacheDir())\n    .bindLifecycle(lifecycleOwner) \u002F\u002F 可选：页面销毁时自动取消\n    .setCompressListener(new OnCompressListener() {\n        @Override\n        public void onStart() {\n            \u002F\u002F 开始压缩\n        }\n\n        @Override\n        public void onSuccess(File file) {\n            \u002F\u002F 压缩成功\n        }\n\n        @Override\n        public void onError(Throwable e) {\n            \u002F\u002F 发生错误\n        }\n    })\n    .launch();\n```\n\n#### 压缩多张图片\n\n```java\nList\u003CString> imagePaths = ...; \u002F\u002F 图片路径列表\n\nLuban.with(context)\n    .load(imagePaths) \u002F\u002F 加载图片列表\n    .setTargetDir(context.getCacheDir())\n    .setCompressListener(new OnCompressListener() {\n        @Override\n        public void onStart() {\n            \u002F\u002F 开始压缩\n        }\n\n        @Override\n        public void onSuccess(File file) {\n            \u002F\u002F 每张图片压缩成功后都会回调一次\n            Log.d(\"Luban\", \"Compressed: \" + file.getAbsolutePath());\n        }\n\n        @Override\n        public void onError(Throwable e) {\n            \u002F\u002F 发生错误\n        }\n    })\n    .launch();\n```\n\n# ☕ 捐助\n\n如果这个项目对您有帮助，欢迎通过以下方式支持我的工作。您的支持是我持续改进和维护这个项目的动力。\n\n\u003Cdiv align=\"center\">\n\n\u003Ctable>\n\u003Ctr>\n\u003Ctd align=\"center\">\n\u003Cimg src=\"images\u002Falipay.png\" width=\"300\" alt=\"支付宝收款码\" \u002F>\n\u003C\u002Ftd>\n\u003Ctd width=\"50\">\u003C\u002Ftd>\n\u003Ctd align=\"center\">\n\u003Cimg src=\"images\u002Fwechat.png\" width=\"300\" alt=\"微信收款码\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\n\u003C\u002Fdiv>\n\n感谢您的支持！🙏\n\n# 📄 License\n\n    Copyright 2025 郑梓斌\n    \n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n    \n        http:\u002F\u002Fwww.apache.org\u002Flicenses\u002FLICENSE-2.0\n    \n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n","Luban 2 是一个高效简洁的 Android 图片压缩工具库，旨在像素级还原微信朋友圈的压缩策略。其核心功能包括自适应统一图像压缩算法，能够根据图片分辨率特征动态调整压缩策略，以达到画质与体积的最佳平衡。技术特点涵盖智能分辨率决策、自适应比特率控制及健壮性保障机制，如膨胀回退和智能格式透传等。该库特别适用于需要高质量图片压缩的应用场景，如社交软件中的图片分享、移动应用内的图片处理等，可有效提升用户体验并节省存储空间。","2026-06-11 03:05:47","top_language"]