Luban 2:簡(jiǎn)潔高效的Android圖片壓縮庫(kù)

Luban 2(魯班 2) —— Android圖片壓縮工具,仿微信朋友圈壓縮策略。

?? 目錄

?? 項(xiàng)目描述

開(kāi)源地址:Gitee | Github

目前做App開(kāi)發(fā)總繞不開(kāi)圖片這個(gè)元素。但是隨著手機(jī)拍照分辨率的提升,圖片的壓縮成為一個(gè)很重要的問(wèn)題。單純對(duì)圖片進(jìn)行裁切,壓縮已經(jīng)有很多文章介紹。但是裁切成多少,壓縮成多少卻很難控制好,裁切過(guò)頭圖片太小,質(zhì)量壓縮過(guò)頭則顯示效果太差。

于是自然想到App巨頭"微信"會(huì)是怎么處理,Luban(魯班)就是通過(guò)在微信朋友圈發(fā)送近100張不同分辨率圖片,對(duì)比原圖與微信壓縮后的圖片逆向推算出來(lái)的壓縮算法。

因?yàn)槭悄嫦蛲扑?,效果還沒(méi)法跟微信一模一樣,但是已經(jīng)很接近微信朋友圈壓縮后的效果,具體看以下對(duì)比!

本庫(kù)是 LubanKotlin 重構(gòu)版本,在升級(jí)核心算法的同時(shí),利用 Kotlin CoroutinesTurboJPEG 進(jìn)行了深度優(yōu)化。新算法比原算法更加健壯和高效,提供更高效的異步處理和更優(yōu)質(zhì)的壓縮效果。

?? 效果與對(duì)比

圖片類(lèi)型 原圖(分辨率, 大?。?/th> Luban(分辨率, 大?。?/th> Wechat(分辨率, 大小)
標(biāo)準(zhǔn)拍照 3024×4032, 5.10MB 1440×1920, 305KB 1440×1920, 303KB
高清大圖 4000×6000, 12.10MB 1440×2160, 318KB 1440×2160, 305KB
2K 截圖 1440×3200, 2.10MB 1440×3200, 148KB 1440×3200, 256KB
超長(zhǎng)記錄 1242×22080, 6.10MB 758×13490, 290KB 744×13129, 256KB
全景橫圖 12000×5000, 8.10MB 1440×600, 126KB 1440×600, 123KB
設(shè)計(jì)原稿 6000×6000, 6.90MB 1440×1440, 263KB 1440×1440, 279KB

?? 核心算法特性

本庫(kù)采用自適應(yīng)統(tǒng)一圖像壓縮算法 (Adaptive Unified Image Compression),通過(guò)原圖的分辨率特征,動(dòng)態(tài)應(yīng)用差異化策略,實(shí)現(xiàn)畫(huà)質(zhì)與體積的最優(yōu)平衡。

智能分辨率決策

  • 高清基準(zhǔn) (1440p):默認(rèn)以 1440px 作為短邊基準(zhǔn),確保在現(xiàn)代 2K/4K 屏幕上的視覺(jué)清晰度
  • 全景墻策略:自動(dòng)識(shí)別超大全景圖(長(zhǎng)邊 >10800px),鎖定長(zhǎng)邊為 1440px,保留完整視野
  • 超大像素陷阱:對(duì)超過(guò) 4096萬(wàn)像素的超高像素圖自動(dòng)執(zhí)行 1/4 降采樣處理
  • 長(zhǎng)圖內(nèi)存保護(hù):針對(duì)超長(zhǎng)截圖建立 10.24MP 像素上限,通過(guò)等比縮放防止 OOM

自適應(yīng)比特率控制

  • 極小圖 (<0.5MP):幾乎不進(jìn)行有損壓縮,防止壓縮偽影
  • 高頻信息圖 (0.5-1MP):提高編碼質(zhì)量,補(bǔ)償分辨率損失
  • 標(biāo)準(zhǔn)圖片 (1-3MP):應(yīng)用平衡系數(shù),對(duì)標(biāo)主流社交軟件體驗(yàn)
  • 超大圖/長(zhǎng)圖 (>3MP):應(yīng)用高壓縮率,顯著減少體積

健壯性保障

  • 膨脹回退:壓縮后體積大于原圖時(shí),自動(dòng)透?jìng)髟瓐D,確保絕不"負(fù)優(yōu)化"
  • 智能格式透?jìng)?/strong>:保留小體積 PNG 的透明通道,大體積 PNG 自動(dòng)轉(zhuǎn)碼為 JPEG
  • 輸入防御:妥善處理極端分辨率輸入(0、負(fù)數(shù)、1px 等),防止崩潰

?? 導(dǎo)入

確保項(xiàng)目的 build.gradlebuild.gradle.kts 已配置 Maven Central 倉(cāng)庫(kù):

repositories {
    mavenCentral()
}

在模塊的構(gòu)建文件中添加依賴(lài):

Kotlin DSL (build.gradle.kts):

dependencies {
    implementation("top.zibin:luban:2.0.0")
}

Groovy (build.gradle):

dependencies {
    implementation 'top.zibin:luban:2.0.0'
}

注意:請(qǐng)?jiān)L問(wèn) Maven Central 查看最新版本號(hào)。

?? 使用

? Kotlin (Coroutines)

在 Kotlin 中,推薦使用 suspend 函數(shù)進(jìn)行調(diào)用,代碼更簡(jiǎn)潔。

壓縮單張圖片

lifecycleScope.launch {
    val inputUri: Uri = ... // 圖片 Uri
    val outputDir = context.cacheDir
    
    Luban.compress(context, inputUri, outputDir)
        .onSuccess { file ->
            // 壓縮成功,file 為壓縮后的圖片文件
            Log.d("Luban", "Compressed: ${file.absolutePath}")
        }
        .onFailure { error ->
            // 處理錯(cuò)誤
            Log.e("Luban", "Error: ${error.message}")
        }
}

壓縮單張圖片文件

lifecycleScope.launch {
    val inputFile: File = ... 
    val outputDir = context.cacheDir
    
    Luban.compress(inputFile, outputDir)
        .onSuccess { file ->
            Log.d("Luban", "Compressed: ${file.absolutePath}")
        }
        .onFailure { error ->
            Log.e("Luban", "Error: ${error.message}")
        }
}

壓縮到指定文件路徑

lifecycleScope.launch {
    val inputFile: File = ...
    val outputFile = File(context.cacheDir, "custom_output.jpg")
    
    Luban.compressToFile(inputFile, outputFile)
        .onSuccess { file ->
            Log.d("Luban", "Compressed to: ${file.absolutePath}")
        }
        .onFailure { error ->
            Log.e("Luban", "Error: ${error.message}")
        }
}

并發(fā)壓縮多張圖片

lifecycleScope.launch {
    val uris: List<Uri> = ... 
    val outputDir = context.cacheDir

    val results = Luban.compress(context, uris, outputDir)
    
    results.forEach { result ->
        result.onSuccess { file -> 
            Log.d("Luban", "Compressed: ${file.absolutePath}")
        }
        .onFailure { error ->
            Log.e("Luban", "Error: ${error.message}")
        }
    }
}

并發(fā)壓縮多個(gè)文件

lifecycleScope.launch {
    val files: List<File> = ...
    val outputDir = context.cacheDir

    val results = Luban.compress(files, outputDir)
    
    results.forEach { result ->
        result.onSuccess { file -> 
            Log.d("Luban", "Compressed: ${file.absolutePath}")
        }
        .onFailure { error ->
            Log.e("Luban", "Error: ${error.message}")
        }
    }
}

在其他協(xié)程作用域中使用

如果不在 Activity/Fragment 中使用,可以使用 CoroutineScope

val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())

scope.launch {
    val inputUri: Uri = ...
    val outputDir = context.cacheDir
    
    Luban.compress(context, inputUri, outputDir)
        .onSuccess { file ->
            // 處理成功
        }
        .onFailure { error ->
            // 處理錯(cuò)誤
        }
}

? Java / Builder 模式

對(duì)于 Java 項(xiàng)目或偏好回調(diào)風(fēng)格的開(kāi)發(fā)者,可以使用兼容舊版風(fēng)格的 Luban.with() API。

壓縮單張圖片

Luban.with(context)
    .load(imageFile) // 支持 File, Uri, 或 String 路徑
    .setTargetDir(context.getCacheDir())
    .bindLifecycle(lifecycleOwner) // 可選:頁(yè)面銷(xiāo)毀時(shí)自動(dòng)取消
    .setCompressListener(new OnCompressListener() {
        @Override
        public void onStart() {
            // 開(kāi)始?jí)嚎s
        }

        @Override
        public void onSuccess(File file) {
            // 壓縮成功
        }

        @Override
        public void onError(Throwable e) {
            // 發(fā)生錯(cuò)誤
        }
    })
    .launch();

壓縮多張圖片

List<String> imagePaths = ...; // 圖片路徑列表

Luban.with(context)
    .load(imagePaths) // 加載圖片列表
    .setTargetDir(context.getCacheDir())
    .setCompressListener(new OnCompressListener() {
        @Override
        public void onStart() {
            // 開(kāi)始?jí)嚎s
        }

        @Override
        public void onSuccess(File file) {
            // 每張圖片壓縮成功后都會(huì)回調(diào)一次
            Log.d("Luban", "Compressed: " + file.getAbsolutePath());
        }

        @Override
        public void onError(Throwable e) {
            // 發(fā)生錯(cuò)誤
        }
    })
    .launch();

彩蛋

FlutterLuban 2 即將上線(xiàn),Android、iOS都能使用,敬請(qǐng)期待~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容