Elysia Tools

在一个清晰的工作台里浏览工具、案例、可视化和主题指南。

热门分类

专题

语言
ZHESPTRUFRDEEN

Elysia Tools

导航

Kotlin

Android Kotlin 图像处理示例

Android Kotlin 图像处理示例,包括图像读取保存、缩放和格式转换

案例

这个案例集合中的条目

代码kotlin中等

图像读取和保存

从各种来源读取图像并将其保存到存储

难度

6/10

预计时间

25 min

标签

kotlin, android, image processing

前置条件

Intermediate Kotlin, Android SDK

kotlin
// Android Kotlin Image Read and Save Examples
// Using android.graphics.Bitmap and related classes

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream

// 1. Reading Images
class ImageReader(private val context: Context) {

    // Read bitmap from resources
    fun readFromResource(resourceId: Int): Bitmap? {
        return try {
            val options = BitmapFactory.Options()
            BitmapFactory.decodeResource(context.resources, resourceId, options)
        } catch (e: Exception) {
            println("Error reading from resource: ${e.message}")
            null
        }
    }

    // Read bitmap from file path
    fun readFromFile(filePath: String): Bitmap? {
        return try {
            val file = File(filePath)
            if (file.exists()) {
                BitmapFactory.decodeFile(filePath)
            } else {
                println("File not found: $filePath")
                null
            }
        } catch (e: Exception) {
            println("Error reading from file: ${e.message}")
            null
        }
    }

    // Read bitmap from URI
    fun readFromUri(uri: Uri): Bitmap? {
        return try {
            val inputStream: InputStream = context.contentResolver.openInputStream(uri) ?: return null
            inputStream.use {
                BitmapFactory.decodeStream(it)
            }
        } catch (e: Exception) {
            println("Error reading from URI: ${e.message}")
            null
        }
    }

    // Read with sampling (for memory efficiency)
    fun readWithSampled(filePath: String, reqWidth: Int, reqHeight: Int): Bitmap? {
        return try {
            // First decode with inJustDecodeBounds=true to check dimensions
            val options = BitmapFactory.Options()
            options.inJustDecodeBounds = true
            BitmapFactory.decodeFile(filePath, options)

            // Calculate inSampleSize
            options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)

            // Decode bitmap with inSampleSize set
            options.inJustDecodeBounds = false
            BitmapFactory.decodeFile(filePath, options)
        } catch (e: Exception) {
            println("Error reading with sampling: ${e.message}")
            null
        }
    }

    // Read from assets
    fun readFromAssets(assetPath: String): Bitmap? {
        return try {
            val inputStream = context.assets.open(assetPath)
            inputStream.use {
                BitmapFactory.decodeStream(it)
            }
        } catch (e: Exception) {
            println("Error reading from assets: ${e.message}")
            null
        }
    }

    // Calculate inSampleSize for efficient loading
    private fun calculateInSampleSize(
                    options: BitmapFactory.Options,
                    reqWidth: Int,
                    reqHeight: Int
    ): Int {
        val height = options.outHeight
        val width = options.outWidth
        var inSampleSize = 1

        if (height > reqHeight || width > reqWidth) {
            val halfHeight = height / 2
            val halfWidth = width / 2

            while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
                inSampleSize *= 2
            }
        }

        return inSampleSize
    }

    // Read with specific config
    fun readWithConfig(filePath: String, config: Bitmap.Config): Bitmap? {
        return try {
            val options = BitmapFactory.Options()
            options.inPreferredConfig = config
            BitmapFactory.decodeFile(filePath, options)
        } catch (e: Exception) {
            println("Error reading with config: ${e.message}")
            null
        }
    }
}

// 2. Saving Images
class ImageSaver(private val context: Context) {

    // Save bitmap to file
    fun saveToFile(bitmap: Bitmap, filePath: String, format: Bitmap.CompressFormat, quality: Int): Boolean {
        return try {
            val file = File(filePath)
            file.parentFile?.mkdirs()

            val outputStream = FileOutputStream(file)
            bitmap.compress(format, quality, outputStream)
            outputStream.flush()
            outputStream.close()

            println("Saved to: $filePath")
            true
        } catch (e: Exception) {
            println("Error saving to file: ${e.message}")
            false
        }
    }

    // Save to internal storage
    fun saveToInternalStorage(bitmap: Bitmap, filename: String, format: Bitmap.CompressFormat): String? {
        return try {
            val file = File(context.filesDir, filename)
            val outputStream = FileOutputStream(file)

            bitmap.compress(format, 100, outputStream)
            outputStream.flush()
            outputStream.close()

            file.absolutePath
        } catch (e: Exception) {
            println("Error saving to internal storage: ${e.message}")
            null
        }
    }

    // Save to cache directory
    fun saveToCache(bitmap: Bitmap, filename: String, format: Bitmap.CompressFormat): String? {
        return try {
            val file = File(context.cacheDir, filename)
            val outputStream = FileOutputStream(file)

            bitmap.compress(format, 100, outputStream)
            outputStream.flush()
            outputStream.close()

            file.absolutePath
        } catch (e: Exception) {
            println("Error saving to cache: ${e.message}")
            null
        }
    }

    // Save to external storage
    fun saveToExternalStorage(bitmap: Bitmap, filename: String, format: Bitmap.CompressFormat): String? {
        return try {
            // Note: Requires WRITE_EXTERNAL_STORAGE permission
            val directory = context.getExternalFilesDir(null)
            val file = File(directory, filename)

            val outputStream = FileOutputStream(file)
            bitmap.compress(format, 100, outputStream)
            outputStream.flush()
            outputStream.close()

            file.absolutePath
        } catch (e: Exception) {
            println("Error saving to external storage: ${e.message}")
            null
        }
    }

    // Save with quality setting
    fun saveWithQuality(bitmap: Bitmap, filePath: String, quality: Int): Boolean {
        val format = when (filePath.substringAfterLast('.', "").lowercase()) {
            "png" -> Bitmap.CompressFormat.PNG
            "webp" -> Bitmap.CompressFormat.WEBP
            else -> Bitmap.CompressFormat.JPEG
        }

        return saveToFile(bitmap, filePath, format, quality)
    }
}

// 3. Image Information
class ImageInfo {

    // Get image dimensions
    fun getImageDimensions(filePath: String): Pair<Int, Int>? {
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true

        try {
            BitmapFactory.decodeFile(filePath, options)
            return Pair(options.outWidth, options.outHeight)
        } catch (e: Exception) {
            println("Error getting dimensions: ${e.message}")
            return null
        }
    }

    // Get image file size
    fun getImageFileSize(filePath: String): Long {
        val file = File(filePath)
        return if (file.exists()) {
            file.length()
        } else {
            0L
        }
    }

    // Get image type from file
    fun getImageType(filePath: String): String? {
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true

        return try {
            BitmapFactory.decodeFile(filePath, options)
            when (options.outMimeType) {
                "image/png" -> "PNG"
                "image/jpeg" -> "JPEG"
                "image/webp" -> "WebP"
                "image/gif" -> "GIF"
                else -> "Unknown"
            }
        } catch (e: Exception) {
            println("Error getting image type: ${e.message}")
            null
        }
    }

    // Get detailed image info
    fun getDetailedInfo(filePath: String): ImageMetadata? {
        val file = File(filePath)
        if (!file.exists()) return null

        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true

        return try {
            BitmapFactory.decodeFile(filePath, options)

            ImageMetadata(
                width = options.outWidth,
                height = options.outHeight,
                mimeType = options.outMimeType,
                fileSize = file.length(),
                path = file.absolutePath
            )
        } catch (e: Exception) {
            println("Error getting detailed info: ${e.message}")
            null
        }
    }
}

// Image Metadata data class
data class ImageMetadata(
    val width: Int,
    val height: Int,
    val mimeType: String?,
    val fileSize: Long,
    val path: String
)

// 4. Advanced Image Loading
class AdvancedImageLoader(private val context: Context) {

    // Load with exact dimensions
    fun loadWithExactDimensions(filePath: String, targetWidth: Int, targetHeight: Int): Bitmap? {
        return try {
            // First get dimensions
            val options = BitmapFactory.Options()
            options.inJustDecodeBounds = true
            BitmapFactory.decodeFile(filePath, options)

            // Calculate scale
            val scaleWidth = options.outWidth.toFloat() / targetWidth
            val scaleHeight = options.outHeight.toFloat() / targetHeight
            val scale = maxOf(scaleWidth, scaleHeight)

            if (scale > 1) {
                options.inSampleSize = scale.toInt()
            }

            options.inJustDecodeBounds = false

            // Decode and scale
            val bitmap = BitmapFactory.decodeFile(filePath, options)

            Bitmap.createScaledBitmap(bitmap, targetWidth, targetHeight, true)
        } catch (e: Exception) {
            println("Error loading with dimensions: ${e.message}")
            null
        }
    }

    // Load with memory constraints
    fun loadWithMemoryLimit(filePath: String, maxMemoryBytes: Long): Bitmap? {
        return try {
            val options = BitmapFactory.Options()

            // Get original dimensions
            options.inJustDecodeBounds = true
            BitmapFactory.decodeFile(filePath, options)

            // Calculate sample size based on memory limit
            val bytesPerPixel = 4 // ARGB_8888
            val totalPixels = options.outWidth * options.outHeight
            val estimatedMemory = totalPixels * bytesPerPixel

            var inSampleSize = 1
            if (estimatedMemory > maxMemoryBytes) {
                inSampleSize = (estimatedMemory / maxMemoryBytes).toInt()
            }

            options.inJustDecodeBounds = false
            options.inSampleSize = inSampleSize
            options.inPreferredConfig = Bitmap.Config.RGB_565 // Use less memory

            BitmapFactory.decodeFile(filePath, options)
        } catch (e: Exception) {
            println("Error loading with memory limit: ${e.message}")
            null
        }
    }
}

// 5. Image Validation
class ImageValidator {

    // Validate if file is a valid image
    fun isValidImage(filePath: String): Boolean {
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true

        return try {
            BitmapFactory.decodeFile(filePath, options)
            options.outWidth != -1 && options.outHeight != -1
        } catch (e: Exception) {
            false
        }
    }

    // Check if image is corrupt
    fun isCorrupt(filePath: String): Boolean {
        return try {
            val bitmap = BitmapFactory.decodeFile(filePath)
            bitmap == null
        } catch (e: Exception) {
            true
        }
    }

    // Validate image dimensions
    fun hasValidDimensions(filePath: String, minWidth: Int, minHeight: Int): Boolean {
        val info = ImageInfo()
        val dimensions = info.getImageDimensions(filePath)

        return dimensions != null &&
               dimensions.first >= minWidth &&
               dimensions.second >= minHeight
    }
}

// 6. Batch Image Operations
class BatchImageOperations(private val context: Context) {

    // Read multiple images
    fun readMultipleImages(filePaths: List<String>): List<Bitmap> {
        val reader = ImageReader(context)
        val bitmaps = mutableListOf<Bitmap>()

        for (path in filePaths) {
            reader.readFromFile(path)?.let { bitmaps.add(it) }
        }

        return bitmaps
    }

    // Save multiple images
    fun saveMultipleImages(bitmaps: List<Bitmap>, directory: String, prefix: String): Boolean {
        val saver = ImageSaver(context)
        var success = true

        bitmaps.forEachIndexed { index, bitmap ->
            val filename = "${prefix}_$index.jpg"
            val filePath = "$directory/$filename"

            if (!saver.saveToFile(bitmap, filePath, Bitmap.CompressFormat.JPEG, 90)) {
                success = false
            }
        }

        return success
    }
}

// Main demonstration
fun demonstrateImageReadSave(context: Context) {
    println("=== Android Kotlin Image Read and Save Examples ===\n")

    val imageReader = ImageReader(context)
    val imageSaver = ImageSaver(context)
    val imageInfo = ImageInfo()

    // 1. Reading images
    println("--- 1. Reading Images ---")

    // Note: These would be actual file paths in real usage
    val sampleImagePath = "/sdcard/sample_image.jpg"

    println("Reading from file: $sampleImagePath")
    val bitmapFromFile = imageReader.readFromFile(sampleImagePath)
    println("Bitmap loaded: ${bitmapFromFile != null}")

    println("\nReading with sampling (200x200):")
    val sampledBitmap = imageReader.readWithSampled(sampleImagePath, 200, 200)
    println("Sampled bitmap loaded: ${sampledBitmap != null}")

    // 2. Getting image info
    println("\n--- 2. Getting Image Info ---")

    val dimensions = imageInfo.getImageDimensions(sampleImagePath)
    println("Dimensions: ${dimensions?.first} x ${dimensions?.second}")

    val fileSize = imageInfo.getImageFileSize(sampleImagePath)
    println("File size: $fileSize bytes")

    val imageType = imageInfo.getImageType(sampleImagePath)
    println("Image type: $imageType")

    val detailedInfo = imageInfo.getDetailedInfo(sampleImagePath)
    println("\nDetailed info:")
    println("  Path: ${detailedInfo?.path}")
    println("  Size: ${detailedInfo?.width}x${detailedInfo?.height}")
    println("  MIME type: ${detailedInfo?.mimeType}")

    // 3. Saving images
    println("\n--- 3. Saving Images ---")

    bitmapFromFile?.let { bitmap ->
        val outputPath = "${context.cacheDir}/saved_image.jpg"
        val saved = imageSaver.saveToFile(bitmap, outputPath, Bitmap.CompressFormat.JPEG, 90)
        println("Saved to cache: $saved")

        val internalPath = imageSaver.saveToInternalStorage(bitmap, "internal_image.jpg", Bitmap.CompressFormat.JPEG)
        println("Saved to internal: $internalPath")

        val cachePath = imageSaver.saveToCache(bitmap, "cache_image.jpg", Bitmap.CompressFormat.JPEG)
        println("Saved to cache dir: $cachePath")
    }

    // 4. Advanced loading
    println("\n--- 4. Advanced Loading ---")

    val advancedLoader = AdvancedImageLoader(context)
    println("Load with exact dimensions (300x300)")
    val exactBitmap = advancedLoader.loadWithExactDimensions(sampleImagePath, 300, 300)
    println("Loaded: ${exactBitmap != null}")

    println("\nLoad with memory limit (1MB)")
    val limitedBitmap = advancedLoader.loadWithMemoryLimit(sampleImagePath, 1024 * 1024)
    println("Loaded: ${limitedBitmap != null}")

    // 5. Validation
    println("\n--- 5. Validation ---")

    val validator = ImageValidator()
    println("Is valid image: ${validator.isValidImage(sampleImagePath)}")
    println("Is corrupt: ${validator.isCorrupt(sampleImagePath)}")
    println("Has valid dimensions (>100x100): ${validator.hasValidDimensions(sampleImagePath, 100, 100)}")

    println("\n=== All Image Read and Save Examples Completed ===")
}
代码kotlin中等

图像缩放

使用各种算法和质量设置调整图像大小和缩放

难度

7/10

预计时间

30 min

标签

kotlin, android, image processing, scaling

前置条件

Intermediate Kotlin, Android Graphics

kotlin
// Android Kotlin Image Scaling Examples
// Using android.graphics.Bitmap and Matrix

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Matrix
import android.graphics.Paint
import android.content.Context
import java.io.File

// 1. Basic Scaling
class BasicImageScaler {

    // Scale to specific dimensions
    fun scaleToSize(bitmap: Bitmap, newWidth: Int, newHeight: Int): Bitmap {
        return Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true)
    }

    // Scale by factor
    fun scaleByFactor(bitmap: Bitmap, factor: Float): Bitmap {
        val newWidth = (bitmap.width * factor).toInt()
        val newHeight = (bitmap.height * factor).toInt()

        return Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true)
    }

    // Scale maintaining aspect ratio
    fun scaleMaintainingAspectRatio(
                    bitmap: Bitmap,
                    maxWidth: Int,
                    maxHeight: Int
    ): Bitmap {
        val widthRatio = maxWidth.toFloat() / bitmap.width
        val heightRatio = maxHeight.toFloat() / bitmap.height
        val scaleFactor = minOf(widthRatio, heightRatio)

        val newWidth = (bitmap.width * scaleFactor).toInt()
        val newHeight = (bitmap.height * scaleFactor).toInt()

        return Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true)
    }

    // Scale to fit width
    fun scaleToWidth(bitmap: Bitmap, targetWidth: Int): Bitmap {
        val scale = targetWidth.toFloat() / bitmap.width
        val newHeight = (bitmap.height * scale).toInt()

        return Bitmap.createScaledBitmap(bitmap, targetWidth, newHeight, true)
    }

    // Scale to fit height
    fun scaleToHeight(bitmap: Bitmap, targetHeight: Int): Bitmap {
        val scale = targetHeight.toFloat() / bitmap.height
        val newWidth = (bitmap.width * scale).toInt()

        return Bitmap.createScaledBitmap(bitmap, newWidth, targetHeight, true)
    }
}

// 2. Advanced Scaling with Matrix
class MatrixScaler {

    private val paint = Paint().apply {
        isFilterBitmap = true
    }

    // Scale using Matrix
    fun scaleWithMatrix(bitmap: Bitmap, scaleX: Float, scaleY: Float): Bitmap {
        val matrix = Matrix()
        matrix.postScale(scaleX, scaleY)

        val scaledBitmap = Bitmap.createBitmap(
            (bitmap.width * scaleX).toInt(),
            (bitmap.height * scaleY).toInt(),
            Bitmap.Config.ARGB_8888
        )

        val canvas = Canvas(scaledBitmap)
        canvas.drawBitmap(bitmap, matrix, paint)

        return scaledBitmap
    }

    // Scale with rotation
    fun scaleAndRotate(
                    bitmap: Bitmap,
                    scaleX: Float,
                    scaleY: Float,
                    rotation: Float
    ): Bitmap {
        val matrix = Matrix()
        matrix.postRotate(rotation)
        matrix.postScale(scaleX, scaleY)

        val scaledBitmap = Bitmap.createBitmap(
            bitmap.width,
            bitmap.height,
            Bitmap.Config.ARGB_8888
        )

        val canvas = Canvas(scaledBitmap)
        canvas.drawBitmap(bitmap, matrix, paint)

        return scaledBitmap
    }

    // Scale with pivot point
    fun scaleFromPoint(
                    bitmap: Bitmap,
                    scaleX: Float,
                    scaleY: Float,
                    pivotX: Float,
                    pivotY: Float
    ): Bitmap {
        val matrix = Matrix()
        matrix.setScale(scaleX, scaleY, pivotX, pivotY)

        val scaledBitmap = Bitmap.createBitmap(
            bitmap.width,
            bitmap.height,
            Bitmap.Config.ARGB_8888
        )

        val canvas = Canvas(scaledBitmap)
        canvas.drawBitmap(bitmap, matrix, paint)

        return scaledBitmap
    }
}

// 3. High Quality Scaling
class QualityScaler {

    // Scale with high quality
    fun scaleHighQuality(bitmap: Bitmap, newWidth: Int, newHeight: Int): Bitmap {
        val paint = Paint().apply {
            isFilterBitmap = true
            isAntiAlias = true
            isDither = true
        }

        val scaledBitmap = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(scaledBitmap)

        val rect = android.graphics.Rect(0, 0, bitmap.width, bitmap.height)
        val destRect = android.graphics.Rect(0, 0, newWidth, newHeight)

        canvas.drawBitmap(bitmap, rect, destRect, paint)

        return scaledBitmap
    }

    // Scale with filtering options
    fun scaleWithFiltering(
                    bitmap: Bitmap,
                    newWidth: Int,
                    newHeight: Int,
                    filterBitmap: Boolean
    ): Bitmap {
        val paint = Paint().apply {
            isFilterBitmap = filterBitmap
        }

        return Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, filterBitmap)
    }

    // Smooth scale (multiple passes)
    fun smoothScale(bitmap: Bitmap, targetWidth: Int, targetHeight: Int): Bitmap {
        var currentBitmap = bitmap
        var currentWidth = bitmap.width
        var currentHeight = bitmap.height

        // Scale in multiple steps for better quality
        while (currentWidth > targetWidth * 1.5 || currentHeight > targetHeight * 1.5) {
            val scaleFactor = 0.75f
            currentWidth = (currentWidth * scaleFactor).toInt()
            currentHeight = (currentHeight * scaleFactor).toInt()

            currentBitmap = Bitmap.createScaledBitmap(
                currentBitmap,
                currentWidth,
                currentHeight,
                true
            )
        }

        // Final scale to exact size
        return Bitmap.createScaledBitmap(
            currentBitmap,
            targetWidth,
            targetHeight,
            true
        )
    }
}

// 4. Thumbnail Generation
class ThumbnailGenerator {

    // Generate thumbnail
    fun generateThumbnail(
                    bitmap: Bitmap,
                    thumbWidth: Int,
                    thumbHeight: Int
    ): Bitmap {
        val scaler = BasicImageScaler()
        return scaler.scaleMaintainingAspectRatio(bitmap, thumbWidth, thumbHeight)
    }

    // Generate square thumbnail (crop center)
    fun generateSquareThumbnail(bitmap: Bitmap, size: Int): Bitmap {
        val minDimension = minOf(bitmap.width, bitmap.height)

        // Calculate crop bounds
        val x = (bitmap.width - minDimension) / 2
        val y = (bitmap.height - minDimension) / 2

        // Crop to square
        val cropped = Bitmap.createBitmap(
            bitmap,
            x, y,
            minDimension, minDimension
        )

        // Scale to target size
        return Bitmap.createScaledBitmap(cropped, size, size, true)
    }

    // Generate thumbnail with rounded corners
    fun generateRoundedThumbnail(
                    bitmap: Bitmap,
                    width: Int,
                    height: Int,
                    cornerRadius: Float
    ): Bitmap {
        // First scale the image
        val scaler = BasicImageScaler()
        val scaled = scaler.scaleMaintainingAspectRatio(bitmap, width, height)

        // Create rounded bitmap
        val output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(output)
        val paint = Paint().apply {
            isAntiAlias = true
            color = android.graphics.Color.BLACK
        }

        // Draw rounded rectangle
        val rect = android.graphics.RectF(0f, 0f, width.toFloat(), height.toFloat())
        canvas.drawRoundRect(rect, cornerRadius, cornerRadius, paint)

        // Set mask for image
        paint.xfermode = android.graphics.PorterDuffXfermode(android.graphics.PorterDuff.Mode.SRC_IN)
        canvas.drawBitmap(scaled, 0f, 0f, paint)

        return output
    }

    // Generate circular thumbnail
    fun generateCircularThumbnail(bitmap: Bitmap, diameter: Int): Bitmap {
        // Create square thumbnail first
        val square = generateSquareThumbnail(bitmap, diameter)

        // Create circular bitmap
        val output = Bitmap.createBitmap(diameter, diameter, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(output)
        val paint = Paint().apply {
            isAntiAlias = true
            color = android.graphics.Color.BLACK
        }

        // Draw circle
        val radius = diameter / 2f
        canvas.drawCircle(radius, radius, radius, paint)

        // Set mask for image
        paint.xfermode = android.graphics.PorterDuffXfermode(android.graphics.PorterDuff.Mode.SRC_IN)
        canvas.drawBitmap(square, 0f, 0f, paint)

        return output
    }
}

// 5. Batch Scaling
class BatchScaler(private val context: Context) {

    // Scale multiple images
    fun scaleMultiple(
                    filePaths: List<String>,
                    targetWidth: Int,
                    targetHeight: Int
    ): List<Bitmap> {
        val scaledBitmaps = mutableListOf<Bitmap>()

        for (path in filePaths) {
            try {
                val bitmap = BitmapFactory.decodeFile(path)
                val scaler = BasicImageScaler()
                val scaled = scaler.scaleMaintainingAspectRatio(bitmap, targetWidth, targetHeight)
                scaledBitmaps.add(scaled)
            } catch (e: Exception) {
                println("Error scaling $path: ${e.message}")
            }
        }

        return scaledBitmaps
    }

    // Generate thumbnails for multiple images
    fun generateThumbnails(
                    filePaths: List<String>,
                    thumbSize: Int
    ): List<Bitmap> {
        val thumbnails = mutableListOf<Bitmap>()
        val generator = ThumbnailGenerator()

        for (path in filePaths) {
            try {
                val bitmap = BitmapFactory.decodeFile(path)
                val thumb = generator.generateSquareThumbnail(bitmap, thumbSize)
                thumbnails.add(thumb)
            } catch (e: Exception) {
                println("Error generating thumbnail for $path: ${e.message}")
            }
        }

        return thumbnails
    }

    // Save scaled images
    fun saveScaledImages(
                    filePaths: List<String>,
                    outputDir: String,
                    targetWidth: Int,
                    targetHeight: Int
    ): Boolean {
        var success = true

        for ((index, path) in filePaths.withIndex()) {
            try {
                val bitmap = BitmapFactory.decodeFile(path)
                val scaler = BasicImageScaler()
                val scaled = scaler.scaleMaintainingAspectRatio(bitmap, targetWidth, targetHeight)

                val outputFile = File(outputDir, "scaled_$index.jpg")
                outputFile.outputStream().use { outputStream ->
                    scaled.compress(Bitmap.CompressFormat.JPEG, 90, outputStream)
                }
            } catch (e: Exception) {
                println("Error saving scaled image: ${e.message}")
                success = false
            }
        }

        return success
    }
}

// 6. Scaling Utilities
class ScalingUtils {

    // Calculate target size maintaining aspect ratio
    fun calculateTargetSize(
                    originalWidth: Int,
                    originalHeight: Int,
                    maxWidth: Int,
                    maxHeight: Int
    ): Pair<Int, Int> {
        val widthRatio = maxWidth.toFloat() / originalWidth
        val heightRatio = maxHeight.toFloat() / originalHeight
        val scaleFactor = minOf(widthRatio, heightRatio)

        val newWidth = (originalWidth * scaleFactor).toInt()
        val newHeight = (originalHeight * scaleFactor).toInt()

        return Pair(newWidth, newHeight)
    }

    // Calculate sample size for efficient loading
    fun calculateSampleSize(
                    originalWidth: Int,
                    originalHeight: Int,
                    requiredWidth: Int,
                    requiredHeight: Int
    ): Int {
        var inSampleSize = 1

        if (originalWidth > requiredWidth || originalHeight > requiredHeight) {
            val halfWidth = originalWidth / 2
            val halfHeight = originalHeight / 2

            while (halfWidth / inSampleSize >= requiredWidth &&
                   halfHeight / inSampleSize >= requiredHeight) {
                inSampleSize *= 2
            }
        }

        return inSampleSize
    }

    // Get optimal sample size from file
    fun getOptimalSampleSize(filePath: String, reqWidth: Int, reqHeight: Int): Int {
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true
        BitmapFactory.decodeFile(filePath, options)

        return calculateSampleSize(options.outWidth, options.outHeight, reqWidth, reqHeight)
    }
}

// Main demonstration
fun demonstrateImageScaling(context: Context) {
    println("=== Android Kotlin Image Scaling Examples ===\n")

    // Create sample bitmap (in real usage, load from file)
    val sampleBitmap = Bitmap.createBitmap(800, 600, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(sampleBitmap)
    canvas.drawColor(android.graphics.Color.BLUE)

    // 1. Basic scaling
    println("--- 1. Basic Scaling ---")
    val basicScaler = BasicImageScaler()

    val scaledToSize = basicScaler.scaleToSize(sampleBitmap, 400, 300)
    println("Scaled to 400x300: ${scaledToSize.width}x${scaledToSize.height}")

    val scaledByFactor = basicScaler.scaleByFactor(sampleBitmap, 0.5f)
    println("Scaled by 0.5x: ${scaledByFactor.width}x${scaledByFactor.height}")

    val aspectRatio = basicScaler.scaleMaintainingAspectRatio(sampleBitmap, 300, 300)
    println("Scaled maintaining aspect ratio (max 300x300): ${aspectRatio.width}x${aspectRatio.height}")

    // 2. Matrix scaling
    println("\n--- 2. Matrix Scaling ---")
    val matrixScaler = MatrixScaler()

    val matrixScaled = matrixScaler.scaleWithMatrix(sampleBitmap, 0.75f, 0.75f)
    println("Matrix scaled 0.75x: ${matrixScaled.width}x${matrixScaled.height}")

    // 3. High quality scaling
    println("\n--- 3. High Quality Scaling ---")
    val qualityScaler = QualityScaler()

    val highQuality = qualityScaler.scaleHighQuality(sampleBitmap, 200, 150)
    println("High quality 200x150: ${highQuality.width}x${highQuality.height}")

    val smoothScaled = qualityScaler.smoothScale(sampleBitmap, 150, 150)
    println("Smooth scaled to 150x150: ${smoothScaled.width}x${smoothScaled.height}")

    // 4. Thumbnails
    println("\n--- 4. Thumbnails ---")
    val thumbGenerator = ThumbnailGenerator()

    val thumbnail = thumbGenerator.generateThumbnail(sampleBitmap, 100, 100)
    println("Thumbnail (100x100): ${thumbnail.width}x${thumbnail.height}")

    val squareThumb = thumbGenerator.generateSquareThumbnail(sampleBitmap, 80)
    println("Square thumbnail (80x80): ${squareThumb.width}x${squareThumb.height}")

    val circularThumb = thumbGenerator.generateCircularThumbnail(sampleBitmap, 60)
    println("Circular thumbnail (60x60): ${circularThumb.width}x${circularThumb.height}")

    // 5. Utilities
    println("\n--- 5. Scaling Utilities ---")
    val utils = ScalingUtils()

    val targetSize = utils.calculateTargetSize(1920, 1080, 800, 600)
    println("Calculated target size for 1920x1080 (max 800x600): ${targetSize.first}x${targetSize.second}")

    val sampleSize = utils.calculateSampleSize(1920, 1080, 400, 300)
    println("Calculated sample size: $sampleSize")

    println("\n=== All Image Scaling Examples Completed ===")
}
代码kotlin中等

图像格式转换

在PNG、JPEG、WebP格式之间转换图像及质量设置

难度

6/10

预计时间

25 min

标签

kotlin, android, image processing, conversion

前置条件

Intermediate Kotlin, Android Graphics

kotlin
// Android Kotlin Image Format Conversion Examples
// Using android.graphics.Bitmap and compression options

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Color
import java.io.File
import java.io.FileOutputStream

// 1. Basic Format Conversion
class FormatConverter {

    // Convert bitmap to JPEG
    fun convertToJPEG(bitmap: Bitmap, filePath: String, quality: Int = 90): Boolean {
        return try {
            val file = File(filePath)
            file.parentFile?.mkdirs()

            val outputStream = FileOutputStream(file)
            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream)
            outputStream.flush()
            outputStream.close()

            println("Converted to JPEG: $filePath")
            true
        } catch (e: Exception) {
            println("Error converting to JPEG: ${e.message}")
            false
        }
    }

    // Convert bitmap to PNG
    fun convertToPNG(bitmap: Bitmap, filePath: String): Boolean {
        return try {
            val file = File(filePath)
            file.parentFile?.mkdirs()

            val outputStream = FileOutputStream(file)
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
            outputStream.flush()
            outputStream.close()

            println("Converted to PNG: $filePath")
            true
        } catch (e: Exception) {
            println("Error converting to PNG: ${e.message}")
            false
        }
    }

    // Convert bitmap to WebP
    fun convertToWebP(bitmap: Bitmap, filePath: String, quality: Int = 90): Boolean {
        return try {
            val file = File(filePath)
            file.parentFile?.mkdirs()

            val outputStream = FileOutputStream(file)
            bitmap.compress(Bitmap.CompressFormat.WEBP, quality, outputStream)
            outputStream.flush()
            outputStream.close()

            println("Converted to WebP: $filePath")
            true
        } catch (e: Exception) {
            println("Error converting to WebP: ${e.message}")
            false
        }
    }

    // Auto-detect format from file extension
    fun convertByExtension(bitmap: Bitmap, filePath: String, quality: Int = 90): Boolean {
        val format = when (filePath.substringAfterLast('.', "").lowercase()) {
            "png" -> Bitmap.CompressFormat.PNG
            "webp" -> Bitmap.CompressFormat.WEBP
            else -> Bitmap.CompressFormat.JPEG
        }

        return try {
            val file = File(filePath)
            file.parentFile?.mkdirs()

            val outputStream = FileOutputStream(file)
            bitmap.compress(format, quality, outputStream)
            outputStream.flush()
            outputStream.close()

            println("Converted to ${format.name}: $filePath")
            true
        } catch (e: Exception) {
            println("Error converting: ${e.message}")
            false
        }
    }
}

// 2. Quality-based Conversion
class QualityConverter {

    // Convert with quality levels
    fun convertWithQuality(
                    bitmap: Bitmap,
                    filePath: String,
                    quality: QualityLevel
    ): Boolean {
        val qualityValue = when (quality) {
            QualityLevel.LOW -> 50
            QualityLevel.MEDIUM -> 70
            QualityLevel.HIGH -> 85
            QualityLevel.MAXIMUM -> 100
        }

        val format = when (filePath.substringAfterLast('.', "").lowercase()) {
            "png" -> Bitmap.CompressFormat.PNG
            "webp" -> Bitmap.CompressFormat.WEBP
            else -> Bitmap.CompressFormat.JPEG
        }

        return try {
            val file = File(filePath)
            val outputStream = FileOutputStream(file)
            bitmap.compress(format, qualityValue, outputStream)
            outputStream.flush()
            outputStream.close()

            println("Converted with quality $quality ($qualityValue%): $filePath")
            true
        } catch (e: Exception) {
            println("Error with quality conversion: ${e.message}")
            false
        }
    }

    // Convert with custom quality
    fun convertWithCustomQuality(
                    bitmap: Bitmap,
                    filePath: String,
                    quality: Int
    ): Boolean {
        require(quality in 0..100) { "Quality must be between 0 and 100" }

        val format = Bitmap.CompressFormat.JPEG
        return try {
            val file = File(filePath)
            val outputStream = FileOutputStream(file)
            bitmap.compress(format, quality, outputStream)
            outputStream.flush()
            outputStream.close()

            println("Converted with custom quality ($quality%): $filePath")
            true
        } catch (e: Exception) {
            println("Error: ${e.message}")
            false
        }
    }

    // Compare quality levels
    fun compareQualities(bitmap: Bitmap, outputDir: String): Map<String, Long> {
        val results = mutableMapOf<String, Long>()

        val qualities = listOf(50, 70, 85, 95)

        for (quality in qualities) {
            val filePath = "$outputDir/quality_$quality.jpg"

            convertWithCustomQuality(bitmap, filePath, quality)

            val fileSize = File(filePath).length()
            results["quality_$quality"] = fileSize
        }

        return results
    }
}

// Quality level enum
enum class QualityLevel {
    LOW, MEDIUM, HIGH, MAXIMUM
}

// 3. Lossless vs Lossy Conversion
class ConversionTypeConverter {

    // Lossless conversion (PNG)
    fun convertLossless(bitmap: Bitmap, filePath: String): Boolean {
        return try {
            val file = File(filePath)
            val outputStream = FileOutputStream(file)

            // PNG is lossless
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
            outputStream.flush()
            outputStream.close()

            println("Lossless conversion (PNG): $filePath")
            true
        } catch (e: Exception) {
            println("Error in lossless conversion: ${e.message}")
            false
        }
    }

    // Lossy conversion (JPEG)
    fun convertLossy(bitmap: Bitmap, filePath: String, quality: Int = 85): Boolean {
        return try {
            val file = File(filePath)
            val outputStream = FileOutputStream(file)

            // JPEG is lossy
            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream)
            outputStream.flush()
            outputStream.close()

            println("Lossy conversion (JPEG, quality=$quality): $filePath")
            true
        } catch (e: Exception) {
            println("Error in lossy conversion: ${e.message}")
            false
        }
    }

    // WebP with lossless option
    fun convertWebPLossless(bitmap: Bitmap, filePath: String): Boolean {
        // Note: Android's WebP encoder doesn't support explicit lossless mode
        // Use quality 100 for near-lossless
        return try {
            val file = File(filePath)
            val outputStream = FileOutputStream(file)

            bitmap.compress(Bitmap.CompressFormat.WEBP, 100, outputStream)
            outputStream.flush()
            outputStream.close()

            println("WebP near-lossless: $filePath")
            true
        } catch (e: Exception) {
            println("Error: ${e.message}")
            false
        }
    }
}

// 4. Batch Format Conversion
class BatchConverter {

    // Convert multiple images to same format
    fun convertMultipleToFormat(
                    inputFiles: List<String>,
                    outputDir: String,
                    format: Bitmap.CompressFormat,
                    quality: Int = 90
    ): Boolean {
        var success = true

        for ((index, inputFile) in inputFiles.withIndex()) {
            try {
                val bitmap = BitmapFactory.decodeFile(inputFile)
                val extension = when (format) {
                    Bitmap.CompressFormat.PNG -> "png"
                    Bitmap.CompressFormat.WEBP -> "webp"
                    else -> "jpg"
                }

                val outputFile = File(outputDir, "converted_$index.$extension")
                val outputStream = FileOutputStream(outputFile)

                bitmap.compress(format, quality, outputStream)
                outputStream.flush()
                outputStream.close()

                println("Converted $inputFile to ${outputFile.name}")

            } catch (e: Exception) {
                println("Error converting $inputFile: ${e.message}")
                success = false
            }
        }

        return success
    }

    // Convert directory of images
    fun convertDirectory(
                    inputDir: String,
                    outputDir: String,
                    targetFormat: Bitmap.CompressFormat,
                    quality: Int = 90
    ): Int {
        val inputDirectory = File(inputDir)
        val outputDirectory = File(outputDir)

        if (!outputDirectory.exists()) {
            outputDirectory.mkdirs()
        }

        val imageFiles = inputDirectory.listFiles { file ->
            file.extension.lowercase() in listOf("jpg", "jpeg", "png", "webp")
        } ?: emptyArray()

        var convertedCount = 0

        for (file in imageFiles) {
            try {
                val bitmap = BitmapFactory.decodeFile(file.absolutePath)
                val extension = when (targetFormat) {
                    Bitmap.CompressFormat.PNG -> "png"
                    Bitmap.CompressFormat.WEBP -> "webp"
                    else -> "jpg"
                }

                val outputFile = File(outputDir, "${file.nameWithoutExtension}.$extension")
                val outputStream = FileOutputStream(outputFile)

                bitmap.compress(targetFormat, quality, outputStream)
                outputStream.flush()
                outputStream.close()

                convertedCount++

            } catch (e: Exception) {
                println("Error converting ${file.name}: ${e.message}")
            }
        }

        println("Converted $convertedCount/${imageFiles.size} images")
        return convertedCount
    }
}

// 5. Format Comparison
class FormatComparator {

    // Compare file sizes for different formats
    fun compareFormatSizes(
                    bitmap: Bitmap,
                    outputDir: String
    ): Map<String, Long> {
        val sizes = mutableMapOf<String, Long>()

        // JPEG with different qualities
        val jpeg85 = File(outputDir, "compare_85.jpg")
        bitmap.compress(Bitmap.CompressFormat.JPEG, 85, FileOutputStream(jpeg85))
        sizes["JPEG_85"] = jpeg85.length()

        val jpeg95 = File(outputDir, "compare_95.jpg")
        bitmap.compress(Bitmap.CompressFormat.JPEG, 95, FileOutputStream(jpeg95))
        sizes["JPEG_95"] = jpeg95.length()

        // PNG
        val png = File(outputDir, "compare.png")
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, FileOutputStream(png))
        sizes["PNG"] = png.length()

        // WebP
        val webp = File(outputDir, "compare.webp")
        bitmap.compress(Bitmap.CompressFormat.WEBP, 90, FileOutputStream(webp))
        sizes["WebP"] = webp.length()

        return sizes
    }

    // Get compression ratio
    fun getCompressionRatio(originalSize: Long, compressedSize: Long): Double {
        return ((originalSize - compressedSize).toDouble() / originalSize) * 100
    }

    // Compare quality visually (would need UI in real app)
    fun compareQuality(bitmap: Bitmap): List<FormatInfo> {
        val formats = listOf(
            FormatInfo("JPEG", 85, Bitmap.CompressFormat.JPEG),
            FormatInfo("JPEG", 95, Bitmap.CompressFormat.JPEG),
            FormatInfo("PNG", 100, Bitmap.CompressFormat.PNG),
            FormatInfo("WebP", 90, Bitmap.CompressFormat.WEBP)
        )

        return formats
    }
}

// Format info data class
data class FormatInfo(
    val format: String,
    val quality: Int,
    val compressFormat: Bitmap.CompressFormat
)

// 6. Special Conversions
class SpecialConverter {

    // Convert to grayscale and save
    fun convertToGrayscale(bitmap: Bitmap, filePath: String): Boolean {
        return try {
            val grayscaleBitmap = Bitmap.createBitmap(
                bitmap.width,
                bitmap.height,
                Bitmap.Config.ARGB_8888
            )

            val canvas = Canvas(grayscaleBitmap)
            val paint = android.graphics.Paint()
            val colorMatrix = android.graphics.ColorMatrix()
            colorMatrix.setSaturation(0f)

            paint.colorFilter = android.graphics.ColorMatrixColorFilter(colorMatrix)
            canvas.drawBitmap(bitmap, 0f, 0f, paint)

            val file = File(filePath)
            val outputStream = FileOutputStream(file)
            grayscaleBitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream)
            outputStream.flush()
            outputStream.close()

            println("Converted to grayscale: $filePath")
            true
        } catch (e: Exception) {
            println("Error: ${e.message}")
            false
        }
    }

    // Convert with color filter
    fun convertWithColorFilter(
                    bitmap: Bitmap,
                    filePath: String,
                    color: Int
    ): Boolean {
        return try {
            val filteredBitmap = Bitmap.createBitmap(
                bitmap.width,
                bitmap.height,
                Bitmap.Config.ARGB_8888
            )

            val canvas = Canvas(filteredBitmap)
            val paint = android.graphics.Paint()

            paint.colorFilter = android.graphics.PorterDuffColorFilter(
                color,
                android.graphics.PorterDuff.Mode.SRC_ATOP
            )

            canvas.drawBitmap(bitmap, 0f, 0f, paint)

            val file = File(filePath)
            val outputStream = FileOutputStream(file)
            filteredBitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream)
            outputStream.flush()
            outputStream.close()

            println("Converted with color filter: $filePath")
            true
        } catch (e: Exception) {
            println("Error: ${e.message}")
            false
        }
    }
}

// Main demonstration
fun demonstrateImageFormatConversion() {
    println("=== Android Kotlin Image Format Conversion Examples ===\n")

    // Create sample bitmap
    val sampleBitmap = Bitmap.createBitmap(400, 300, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(sampleBitmap)
    canvas.drawColor(Color.BLUE)

    // 1. Basic conversion
    println("--- 1. Basic Format Conversion ---")
    val converter = FormatConverter()

    // Note: In real usage, use actual file paths
    println("Converting to JPEG...")
    println("Converting to PNG...")
    println("Converting to WebP...")

    // 2. Quality conversion
    println("\n--- 2. Quality Conversion ---")
    val qualityConverter = QualityConverter()

    println("Converting with quality levels:")
    QualityLevel.values().forEach { level ->
        println("  - $level")
    }

    // 3. Lossless vs Lossy
    println("\n--- 3. Lossless vs Lossy ---")
    val typeConverter = ConversionTypeConverter()

    println("Lossless (PNG): preserves all image data, larger file size")
    println("Lossy (JPEG): smaller file size, some quality loss")
    println("WebP: modern format with good compression")

    // 4. Format comparison
    println("\n--- 4. Format Comparison ---")
    val comparator = FormatComparator()

    println("Comparing formats:")
    println("  - JPEG (85%): Good balance of quality and size")
    println("  - JPEG (95%): High quality, larger size")
    println("  - PNG: Lossless, largest size")
    println("  - WebP (90%): Best compression ratio")

    val originalSize = 1000000L // Example size
    val compressedSize = 150000L

    val ratio = comparator.getCompressionRatio(originalSize, compressedSize)
    println("\nCompression ratio: ${String.format("%.2f", ratio)}%")

    // 5. Batch conversion
    println("\n--- 5. Batch Conversion ---")
    val batchConverter = BatchConverter()

    println("Batch conversion methods:")
    println("  - convertMultipleToFormat(): Convert multiple images")
    println("  - convertDirectory(): Convert all images in directory")

    // 6. Special conversions
    println("\n--- 6. Special Conversions ---")
    val specialConverter = SpecialConverter()

    println("Special conversion methods:")
    println("  - convertToGrayscale(): Convert to black and white")
    println("  - convertWithColorFilter(): Apply color tint")

    println("\n=== All Image Format Conversion Examples Completed ===")
}

工具

经常与该案例搭配使用的工具

相关内容

相关案例集合

工具使用指南

帮助搜索与理解工作流的案例说明

标题

Android Kotlin 图像处理示例

描述

Android Kotlin 图像处理示例,包括图像读取保存、缩放和格式转换

概览

Android Kotlin 图像处理示例,包括图像读取保存、缩放和格式转换

适用场景

  • Use this sample set when you want reference inputs for Android Kotlin 图像处理示例.
  • Use it to preview output formats and compare related sample variants.

使用方式

  1. 1Open a sample entry to inspect the prepared example payload or asset.
  2. 2Compare it with related tools to understand how the workflow connects.

常见用途

  • 图像读取和保存
  • 图像缩放
  • 图像格式转换

常见问题

What is included in Android Kotlin 图像处理示例?

This page includes curated sample entries, related tools, and neighboring sample collections for Android Kotlin 图像处理示例.

首页
工具3197
案例593
可视化461
文件查看器103
专题229
标签333
图像、音频与视频655

图像、音频、视频处理、转换与优化工具

数学、日期与金融644

计算器、数值计算、日期逻辑、统计与金融工具

设计与颜色296

颜色、版式、图形、视觉样式与设计辅助工具

文本与写作209

写作、清洗、格式化、提取与文本分析工具

开发与 Web193

开发者工具、网络处理、Web 调试与自动化辅助工具

转换与编码175

格式、文件、压缩包、单位与编码转换工具

界面截图结构化、人工校对与开发交付
钢琴旋律草稿创作、MIDI 核验与试听样稿交付
复古游戏纹理制作、候选评审与素材交付
操作截图到可复核图文指南与培训交付
网页改版响应式视觉回归审核与证据交付

© 2026 Elysia Tools. 保留所有权利。

文档价格关于我们服务条款隐私政策Cookie 政策联系我们

Media

视频转图片序列

将视频帧提取为图片序列,支持自定义帧率、质量和输出格式

Media

批量图片转换

批量转换多张图片到不同格式,支持质量设置

Media

批量图片转换

批量转换多个图片文件格式,支持 JPG、PNG、WebP、AVIF、TIFF、GIF,支持质量设置和批量处理

Media

批量图片信息查看器

一次查看多张图片的基本信息 - 尺寸、格式、文件大小和元数据存在情况

Media

批量图片压缩

批量压缩多张图片,支持质量控制、输出格式选择和大小优化

Media

图像元数据提取器

从图像中提取全面的元数据,包括EXIF、IPTC、XMP和技术信息

Media

图片缩放工具

专业的图片缩放工具,支持多种缩放方式、长宽比保持和格式转换,包含模糊背景功能,支持 GIF/Animated WebP/APNG 和 JPEG/PNG/WEBP 格式。

Media

批量图片调整

批量调整多张图片到指定尺寸,支持多种调整选项

Java

Android Java 图像处理示例

Android Java 图像处理示例,包括图像读取保存、缩放和格式转换

Python

Web Python 图像处理示例

Web Python 图像处理示例,使用 PIL/Pillow 包括读取、保存、缩放和格式转换

C++

Windows C++ 图像处理示例

Windows C++ 图像处理示例,包括读取/保存图像、调整大小和使用Windows Imaging Component进行格式转换

Go

Web Go 图像处理示例

Web Go 图像处理示例,包括图像读写、图像缩放和格式转换

Objective-C

macOS Objective-C 图像处理示例

macOS Objective-C 图像处理示例,包括图像读取保存、图像缩放和格式转换

Rust

Web Rust 图像处理示例

Web Rust 图像处理示例,包括图像读取保存、缩放和格式转换