6.6.3 - Alpha5 - images.save 方法使用 quality 参数时支持 png 格式的文件体积压缩 (issue #367)
This commit is contained in:
@@ -546,10 +546,33 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File
|
||||
MLKIT_BARCODE(
|
||||
label = "MLKit Barcode",
|
||||
aliases = listOf("barcode", "mlkit-barcode", "mlkit_barcode"),
|
||||
libsToInclude = listOf(
|
||||
"libbarhopper_v3.so",
|
||||
),
|
||||
assetDirsToExclude = listOf(
|
||||
"mlkit_barcode_models",
|
||||
),
|
||||
);
|
||||
),
|
||||
|
||||
MEDIA_INFO(
|
||||
label = "MediaInfo",
|
||||
aliases = listOf("mediainfo", "media-info", "media_info"),
|
||||
libsToInclude = listOf(
|
||||
"libmediainfo.so",
|
||||
),
|
||||
),
|
||||
|
||||
IMAGE_QUANT(
|
||||
label = "Image Quantization",
|
||||
aliases = listOf("imagequant", "image-quant", "image-quantization", "image_quant", "image_quantization"),
|
||||
libsToInclude = listOf(
|
||||
"libpng.so",
|
||||
"libpng16d.so",
|
||||
"libpngquant_bridge.so",
|
||||
),
|
||||
),
|
||||
|
||||
;
|
||||
|
||||
fun ensureLibFiles(moduleName: String = label) {
|
||||
if (!isInrt) return
|
||||
|
||||
@@ -61,7 +61,7 @@ public final class ImageFeatureMatching {
|
||||
* reused later by {@link #featureMatching}</li>
|
||||
* </ol></p>
|
||||
*
|
||||
* <p><b>zh-CN</b><br>
|
||||
* <p><b>zh-CN:</b><br>
|
||||
*
|
||||
* 创建 (预计算) 特征匹配描述符.<br>
|
||||
* 典型流程: <pre>
|
||||
@@ -168,7 +168,7 @@ public final class ImageFeatureMatching {
|
||||
* <li>If caller sets {@code debugMatchesImagePath}, save visualization of match lines to that path</li>
|
||||
* </ol></p>
|
||||
*
|
||||
* <p><b>zh-CN</b><br>
|
||||
* <p><b>zh-CN:</b><br>
|
||||
*
|
||||
* 在两张图的特征描述符之间执行匹配, 并 (可选) 估算单应矩阵以获得被 object 图在 scene 图中的投影区域.<br>
|
||||
* <p>内部流程: <br>
|
||||
|
||||
@@ -35,6 +35,8 @@ import org.autojs.autojs.core.ui.inflater.util.Drawables;
|
||||
import org.autojs.autojs.pio.UncheckedIOException;
|
||||
import org.autojs.autojs.runtime.ScriptRuntime;
|
||||
import org.autojs.autojs.runtime.api.ImageFeatureMatching.FeatureMatchingDescriptor;
|
||||
import org.autojs.autojs.runtime.exception.WrappedRuntimeException;
|
||||
import org.autojs.autojs.util.BitmapUtils;
|
||||
import org.autojs.autojs6.R;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -254,13 +256,38 @@ public class Images {
|
||||
return imageWrapper;
|
||||
}
|
||||
|
||||
public boolean save(@NonNull ImageWrapper image, String path, String format, int quality) throws IOException {
|
||||
Bitmap.CompressFormat compressFormat = parseImageFormat(format);
|
||||
public boolean save(@NonNull ImageWrapper image,
|
||||
@NonNull String path,
|
||||
@NonNull String format,
|
||||
int quality) throws IOException {
|
||||
|
||||
Bitmap bitmap = image.getBitmap();
|
||||
FileOutputStream outputStream = new FileOutputStream(path);
|
||||
boolean b = bitmap.compress(compressFormat, quality, outputStream);
|
||||
image.shoot();
|
||||
return b;
|
||||
Bitmap.CompressFormat compressFormat = parseImageFormat(format);
|
||||
|
||||
if (compressFormat == Bitmap.CompressFormat.PNG && quality != 100) {
|
||||
// ARGB_8888 -> RGBA[]
|
||||
byte[] rgba = BitmapUtils.bitmapToRgba(bitmap);
|
||||
byte[] compressed = PngQuantBridge.quantize(rgba, bitmap.getWidth(), bitmap.getHeight(), quality);
|
||||
if (compressed != null) {
|
||||
try (FileOutputStream fos = new FileOutputStream(path)) {
|
||||
fos.write(compressed);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
throw new WrappedRuntimeException("PNG quantization failed");
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
if (compressFormat == Bitmap.CompressFormat.WEBP_LOSSLESS && quality != 100) {
|
||||
throw new IllegalArgumentException(mContext.getString(R.string.error_webp_lossless_quality_not_supported));
|
||||
}
|
||||
}
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(path)) {
|
||||
boolean b = bitmap.compress(compressFormat, quality, fos);
|
||||
image.shoot();
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
// public EventEmitter select() {
|
||||
@@ -357,13 +384,13 @@ public class Images {
|
||||
case "png" -> Bitmap.CompressFormat.PNG;
|
||||
case "jpeg", "jpg" -> Bitmap.CompressFormat.JPEG;
|
||||
case "webp" -> Bitmap.CompressFormat.WEBP;
|
||||
case "webp_lossy" -> {
|
||||
case "webp_lossy", "webp-lossy" -> {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
yield Bitmap.CompressFormat.WEBP_LOSSY;
|
||||
}
|
||||
throw new IllegalArgumentException("Image format \"WEBP_LOSSY\" only supports on Android API Level 30 (11) [R] and above");
|
||||
}
|
||||
case "webp_lossless" -> {
|
||||
case "webp_lossless", "webp-lossless" -> {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
yield Bitmap.CompressFormat.WEBP_LOSSLESS;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.autojs.autojs.runtime.api;
|
||||
|
||||
public class PngQuantBridge {
|
||||
|
||||
static {
|
||||
System.loadLibrary("pngquant_bridge");
|
||||
}
|
||||
|
||||
/**
|
||||
* Quantizes a 32-bit RGBA image to an 8-bit indexed PNG and returns the encoded bytes.<br>
|
||||
* <p>
|
||||
* The routine converts the input buffer (RGBA8888) to a palette-based image through
|
||||
* <em>libimagequant</em> and then writes it out as PNG8. The PNG/Deflate stage that follows
|
||||
* is <b>strictly lossless</b>—the stream produced by this method can always be inflated
|
||||
* back to the same 8-bit palette data byte-for-byte.<br>
|
||||
* <p>
|
||||
* The potentially visible degradation comes solely from the <b>color quantization</b> step:
|
||||
* ~16.7 M true-color values are mapped to ≤256 palette entries. How noticeable this mapping is
|
||||
* depends on both the source image and the {@code quality} you request.
|
||||
* <ul>
|
||||
* <li>{@code quality} represents the upper limit of <i>Mean Square Error × 10</i> accepted
|
||||
* by libimagequant (range 0–100). Lower numbers allow larger error, producing smaller files.</li>
|
||||
* <li>Because many graphics are well represented with 256 colors, even an extremely low
|
||||
* {@code quality} such as {@code 1} may look almost identical to the original while shrinking
|
||||
* to 5–20 % of its former size.</li>
|
||||
* <li>No further lossy step exists during PNG writing; the format itself does not permit it.</li>
|
||||
* </ul>
|
||||
* <p><b>zh-CN:</b><br>
|
||||
* 该方法把 32 位 RGBA 图像量化为 8 位索引色 PNG, 并返回编码后的字节数组.<br>
|
||||
* PNG 的 Deflate 压缩阶段完全<strong>无损</strong>; 图像失真来自量化过程: 32 位真彩被映射到
|
||||
* ≤256 色调色板, 失真程度由 {@code quality} 决定.
|
||||
* <ul>
|
||||
* <li>{@code quality} 取值 0–100, 对应 libimagequant 允许的 (MSE×10)上限; 数值越小, 容许误差越大, 文件越小.</li>
|
||||
* <li>许多图片用 256 色即可精准表示, 因此即便 {@code quality}=1 也可能与原图几乎无差别, 体积却可缩至原来的 5–20 %.</li>
|
||||
* <li>PNG 规范不支持在压缩阶段引入有损处理, 因此不会像 JPEG 那样再出现马赛克等失真.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param rgba contiguous RGBA8888 buffer; length must equal {@code width * height * 4}
|
||||
* @param width image width in pixels
|
||||
* @param height image height in pixels
|
||||
* @param quality libimagequant quality (0–100, lower = smaller file & potentially higher error)
|
||||
* @return palette-based PNG bytes (may contain transparency)
|
||||
*/
|
||||
public static native byte[] quantize(byte[] rgba, int width, int height, int quality);
|
||||
|
||||
}
|
||||
@@ -143,8 +143,19 @@ abstract class Augmentable(private val scriptRuntime: ScriptRuntime? = null) : F
|
||||
try {
|
||||
(this as Invokable).invoke(*args)
|
||||
} catch (e: Exception) {
|
||||
val message = e.message?.let {
|
||||
globalContext.getString(R.string.error_failed_to_call_method_with_cause, key, it)
|
||||
val message = e.message?.let { msg ->
|
||||
when {
|
||||
msg.contains("\n") -> {
|
||||
msg.split("\n").let { split ->
|
||||
globalContext.getString(R.string.error_failed_to_call_method_with_cause, key, split.first()).let { result ->
|
||||
split.slice(1..split.lastIndex).joinToString("\n").takeUnless { it.isBlank() }?.let {
|
||||
"$result\n$it"
|
||||
} ?: result
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> globalContext.getString(R.string.error_failed_to_call_method_with_cause, key, msg)
|
||||
}
|
||||
} ?: globalContext.getString(R.string.error_failed_to_call_method, key)
|
||||
throw WrappedRuntimeException(message, e)
|
||||
}
|
||||
|
||||
@@ -1334,8 +1334,11 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
|
||||
|
||||
private fun parseImageFormat(o: Any?): String = when {
|
||||
o.isJsNullish() -> "png"
|
||||
else -> when (val format = coerceString(o).lowercase()) {
|
||||
else -> when (val format = coerceString(o).lowercase().trim()) {
|
||||
"" -> "png"
|
||||
"png", "jpg", "jpeg", "webp" -> format
|
||||
"webp_lossless", "webp-lossless" -> format
|
||||
"webp_lossy", "webp-lossy" -> format
|
||||
else -> throw WrappedIllegalArgumentException("Unknown image format: $format")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,4 +34,28 @@ object BitmapUtils {
|
||||
.also { drawable.draw(Canvas(it)) }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun bitmapToRgba(bmp: Bitmap): ByteArray {
|
||||
val w = bmp.getWidth()
|
||||
val h = bmp.getHeight()
|
||||
|
||||
require(w > 0 && h > 0) { "bitmap size is 0" }
|
||||
|
||||
val pixelCount = w * h
|
||||
val byteCount = pixelCount * 4
|
||||
|
||||
val rgba = ByteArray(byteCount)
|
||||
val argb = IntArray(pixelCount)
|
||||
bmp.getPixels(argb, 0, w, 0, 0, w, h)
|
||||
|
||||
var i4 = 0
|
||||
for (p in argb) {
|
||||
rgba[i4++] = ((p shr 16) and 0xFF).toByte() // R
|
||||
rgba[i4++] = ((p shr 8) and 0xFF).toByte() // G
|
||||
rgba[i4++] = (p and 0xFF).toByte() // B
|
||||
rgba[i4++] = ((p shr 24) and 0xFF).toByte() // A
|
||||
}
|
||||
return rgba
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1048,5 +1048,6 @@
|
||||
<string name="error_no_applications_available_for_viewing_this_file">لا توجد تطبيقات متاحة لعرض هذا الملف</string>
|
||||
<string name="error_no_applications_available_for_sending_this_file">لا توجد تطبيقات متاحة لإرسال هذا الملف</string>
|
||||
<string name="error_no_applications_available_for_playing_this_file">لا توجد تطبيقات متاحة لتشغيل هذا الملف</string>
|
||||
<string name="error_webp_lossless_quality_not_supported">لا يمكن ضغط تنسيق WebP-Lossless باستخدام معامل الجودة؛ استخدم JPEG/PNG/WebP-Lossy بدلاً من ذلك</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -1043,5 +1043,6 @@
|
||||
<string name="error_no_applications_available_for_viewing_this_file">No applications available for viewing this file</string>
|
||||
<string name="error_no_applications_available_for_sending_this_file">No applications available for sending this file</string>
|
||||
<string name="error_no_applications_available_for_playing_this_file">No applications available for playing this file</string>
|
||||
<string name="error_webp_lossless_quality_not_supported">Format WebP-Lossless cannot be compressed with a quality parameter, use JPEG/PNG/WebP-Lossy instead</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -1046,5 +1046,6 @@
|
||||
<string name="error_no_applications_available_for_viewing_this_file">No hay aplicaciones disponibles para ver este archivo</string>
|
||||
<string name="error_no_applications_available_for_sending_this_file">No hay aplicaciones disponibles para enviar este archivo</string>
|
||||
<string name="error_no_applications_available_for_playing_this_file">No hay aplicaciones disponibles para reproducir este archivo</string>
|
||||
<string name="error_webp_lossless_quality_not_supported">El formato WebP-Lossless no se puede comprimir con un parámetro de calidad; usa JPEG/PNG/WebP-Lossy en su lugar</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -1046,5 +1046,6 @@
|
||||
<string name="error_no_applications_available_for_viewing_this_file">Aucune application disponible pour afficher ce fichier</string>
|
||||
<string name="error_no_applications_available_for_sending_this_file">Aucune application disponible pour envoyer ce fichier</string>
|
||||
<string name="error_no_applications_available_for_playing_this_file">Aucune application disponible pour lire ce fichier</string>
|
||||
<string name="error_webp_lossless_quality_not_supported">Le format WebP-Lossless ne peut pas être compressé avec un paramètre de qualité ; utilisez plutôt JPEG/PNG/WebP-Lossy</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -1047,5 +1047,6 @@
|
||||
<string name="error_no_applications_available_for_viewing_this_file">このファイルを表示できるアプリがありません</string>
|
||||
<string name="error_no_applications_available_for_sending_this_file">このファイルを送信できるアプリがありません</string>
|
||||
<string name="error_no_applications_available_for_playing_this_file">このファイルを再生できるアプリがありません</string>
|
||||
<string name="error_webp_lossless_quality_not_supported">WebP-Lossless 形式は品質パラメータで圧縮できません, 代わりに JPEG/PNG/WebP-Lossy を使用してください</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -182,7 +182,7 @@
|
||||
<string name="error_excessive_width_for_template_n_region">너비 초과: 템플릿 [%1$d] > 영역 [%2$d]</string>
|
||||
<string name="error_failed_to_apply_current_color_history">현재 색상 기록 적용에 실패했습니다</string>
|
||||
<string name="error_failed_to_call_method">메서드 \"%s\"를 호출하지 못했습니다</string>
|
||||
<string name="error_failed_to_call_method_with_cause"><![CDATA[메서드 \"%1$s\"를 호출하지 못했습니다: [ %2$s ]]]></string>
|
||||
<string name="error_failed_to_call_method_with_cause"><![CDATA[메서드 \"%1$s\" 를 호출하지 못했습니다: [ %2$s ]]]></string>
|
||||
<string name="error_failed_to_convert_into_drawable">%s 값을 Drawable 로 변환하지 못했습니다</string>
|
||||
<string name="error_failed_to_grant_shizuku_access">Shizuku 권한을 부여하지 못했습니다</string>
|
||||
<string name="error_failed_to_instantiate">\"%s\" 인스턴스 생성에 실패했습니다</string>
|
||||
@@ -1048,5 +1048,6 @@
|
||||
<string name="error_no_applications_available_for_viewing_this_file">이 파일을 볼 수 있는 앱이 없습니다</string>
|
||||
<string name="error_no_applications_available_for_sending_this_file">이 파일을 전송할 수 있는 앱이 없습니다</string>
|
||||
<string name="error_no_applications_available_for_playing_this_file">이 파일을 재생할 수 있는 앱이 없습니다</string>
|
||||
<string name="error_webp_lossless_quality_not_supported">WebP-Lossless 형식은 품질 파라미터로 압축할 수 없습니다, 대신 JPEG/PNG/WebP-Lossy를 사용하세요</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -1046,5 +1046,6 @@
|
||||
<string name="error_no_applications_available_for_viewing_this_file">Нет приложений для просмотра этого файла</string>
|
||||
<string name="error_no_applications_available_for_sending_this_file">Нет приложений для отправки этого файла</string>
|
||||
<string name="error_no_applications_available_for_playing_this_file">Нет приложений для воспроизведения этого файла</string>
|
||||
<string name="error_webp_lossless_quality_not_supported">Формат WebP-Lossless нельзя сжать с параметром качества; используйте вместо этого JPEG/PNG/WebP-Lossy</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -177,12 +177,12 @@
|
||||
<string name="error_excessive_height_for_template_n_region">高度超限: 模板圖像 [%1$d] > 限定區域 [%2$d]</string>
|
||||
<string name="error_excessive_width_for_template_n_region">寬度超限: 模板圖像 [%1$d] > 限定區域 [%2$d]</string>
|
||||
<string name="error_failed_to_apply_current_color_history">應用當前歷史顏色失敗</string>
|
||||
<string name="error_failed_to_call_method">調用方法 \"%s\" 失敗</string>
|
||||
<string name="error_failed_to_call_method_with_cause"><![CDATA[調用方法 \"%1$s\" 失敗: [ %2$s ]]]></string>
|
||||
<string name="error_failed_to_call_method">方法 \"%s\" 調用失敗</string>
|
||||
<string name="error_failed_to_call_method_with_cause"><![CDATA[方法 \"%1$s\" 調用失敗: [ %2$s ]]]></string>
|
||||
<string name="error_failed_to_convert_into_drawable">無法將值 %s 轉換為 Drawable 實例</string>
|
||||
<string name="error_failed_to_grant_shizuku_access">Shizuku 權限授予失敗</string>
|
||||
<string name="error_failed_to_instantiate">創建實例 \"%s\" 失敗</string>
|
||||
<string name="error_failed_to_instantiate_with_cause"><![CDATA[創建實例 \"%1$s\" 失敗: [ %2$s ]]]></string>
|
||||
<string name="error_failed_to_instantiate">實例 \"%s\" 創建失敗</string>
|
||||
<string name="error_failed_to_instantiate_with_cause"><![CDATA[實例 \"%1$s\" 創建失敗: [ %2$s ]]]></string>
|
||||
<string name="error_failed_to_invoke_method_with_description">方法 %1$s 調用失敗</string>
|
||||
<string name="error_failed_to_render_content">內容渲染失敗</string>
|
||||
<string name="error_failed_to_retrieve_released_notes">獲取版本信息失敗</string>
|
||||
@@ -1044,5 +1044,6 @@
|
||||
<string name="error_no_applications_available_for_viewing_this_file">未找到用於查看該文件的應用</string>
|
||||
<string name="error_no_applications_available_for_sending_this_file">未找到用於發送該文件的應用</string>
|
||||
<string name="error_no_applications_available_for_playing_this_file">未找到用於播放該文件的應用</string>
|
||||
<string name="error_webp_lossless_quality_not_supported">WebP-Lossless 格式無法使用 quality 質量參數進行壓縮, 可改用 JPEG/PNG/WebP-Lossy</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -177,12 +177,12 @@
|
||||
<string name="error_excessive_height_for_template_n_region">高度超限: 模板影象 [%1$d] > 限定區域 [%2$d]</string>
|
||||
<string name="error_excessive_width_for_template_n_region">寬度超限: 模板影象 [%1$d] > 限定區域 [%2$d]</string>
|
||||
<string name="error_failed_to_apply_current_color_history">應用當前歷史顏色失敗</string>
|
||||
<string name="error_failed_to_call_method">呼叫方法 \"%s\" 失敗</string>
|
||||
<string name="error_failed_to_call_method_with_cause"><![CDATA[呼叫方法 \"%1$s\" 失敗: [ %2$s ]]]></string>
|
||||
<string name="error_failed_to_call_method">方法 \"%s\" 呼叫失敗</string>
|
||||
<string name="error_failed_to_call_method_with_cause"><![CDATA[方法 \"%1$s\" 呼叫失敗: [ %2$s ]]]></string>
|
||||
<string name="error_failed_to_convert_into_drawable">無法將值 %s 轉換為 Drawable 例項</string>
|
||||
<string name="error_failed_to_grant_shizuku_access">Shizuku 許可權授予失敗</string>
|
||||
<string name="error_failed_to_instantiate">建立例項 \"%s\" 失敗</string>
|
||||
<string name="error_failed_to_instantiate_with_cause"><![CDATA[建立例項 \"%1$s\" 失敗: [ %2$s ]]]></string>
|
||||
<string name="error_failed_to_instantiate">例項 \"%s\" 建立失敗</string>
|
||||
<string name="error_failed_to_instantiate_with_cause"><![CDATA[例項 \"%1$s\" 建立失敗: [ %2$s ]]]></string>
|
||||
<string name="error_failed_to_invoke_method_with_description">方法 %1$s 呼叫失敗</string>
|
||||
<string name="error_failed_to_render_content">內容渲染失敗</string>
|
||||
<string name="error_failed_to_retrieve_released_notes">獲取版本資訊失敗</string>
|
||||
@@ -1044,5 +1044,6 @@
|
||||
<string name="error_no_applications_available_for_viewing_this_file">未找到用於檢視該檔案的應用</string>
|
||||
<string name="error_no_applications_available_for_sending_this_file">未找到用於傳送該檔案的應用</string>
|
||||
<string name="error_no_applications_available_for_playing_this_file">未找到用於播放該檔案的應用</string>
|
||||
<string name="error_webp_lossless_quality_not_supported">WebP-Lossless 格式無法使用 quality 質量引數進行壓縮, 可改用 JPEG/PNG/WebP-Lossy</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -177,12 +177,12 @@
|
||||
<string name="error_excessive_height_for_template_n_region">高度超限: 模板图像 [%1$d] > 限定区域 [%2$d]</string>
|
||||
<string name="error_excessive_width_for_template_n_region">宽度超限: 模板图像 [%1$d] > 限定区域 [%2$d]</string>
|
||||
<string name="error_failed_to_apply_current_color_history">应用当前历史颜色失败</string>
|
||||
<string name="error_failed_to_call_method">调用方法 \"%s\" 失败</string>
|
||||
<string name="error_failed_to_call_method_with_cause"><![CDATA[调用方法 \"%1$s\" 失败: [ %2$s ]]]></string>
|
||||
<string name="error_failed_to_call_method">方法 \"%s\" 调用失败</string>
|
||||
<string name="error_failed_to_call_method_with_cause"><![CDATA[方法 \"%1$s\" 调用失败: [ %2$s ]]]></string>
|
||||
<string name="error_failed_to_convert_into_drawable">无法将值 %s 转换为 Drawable 实例</string>
|
||||
<string name="error_failed_to_grant_shizuku_access">Shizuku 权限授予失败</string>
|
||||
<string name="error_failed_to_instantiate">创建实例 \"%s\" 失败</string>
|
||||
<string name="error_failed_to_instantiate_with_cause"><![CDATA[创建实例 \"%1$s\" 失败: [ %2$s ]]]></string>
|
||||
<string name="error_failed_to_instantiate">实例 \"%s\" 创建失败</string>
|
||||
<string name="error_failed_to_instantiate_with_cause"><![CDATA[实例 \"%1$s\" 创建失败: [ %2$s ]]]></string>
|
||||
<string name="error_failed_to_invoke_method_with_description">方法 %1$s 调用失败</string>
|
||||
<string name="error_failed_to_render_content">内容渲染失败</string>
|
||||
<string name="error_failed_to_retrieve_released_notes">获取版本信息失败</string>
|
||||
@@ -1044,5 +1044,6 @@
|
||||
<string name="error_no_applications_available_for_viewing_this_file">未找到用于查看该文件的应用</string>
|
||||
<string name="error_no_applications_available_for_sending_this_file">未找到用于发送该文件的应用</string>
|
||||
<string name="error_no_applications_available_for_playing_this_file">未找到用于播放该文件的应用</string>
|
||||
<string name="error_webp_lossless_quality_not_supported">WebP-Lossless 格式无法使用 quality 质量参数进行压缩, 可改用 JPEG/PNG/WebP-Lossy</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -1274,5 +1274,6 @@
|
||||
<string name="error_no_applications_available_for_viewing_this_file">No applications available for viewing this file</string>
|
||||
<string name="error_no_applications_available_for_sending_this_file">No applications available for sending this file</string>
|
||||
<string name="error_no_applications_available_for_playing_this_file">No applications available for playing this file</string>
|
||||
<string name="error_webp_lossless_quality_not_supported">Format WebP-Lossless cannot be compressed with a quality parameter, use JPEG/PNG/WebP-Lossy instead</string>
|
||||
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user