png, svg转矢量图,webp到底用什么格式的图片呢?
在Android开发中选择图片资源格式(PNG、SVG、WebP)需综合考虑应用场景、性能需求、兼容性及维护成本。以下是综合判定逻辑及实践建议:
📊 一、核心格式特性对比
格式 | 优势 | 劣势 | 适用场景 | 性能影响 |
---|---|---|---|---|
PNG<br>(位图) | 无损压缩、支持透明度、显示质量高 | 文件体积大、多分辨率需多套资源 | 1. 带透明度的UI元素(按钮/图标)<br>2. 细节丰富的静态图(如插画) | 内存占用高(与分辨率正相关)
1 3 |
SVG<br>(矢量图) | 无限缩放不失真、单文件适配多分辨率、体积小 | 复杂图形渲染耗CPU、不支持投影/模糊等特效 | 1. 纯色图标/简单图形<br>2. Material Design图标<br>3. 需要动态修改颜色的元素 | CPU渲染开销大(尤其复杂SVG)<br>内存占用可能高于PNG
6 7 |
WebP<br>(位图) | 高压缩率(比PNG小26%↑,比JPEG小25%~34%)、支持有损/无损/透明度/动画 | 低版本Android需兼容库(API<14)、转换工具少 | 1. 网络传输图片(缩略图/背景)<br>2. 需平衡质量与体积的场景<br>3. 替代GIF的动画 | 解码速度慢于JPEG 1.5倍,但加载更快(体积优势)
9 10 |
所以基本一些简单的icon,可以用svg
大图网图 webp
复杂或者不太大的图片png
由于历史遗留项目,用了很多PNG图片,导致APK包要一百多M。
优化思路,将部分PNG图片转换成webp
那是全部都要转换吗?
大概一个判断标准
推荐的图片大小判断标准(基于 Android 性能优化实践)
图片大小 | 转换决策 | 原因和说明 |
---|---|---|
<2KB | ❌ 不要转换 | 原始 PNG 头信息比 WebP 更小,转换后反而可能增大约 100-300 字节 |
2KB-10KB | ⚠️ 可选转换 | 转换后能节省约 15-30% 空间,但对整体包大小影响有限 |
10KB-50KB | ✅ 强烈推荐转换 | 转换后能节省 25-40% 空间,有明显收益 |
>50KB | ✅ 必须转换 | 转换后节省可达 40-70%,对 APK 大小影响显著 |
基于上面的标准
我把阈值设置在30k
大致脚本文件如下 findlargepngs.ps1
param(
[Parameter(Mandatory=$false, HelpMessage="Target directory path")]
[string]$TargetPath = (Get-Location).Path,
[Parameter(Mandatory=$false, HelpMessage="Minimum file size in KB")]
[int]$MinSizeKB = 30
)
# Set encoding to UTF-8 to try to avoid any encoding issues
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
# Check if directory exists
if (-not (Test-Path -Path $TargetPath -PathType Container)) {
Write-Host "Error: Directory does not exist - $TargetPath" -ForegroundColor Red
exit 1
}
# Check if cwebp is available
$cwebpPath = "cwebp.exe"
if (-not (Get-Command $cwebpPath -ErrorAction SilentlyContinue)) {
Write-Host "Warning: cwebp.exe not found." -ForegroundColor Yellow
Write-Host "Download from: https://developers.google.com/speed/webp/download and add to PATH" -ForegroundColor Cyan
Write-Host "OR provide full path to cwebp.exe" -NoNewline
$cwebpPath = Read-Host
if (-not (Test-Path $cwebpPath)) {
Write-Host "cwebp.exe not found at provided path. Exiting." -ForegroundColor Red
exit 1
}
}
# Create log file
$logPath = Join-Path -Path $TargetPath -ChildPath "PNG_WebP_Conversion_Log.txt"
"=== PNG to WebP Conversion Log ===" | Out-File $logPath
"Time: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" | Out-File $logPath -Append
"Directory: $TargetPath" | Out-File $logPath -Append
"Minimum Size: ${MinSizeKB}KB" | Out-File $logPath -Append
"" | Out-File $logPath -Append
Write-Host "`nScanning directory: $TargetPath"
Write-Host "Looking for PNG files larger than ${MinSizeKB}KB..." -ForegroundColor Cyan
# Find PNG files larger than the threshold
$minSizeBytes = $MinSizeKB * 1024
$largePngs = Get-ChildItem -Path $TargetPath -Recurse -Include "*.png" -ErrorAction SilentlyContinue |
Where-Object { $_.Length -gt $minSizeBytes }
$totalCount = $largePngs.Count
if ($totalCount -eq 0) {
Write-Host "No PNG files found larger than ${MinSizeKB}KB." -ForegroundColor Yellow
"No eligible files found." | Out-File $logPath -Append
exit
}
Write-Host "Found $totalCount files to convert."
# Conversion process
$successCount = 0
$skippedCount = 0
$failedCount = 0
$totalSpaceSaved = 0
foreach ($png in $largePngs) {
$pngPath = $png.FullName
$webpPath = [System.IO.Path]::ChangeExtension($pngPath, "webp")
$originalSize = $png.Length / 1KB
$originalSize = [math]::Round($originalSize, 2)
Write-Host "`nProcessing: $($png.Name) [$originalSize KB]"
"Processing file: $pngPath" | Out-File $logPath -Append
"Original size: $originalSize KB" | Out-File $logPath -Append
try {
# Convert: Use lossless if transparent, otherwise lossy with quality 80
$hasTransparency = $false
try {
# Check for transparency using ImageMagick (if available) or assume false
$hasTransparency = & magick identify -format "%[opaque]" $pngPath 2>$null
$hasTransparency = ($hasTransparency -eq "false")
} catch {
$hasTransparency = $false
}
if ($hasTransparency) {
& $cwebpPath -lossless -mt "$pngPath" -o "$webpPath"
} else {
& $cwebpPath -q 80 -mt "$pngPath" -o "$webpPath"
}
if ($LASTEXITCODE -ne 0) {
throw "Conversion failed with error code: $LASTEXITCODE"
}
# Check if WebP file was created
if (-not (Test-Path $webpPath)) {
throw "WebP file not created after conversion."
}
$webpSize = (Get-Item $webpPath).Length / 1KB
$webpSize = [math]::Round($webpSize, 2)
$spaceSaved = $originalSize - $webpSize
# Check if the new file is actually smaller
if ($webpSize -ge $originalSize) {
"Warning: Converted file not smaller ($originalSize KB → $webpSize KB)" | Out-File $logPath -Append
Write-Host " Warning: Converted file not smaller ($originalSize KB → $webpSize KB)" -ForegroundColor Yellow
# Remove the WebP file and skip
Remove-Item -Path $webpPath -Force -ErrorAction SilentlyContinue
$skippedCount++
} else {
# Calculate space saved
$spaceSaved = [math]::Round($spaceSaved, 2)
$savedPercent = [math]::Round(($spaceSaved / $originalSize) * 100, 1)
$totalSpaceSaved += $spaceSaved
# Backup the original PNG (optional)
#$backupPath = $pngPath + ".orig"
#Copy-Item -Path $pngPath -Destination $backupPath -Force -ErrorAction SilentlyContinue
# Replace the original with WebP
Remove-Item -Path $pngPath -Force
"Converted successfully: $originalSize KB → $webpSize KB, Saved $spaceSaved KB ($savedPercent%)" | Out-File $logPath -Append
Write-Host " Converted successfully: Saved $spaceSaved KB ($savedPercent%)" -ForegroundColor Green
$successCount++
}
} catch {
$errorMsg = $_.Exception.Message
"Error: $errorMsg" | Out-File $logPath -Append
Write-Host " Error: $errorMsg" -ForegroundColor Red
$failedCount++
}
}
# Generate report
$endTime = Get-Date
$elapsedTime = New-TimeSpan -Start (Get-Date) -End $endTime | ForEach-Object { $_.TotalMinutes }
$elapsedTime = [math]::Round($elapsedTime, 1)
# Output results
Write-Host "`n================================================" -ForegroundColor Cyan
Write-Host "Conversion Complete!" -ForegroundColor Green
Write-Host "Total files: $totalCount"
Write-Host "Successfully converted: $successCount" -ForegroundColor Green
Write-Host "Skipped (not smaller): $skippedCount" -ForegroundColor Yellow
Write-Host "Failures: $failedCount" -ForegroundColor Red
Write-Host "Total space saved: $([math]::Round($totalSpaceSaved, 2)) KB" -ForegroundColor Cyan
Write-Host "Time elapsed: $elapsedTime minutes" -ForegroundColor Cyan
Write-Host "Log file: $logPath" -ForegroundColor Magenta
Write-Host "================================================" -ForegroundColor Cyan
命令行运行,添加目标地址
.\findlargepngs.ps1 -TargetPath "E:\workspace\xxxx\src\main"
即可将png转换成webp
最后APK大小成功减小50%