Android Java Bildverarbeitungsbeispiele

Android Java Bildverarbeitungsbeispiele einschließlich Lesen/Schreiben, Skalierung und Formatkonvertierung

💻 Bilder Lesen und Speichern java

🟡 intermediate ⭐⭐⭐

Bilder aus verschiedenen Quellen lesen und im Speicher speichern

⏱️ 25 min 🏷️ java, android, image processing
Prerequisites: Intermediate Java, Android SDK
// Android Java 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;
import java.io.IOException;

// 1. Reading Images
class ImageReader {
    private Context context;

    public ImageReader(Context context) {
        this.context = context;
    }

    // Read bitmap from resources
    public Bitmap readFromResource(int resourceId) {
        try {
            BitmapFactory.Options options = new BitmapFactory.Options();
            return BitmapFactory.decodeResource(context.getResources(), resourceId, options);
        } catch (Exception e) {
            System.out.println("Error reading from resource: " + e.getMessage());
            return null;
        }
    }

    // Read bitmap from file path
    public Bitmap readFromFile(String filePath) {
        try {
            File file = new File(filePath);
            if (file.exists()) {
                return BitmapFactory.decodeFile(filePath);
            } else {
                System.out.println("File not found: " + filePath);
                return null;
            }
        } catch (Exception e) {
            System.out.println("Error reading from file: " + e.getMessage());
            return null;
        }
    }

    // Read bitmap from URI
    public Bitmap readFromUri(Uri uri) {
        try {
            InputStream inputStream = context.getContentResolver().openInputStream(uri);
            if (inputStream == null) {
                return null;
            }
            return BitmapFactory.decodeStream(inputStream);
        } catch (Exception e) {
            System.out.println("Error reading from URI: " + e.getMessage());
            return null;
        }
    }

    // Read with sampling (for memory efficiency)
    public Bitmap readWithSampled(String filePath, int reqWidth, int reqHeight) {
        try {
            // First decode with inJustDecodeBounds=true to check dimensions
            BitmapFactory.Options options = new 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;
            return BitmapFactory.decodeFile(filePath, options);
        } catch (Exception e) {
            System.out.println("Error reading with sampling: " + e.getMessage());
            return null;
        }
    }

    // Read from assets
    public Bitmap readFromAssets(String assetPath) {
        try {
            InputStream inputStream = context.getAssets().open(assetPath);
            return BitmapFactory.decodeStream(inputStream);
        } catch (Exception e) {
            System.out.println("Error reading from assets: " + e.getMessage());
            return null;
        }
    }

    // Calculate inSampleSize for efficient loading
    private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

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

        return inSampleSize;
    }

    // Read with specific config
    public Bitmap readWithConfig(String filePath, Bitmap.Config config) {
        try {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inPreferredConfig = config;
            return BitmapFactory.decodeFile(filePath, options);
        } catch (Exception e) {
            System.out.println("Error reading with config: " + e.getMessage());
            return null;
        }
    }
}

// 2. Saving Images
class ImageSaver {
    private Context context;

    public ImageSaver(Context context) {
        this.context = context;
    }

    // Save bitmap to file
    public boolean saveToFile(Bitmap bitmap, String filePath, Bitmap.CompressFormat format, int quality) {
        try {
            File file = new File(filePath);
            File parentDir = file.getParentFile();
            if (parentDir != null && !parentDir.exists()) {
                parentDir.mkdirs();
            }

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

            System.out.println("Saved to: " + filePath);
            return true;
        } catch (Exception e) {
            System.out.println("Error saving to file: " + e.getMessage());
            return false;
        }
    }

    // Save to internal storage
    public String saveToInternalStorage(Bitmap bitmap, String filename, Bitmap.CompressFormat format) {
        try {
            File file = new File(context.getFilesDir(), filename);
            FileOutputStream outputStream = new FileOutputStream(file);

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

            return file.getAbsolutePath();
        } catch (Exception e) {
            System.out.println("Error saving to internal storage: " + e.getMessage());
            return null;
        }
    }

    // Save to cache directory
    public String saveToCache(Bitmap bitmap, String filename, Bitmap.CompressFormat format) {
        try {
            File file = new File(context.getCacheDir(), filename);
            FileOutputStream outputStream = new FileOutputStream(file);

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

            return file.getAbsolutePath();
        } catch (Exception e) {
            System.out.println("Error saving to cache: " + e.getMessage());
            return null;
        }
    }

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

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

            return file.getAbsolutePath();
        } catch (Exception e) {
            System.out.println("Error saving to external storage: " + e.getMessage());
            return null;
        }
    }

    // Save with quality setting
    public boolean saveWithQuality(Bitmap bitmap, String filePath, int quality) {
        String extension = getExtension(filePath);
        Bitmap.CompressFormat format;

        if ("png".equalsIgnoreCase(extension)) {
            format = Bitmap.CompressFormat.PNG;
        } else if ("webp".equalsIgnoreCase(extension)) {
            format = Bitmap.CompressFormat.WEBP;
        } else {
            format = Bitmap.CompressFormat.JPEG;
        }

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

    private String getExtension(String filePath) {
        int lastDot = filePath.lastIndexOf('.');
        return lastDot > 0 ? filePath.substring(lastDot + 1) : "";
    }
}

// 3. Image Information
class ImageInfo {

    // Dimension holder
    public static class Dimensions {
        public int width;
        public int height;

        public Dimensions(int width, int height) {
            this.width = width;
            this.height = height;
        }
    }

    // Get image dimensions
    public Dimensions getImageDimensions(String filePath) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;

        try {
            BitmapFactory.decodeFile(filePath, options);
            return new Dimensions(options.outWidth, options.outHeight);
        } catch (Exception e) {
            System.out.println("Error getting dimensions: " + e.getMessage());
            return null;
        }
    }

    // Get image file size
    public long getImageFileSize(String filePath) {
        File file = new File(filePath);
        if (file.exists()) {
            return file.length();
        } else {
            return 0L;
        }
    }

    // Get image type from file
    public String getImageType(String filePath) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;

        try {
            BitmapFactory.decodeFile(filePath, options);
            String mimeType = options.outMimeType;

            if (mimeType == null) {
                return null;
            }

            switch (mimeType) {
                case "image/png":
                    return "PNG";
                case "image/jpeg":
                    return "JPEG";
                case "image/webp":
                    return "WebP";
                case "image/gif":
                    return "GIF";
                default:
                    return "Unknown";
            }
        } catch (Exception e) {
            System.out.println("Error getting image type: " + e.getMessage());
            return null;
        }
    }

    // Image Metadata class
    public static class ImageMetadata {
        public int width;
        public int height;
        public String mimeType;
        public long fileSize;
        public String path;

        public ImageMetadata(int width, int height, String mimeType, long fileSize, String path) {
            this.width = width;
            this.height = height;
            this.mimeType = mimeType;
            this.fileSize = fileSize;
            this.path = path;
        }
    }

    // Get detailed image info
    public ImageMetadata getDetailedInfo(String filePath) {
        File file = new File(filePath);
        if (!file.exists()) {
            return null;
        }

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;

        try {
            BitmapFactory.decodeFile(filePath, options);

            return new ImageMetadata(
                options.outWidth,
                options.outHeight,
                options.outMimeType,
                file.length(),
                file.getAbsolutePath()
            );
        } catch (Exception e) {
            System.out.println("Error getting detailed info: " + e.getMessage());
            return null;
        }
    }
}

// 4. Advanced Image Loading
class AdvancedImageLoader {
    private Context context;

    public AdvancedImageLoader(Context context) {
        this.context = context;
    }

    // Load with exact dimensions
    public Bitmap loadWithExactDimensions(String filePath, int targetWidth, int targetHeight) {
        try {
            // First get dimensions
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(filePath, options);

            // Calculate scale
            float scaleWidth = (float) options.outWidth / targetWidth;
            float scaleHeight = (float) options.outHeight / targetHeight;
            float scale = Math.max(scaleWidth, scaleHeight);

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

            options.inJustDecodeBounds = false;

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

            return Bitmap.createScaledBitmap(bitmap, targetWidth, targetHeight, true);
        } catch (Exception e) {
            System.out.println("Error loading with dimensions: " + e.getMessage());
            return null;
        }
    }

    // Load with memory constraints
    public Bitmap loadWithMemoryLimit(String filePath, long maxMemoryBytes) {
        try {
            BitmapFactory.Options options = new BitmapFactory.Options();

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

            // Calculate sample size based on memory limit
            final int bytesPerPixel = 4; // ARGB_8888
            final long totalPixels = (long) options.outWidth * options.outHeight;
            final long estimatedMemory = totalPixels * bytesPerPixel;

            int inSampleSize = 1;
            if (estimatedMemory > maxMemoryBytes) {
                inSampleSize = (int) (estimatedMemory / maxMemoryBytes);
            }

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

            return BitmapFactory.decodeFile(filePath, options);
        } catch (Exception e) {
            System.out.println("Error loading with memory limit: " + e.getMessage());
            return null;
        }
    }
}

// 5. Image Validation
class ImageValidator {

    // Validate if file is a valid image
    public boolean isValidImage(String filePath) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;

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

    // Check if image is corrupt
    public boolean isCorrupt(String filePath) {
        try {
            Bitmap bitmap = BitmapFactory.decodeFile(filePath);
            return bitmap == null;
        } catch (Exception e) {
            return true;
        }
    }

    // Validate image dimensions
    public boolean hasValidDimensions(String filePath, int minWidth, int minHeight) {
        ImageInfo info = new ImageInfo();
        ImageInfo.Dimensions dimensions = info.getImageDimensions(filePath);

        return dimensions != null
                && dimensions.width >= minWidth
                && dimensions.height >= minHeight;
    }
}

// 6. Batch Image Operations
class BatchImageOperations {
    private Context context;

    public BatchImageOperations(Context context) {
        this.context = context;
    }

    // Read multiple images
    public java.util.List<Bitmap> readMultipleImages(java.util.List<String> filePaths) {
        ImageReader reader = new ImageReader(context);
        java.util.List<Bitmap> bitmaps = new java.util.ArrayList<>();

        for (String path : filePaths) {
            Bitmap bitmap = reader.readFromFile(path);
            if (bitmap != null) {
                bitmaps.add(bitmap);
            }
        }

        return bitmaps;
    }

    // Save multiple images
    public boolean saveMultipleImages(java.util.List<Bitmap> bitmaps, String directory, String prefix) {
        ImageSaver saver = new ImageSaver(context);
        boolean success = true;

        for (int i = 0; i < bitmaps.size(); i++) {
            String filename = prefix + "_" + i + ".jpg";
            String filePath = directory + File.separator + filename;

            if (!saver.saveToFile(bitmaps.get(i), filePath, Bitmap.CompressFormat.JPEG, 90)) {
                success = false;
            }
        }

        return success;
    }
}

// Main demonstration
public class ImageReadSaveDemo {
    public static void demonstrateImageReadSave(Context context) {
        System.out.println("=== Android Java Image Read and Save Examples ===\n");

        ImageReader imageReader = new ImageReader(context);
        ImageSaver imageSaver = new ImageSaver(context);
        ImageInfo imageInfo = new ImageInfo();

        // 1. Reading images
        System.out.println("--- 1. Reading Images ---");

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

        System.out.println("Reading from file: " + sampleImagePath);
        Bitmap bitmapFromFile = imageReader.readFromFile(sampleImagePath);
        System.out.println("Bitmap loaded: " + (bitmapFromFile != null));

        System.out.println("\nReading with sampling (200x200):");
        Bitmap sampledBitmap = imageReader.readWithSampled(sampleImagePath, 200, 200);
        System.out.println("Sampled bitmap loaded: " + (sampledBitmap != null));

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

        ImageInfo.Dimensions dimensions = imageInfo.getImageDimensions(sampleImagePath);
        if (dimensions != null) {
            System.out.println("Dimensions: " + dimensions.width + " x " + dimensions.height);
        }

        long fileSize = imageInfo.getImageFileSize(sampleImagePath);
        System.out.println("File size: " + fileSize + " bytes");

        String imageType = imageInfo.getImageType(sampleImagePath);
        System.out.println("Image type: " + imageType);

        ImageInfo.ImageMetadata detailedInfo = imageInfo.getDetailedInfo(sampleImagePath);
        if (detailedInfo != null) {
            System.out.println("\nDetailed info:");
            System.out.println("  Path: " + detailedInfo.path);
            System.out.println("  Size: " + detailedInfo.width + "x" + detailedInfo.height);
            System.out.println("  MIME type: " + detailedInfo.mimeType);
        }

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

        if (bitmapFromFile != null) {
            String outputPath = context.getCacheDir() + "/saved_image.jpg";
            boolean saved = imageSaver.saveToFile(bitmapFromFile, outputPath, Bitmap.CompressFormat.JPEG, 90);
            System.out.println("Saved to cache: " + saved);

            String internalPath = imageSaver.saveToInternalStorage(bitmapFromFile, "internal_image.jpg", Bitmap.CompressFormat.JPEG);
            System.out.println("Saved to internal: " + internalPath);

            String cachePath = imageSaver.saveToCache(bitmapFromFile, "cache_image.jpg", Bitmap.CompressFormat.JPEG);
            System.out.println("Saved to cache dir: " + cachePath);
        }

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

        AdvancedImageLoader advancedLoader = new AdvancedImageLoader(context);
        System.out.println("Load with exact dimensions (300x300)");
        Bitmap exactBitmap = advancedLoader.loadWithExactDimensions(sampleImagePath, 300, 300);
        System.out.println("Loaded: " + (exactBitmap != null));

        System.out.println("\nLoad with memory limit (1MB)");
        Bitmap limitedBitmap = advancedLoader.loadWithMemoryLimit(sampleImagePath, 1024 * 1024);
        System.out.println("Loaded: " + (limitedBitmap != null));

        // 5. Validation
        System.out.println("\n--- 5. Validation ---");

        ImageValidator validator = new ImageValidator();
        System.out.println("Is valid image: " + validator.isValidImage(sampleImagePath));
        System.out.println("Is corrupt: " + validator.isCorrupt(sampleImagePath));
        System.out.println("Has valid dimensions (>100x100): " + validator.hasValidDimensions(sampleImagePath, 100, 100));

        System.out.println("\n=== All Image Read and Save Examples Completed ===");
    }
}

💻 Bildskalierung java

🟡 intermediate ⭐⭐⭐⭐

Bilder mit verschiedenen Algorithmen und Qualitätseinstellungen skalieren

⏱️ 30 min 🏷️ java, android, image processing, scaling
Prerequisites: Intermediate Java, Android Graphics
// Android Java 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
    public Bitmap scaleToSize(Bitmap bitmap, int newWidth, int newHeight) {
        return Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
    }

    // Scale by factor
    public Bitmap scaleByFactor(Bitmap bitmap, float factor) {
        int newWidth = (int) (bitmap.getWidth() * factor);
        int newHeight = (int) (bitmap.getHeight() * factor);

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

    // Scale maintaining aspect ratio
    public Bitmap scaleMaintainingAspectRatio(Bitmap bitmap, int maxWidth, int maxHeight) {
        float widthRatio = (float) maxWidth / bitmap.getWidth();
        float heightRatio = (float) maxHeight / bitmap.getHeight();
        float scaleFactor = Math.min(widthRatio, heightRatio);

        int newWidth = (int) (bitmap.getWidth() * scaleFactor);
        int newHeight = (int) (bitmap.getHeight() * scaleFactor);

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

    // Scale to fit width
    public Bitmap scaleToWidth(Bitmap bitmap, int targetWidth) {
        float scale = (float) targetWidth / bitmap.getWidth();
        int newHeight = (int) (bitmap.getHeight() * scale);

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

    // Scale to fit height
    public Bitmap scaleToHeight(Bitmap bitmap, int targetHeight) {
        float scale = (float) targetHeight / bitmap.getHeight();
        int newWidth = (int) (bitmap.getWidth() * scale);

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

// 2. Advanced Scaling with Matrix
class MatrixScaler {

    private Paint paint;

    public MatrixScaler() {
        paint = new Paint();
        paint.setFilterBitmap(true);
    }

    // Scale using Matrix
    public Bitmap scaleWithMatrix(Bitmap bitmap, float scaleX, float scaleY) {
        Matrix matrix = new Matrix();
        matrix.postScale(scaleX, scaleY);

        Bitmap scaledBitmap = Bitmap.createBitmap(
            (int) (bitmap.getWidth() * scaleX),
            (int) (bitmap.getHeight() * scaleY),
            Bitmap.Config.ARGB_8888
        );

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

        return scaledBitmap;
    }

    // Scale with rotation
    public Bitmap scaleAndRotate(Bitmap bitmap, float scaleX, float scaleY, float rotation) {
        Matrix matrix = new Matrix();
        matrix.postRotate(rotation);
        matrix.postScale(scaleX, scaleY);

        Bitmap scaledBitmap = Bitmap.createBitmap(
            bitmap.getWidth(),
            bitmap.getHeight(),
            Bitmap.Config.ARGB_8888
        );

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

        return scaledBitmap;
    }

    // Scale with pivot point
    public Bitmap scaleFromPoint(Bitmap bitmap, float scaleX, float scaleY, float pivotX, float pivotY) {
        Matrix matrix = new Matrix();
        matrix.setScale(scaleX, scaleY, pivotX, pivotY);

        Bitmap scaledBitmap = Bitmap.createBitmap(
            bitmap.getWidth(),
            bitmap.getHeight(),
            Bitmap.Config.ARGB_8888
        );

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

        return scaledBitmap;
    }
}

// 3. High Quality Scaling
class QualityScaler {

    // Scale with high quality
    public Bitmap scaleHighQuality(Bitmap bitmap, int newWidth, int newHeight) {
        Paint paint = new Paint();
        paint.setFilterBitmap(true);
        paint.setAntiAlias(true);
        paint.setDither(true);

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

        android.graphics.Rect srcRect = new android.graphics.Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        android.graphics.Rect destRect = new android.graphics.Rect(0, 0, newWidth, newHeight);

        canvas.drawBitmap(bitmap, srcRect, destRect, paint);

        return scaledBitmap;
    }

    // Scale with filtering options
    public Bitmap scaleWithFiltering(Bitmap bitmap, int newWidth, int newHeight, boolean filterBitmap) {
        Paint paint = new Paint();
        paint.setFilterBitmap(filterBitmap);

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

    // Smooth scale (multiple passes)
    public Bitmap smoothScale(Bitmap bitmap, int targetWidth, int targetHeight) {
        Bitmap currentBitmap = bitmap;
        int currentWidth = bitmap.getWidth();
        int currentHeight = bitmap.getHeight();

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

            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
    public Bitmap generateThumbnail(Bitmap bitmap, int thumbWidth, int thumbHeight) {
        BasicImageScaler scaler = new BasicImageScaler();
        return scaler.scaleMaintainingAspectRatio(bitmap, thumbWidth, thumbHeight);
    }

    // Generate square thumbnail (crop center)
    public Bitmap generateSquareThumbnail(Bitmap bitmap, int size) {
        int minDimension = Math.min(bitmap.getWidth(), bitmap.getHeight());

        // Calculate crop bounds
        int x = (bitmap.getWidth() - minDimension) / 2;
        int y = (bitmap.getHeight() - minDimension) / 2;

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

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

    // Generate thumbnail with rounded corners
    public Bitmap generateRoundedThumbnail(Bitmap bitmap, int width, int height, float cornerRadius) {
        // First scale the image
        BasicImageScaler scaler = new BasicImageScaler();
        Bitmap scaled = scaler.scaleMaintainingAspectRatio(bitmap, width, height);

        // Create rounded bitmap
        Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(android.graphics.Color.BLACK);

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

        // Set mask for image
        paint.setXfermode(new android.graphics.PorterDuffXfermode(android.graphics.PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(scaled, 0, 0, paint);

        return output;
    }

    // Generate circular thumbnail
    public Bitmap generateCircularThumbnail(Bitmap bitmap, int diameter) {
        // Create square thumbnail first
        Bitmap square = generateSquareThumbnail(bitmap, diameter);

        // Create circular bitmap
        Bitmap output = Bitmap.createBitmap(diameter, diameter, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(android.graphics.Color.BLACK);

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

        // Set mask for image
        paint.setXfermode(new android.graphics.PorterDuffXfermode(android.graphics.PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(square, 0, 0, paint);

        return output;
    }
}

// 5. Batch Scaling
class BatchScaler {
    private Context context;

    public BatchScaler(Context context) {
        this.context = context;
    }

    // Scale multiple images
    public java.util.List<Bitmap> scaleMultiple(java.util.List<String> filePaths, int targetWidth, int targetHeight) {
        java.util.List<Bitmap> scaledBitmaps = new java.util.ArrayList<>();

        for (String path : filePaths) {
            try {
                Bitmap bitmap = BitmapFactory.decodeFile(path);
                BasicImageScaler scaler = new BasicImageScaler();
                Bitmap scaled = scaler.scaleMaintainingAspectRatio(bitmap, targetWidth, targetHeight);
                scaledBitmaps.add(scaled);
            } catch (Exception e) {
                System.out.println("Error scaling " + path + ": " + e.getMessage());
            }
        }

        return scaledBitmaps;
    }

    // Generate thumbnails for multiple images
    public java.util.List<Bitmap> generateThumbnails(java.util.List<String> filePaths, int thumbSize) {
        java.util.List<Bitmap> thumbnails = new java.util.ArrayList<>();
        ThumbnailGenerator generator = new ThumbnailGenerator();

        for (String path : filePaths) {
            try {
                Bitmap bitmap = BitmapFactory.decodeFile(path);
                Bitmap thumb = generator.generateSquareThumbnail(bitmap, thumbSize);
                thumbnails.add(thumb);
            } catch (Exception e) {
                System.out.println("Error generating thumbnail for " + path + ": " + e.getMessage());
            }
        }

        return thumbnails;
    }

    // Save scaled images
    public boolean saveScaledImages(java.util.List<String> filePaths, String outputDir, int targetWidth, int targetHeight) {
        boolean success = true;

        for (int i = 0; i < filePaths.size(); i++) {
            try {
                String path = filePaths.get(i);
                Bitmap bitmap = BitmapFactory.decodeFile(path);
                BasicImageScaler scaler = new BasicImageScaler();
                Bitmap scaled = scaler.scaleMaintainingAspectRatio(bitmap, targetWidth, targetHeight);

                File outputFile = new File(outputDir, "scaled_" + i + ".jpg");
                FileOutputStream outputStream = new FileOutputStream(outputFile);
                scaled.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);
                outputStream.flush();
                outputStream.close();
            } catch (Exception e) {
                System.out.println("Error saving scaled image: " + e.getMessage());
                success = false;
            }
        }

        return success;
    }
}

// 6. Scaling Utilities
class ScalingUtils {

    // Target size holder
    public static class TargetSize {
        public int width;
        public int height;

        public TargetSize(int width, int height) {
            this.width = width;
            this.height = height;
        }
    }

    // Calculate target size maintaining aspect ratio
    public TargetSize calculateTargetSize(int originalWidth, int originalHeight, int maxWidth, int maxHeight) {
        float widthRatio = (float) maxWidth / originalWidth;
        float heightRatio = (float) maxHeight / originalHeight;
        float scaleFactor = Math.min(widthRatio, heightRatio);

        int newWidth = (int) (originalWidth * scaleFactor);
        int newHeight = (int) (originalHeight * scaleFactor);

        return new TargetSize(newWidth, newHeight);
    }

    // Calculate sample size for efficient loading
    public int calculateSampleSize(int originalWidth, int originalHeight, int requiredWidth, int requiredHeight) {
        int inSampleSize = 1;

        if (originalWidth > requiredWidth || originalHeight > requiredHeight) {
            final int halfWidth = originalWidth / 2;
            final int halfHeight = originalHeight / 2;

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

        return inSampleSize;
    }

    // Get optimal sample size from file
    public int getOptimalSampleSize(String filePath, int reqWidth, int reqHeight) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);

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

// Main demonstration
public class ImageScalingDemo {
    public static void demonstrateImageScaling(Context context) {
        System.out.println("=== Android Java Image Scaling Examples ===\n");

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

        // 1. Basic scaling
        System.out.println("--- 1. Basic Scaling ---");
        BasicImageScaler basicScaler = new BasicImageScaler();

        Bitmap scaledToSize = basicScaler.scaleToSize(sampleBitmap, 400, 300);
        System.out.println("Scaled to 400x300: " + scaledToSize.getWidth() + "x" + scaledToSize.getHeight());

        Bitmap scaledByFactor = basicScaler.scaleByFactor(sampleBitmap, 0.5f);
        System.out.println("Scaled by 0.5x: " + scaledByFactor.getWidth() + "x" + scaledByFactor.getHeight());

        Bitmap aspectRatio = basicScaler.scaleMaintainingAspectRatio(sampleBitmap, 300, 300);
        System.out.println("Scaled maintaining aspect ratio (max 300x300): " + aspectRatio.getWidth() + "x" + aspectRatio.getHeight());

        // 2. Matrix scaling
        System.out.println("\n--- 2. Matrix Scaling ---");
        MatrixScaler matrixScaler = new MatrixScaler();

        Bitmap matrixScaled = matrixScaler.scaleWithMatrix(sampleBitmap, 0.75f, 0.75f);
        System.out.println("Matrix scaled 0.75x: " + matrixScaled.getWidth() + "x" + matrixScaled.getHeight());

        // 3. High quality scaling
        System.out.println("\n--- 3. High Quality Scaling ---");
        QualityScaler qualityScaler = new QualityScaler();

        Bitmap highQuality = qualityScaler.scaleHighQuality(sampleBitmap, 200, 150);
        System.out.println("High quality 200x150: " + highQuality.getWidth() + "x" + highQuality.getHeight());

        Bitmap smoothScaled = qualityScaler.smoothScale(sampleBitmap, 150, 150);
        System.out.println("Smooth scaled to 150x150: " + smoothScaled.getWidth() + "x" + smoothScaled.getHeight());

        // 4. Thumbnails
        System.out.println("\n--- 4. Thumbnails ---");
        ThumbnailGenerator thumbGenerator = new ThumbnailGenerator();

        Bitmap thumbnail = thumbGenerator.generateThumbnail(sampleBitmap, 100, 100);
        System.out.println("Thumbnail (100x100): " + thumbnail.getWidth() + "x" + thumbnail.getHeight());

        Bitmap squareThumb = thumbGenerator.generateSquareThumbnail(sampleBitmap, 80);
        System.out.println("Square thumbnail (80x80): " + squareThumb.getWidth() + "x" + squareThumb.getHeight());

        Bitmap circularThumb = thumbGenerator.generateCircularThumbnail(sampleBitmap, 60);
        System.out.println("Circular thumbnail (60x60): " + circularThumb.getWidth() + "x" + circularThumb.getHeight());

        // 5. Utilities
        System.out.println("\n--- 5. Scaling Utilities ---");
        ScalingUtils utils = new ScalingUtils();

        ScalingUtils.TargetSize targetSize = utils.calculateTargetSize(1920, 1080, 800, 600);
        System.out.println("Calculated target size for 1920x1080 (max 800x600): " + targetSize.width + "x" + targetSize.height);

        int sampleSize = utils.calculateSampleSize(1920, 1080, 400, 300);
        System.out.println("Calculated sample size: " + sampleSize);

        System.out.println("\n=== All Image Scaling Examples Completed ===");
    }
}

💻 Bildformatkonvertierung java

🟡 intermediate ⭐⭐⭐

Bilder zwischen PNG-, JPEG-, WebP-Formaten mit Qualitätseinstellungen konvertieren

⏱️ 25 min 🏷️ java, android, image processing, conversion
Prerequisites: Intermediate Java, Android Graphics
// Android Java 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;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

// 1. Basic Format Conversion
class FormatConverter {

    // Convert bitmap to JPEG
    public boolean convertToJPEG(Bitmap bitmap, String filePath, int quality) {
        try {
            File file = new File(filePath);
            File parentDir = file.getParentFile();
            if (parentDir != null && !parentDir.exists()) {
                parentDir.mkdirs();
            }

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

            System.out.println("Converted to JPEG: " + filePath);
            return true;
        } catch (Exception e) {
            System.out.println("Error converting to JPEG: " + e.getMessage());
            return false;
        }
    }

    public boolean convertToJPEG(Bitmap bitmap, String filePath) {
        return convertToJPEG(bitmap, filePath, 90);
    }

    // Convert bitmap to PNG
    public boolean convertToPNG(Bitmap bitmap, String filePath) {
        try {
            File file = new File(filePath);
            File parentDir = file.getParentFile();
            if (parentDir != null && !parentDir.exists()) {
                parentDir.mkdirs();
            }

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

            System.out.println("Converted to PNG: " + filePath);
            return true;
        } catch (Exception e) {
            System.out.println("Error converting to PNG: " + e.getMessage());
            return false;
        }
    }

    // Convert bitmap to WebP
    public boolean convertToWebP(Bitmap bitmap, String filePath, int quality) {
        try {
            File file = new File(filePath);
            File parentDir = file.getParentFile();
            if (parentDir != null && !parentDir.exists()) {
                parentDir.mkdirs();
            }

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

            System.out.println("Converted to WebP: " + filePath);
            return true;
        } catch (Exception e) {
            System.out.println("Error converting to WebP: " + e.getMessage());
            return false;
        }
    }

    public boolean convertToWebP(Bitmap bitmap, String filePath) {
        return convertToWebP(bitmap, filePath, 90);
    }

    // Auto-detect format from file extension
    public boolean convertByExtension(Bitmap bitmap, String filePath, int quality) {
        String extension = getExtension(filePath);
        Bitmap.CompressFormat format;

        switch (extension.toLowerCase()) {
            case "png":
                format = Bitmap.CompressFormat.PNG;
                break;
            case "webp":
                format = Bitmap.CompressFormat.WEBP;
                break;
            default:
                format = Bitmap.CompressFormat.JPEG;
                break;
        }

        try {
            File file = new File(filePath);
            File parentDir = file.getParentFile();
            if (parentDir != null && !parentDir.exists()) {
                parentDir.mkdirs();
            }

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

            System.out.println("Converted to " + format.name() + ": " + filePath);
            return true;
        } catch (Exception e) {
            System.out.println("Error converting: " + e.getMessage());
            return false;
        }
    }

    public boolean convertByExtension(Bitmap bitmap, String filePath) {
        return convertByExtension(bitmap, filePath, 90);
    }

    private String getExtension(String filePath) {
        int lastDot = filePath.lastIndexOf('.');
        return lastDot > 0 ? filePath.substring(lastDot + 1) : "";
    }
}

// 2. Quality-based Conversion
class QualityConverter {

    public enum QualityLevel {
        LOW, MEDIUM, HIGH, MAXIMUM
    }

    // Convert with quality levels
    public boolean convertWithQuality(Bitmap bitmap, String filePath, QualityLevel quality) {
        int qualityValue;
        switch (quality) {
            case LOW:
                qualityValue = 50;
                break;
            case MEDIUM:
                qualityValue = 70;
                break;
            case HIGH:
                qualityValue = 85;
                break;
            case MAXIMUM:
                qualityValue = 100;
                break;
            default:
                qualityValue = 85;
        }

        String extension = getExtension(filePath);
        Bitmap.CompressFormat format;

        switch (extension.toLowerCase()) {
            case "png":
                format = Bitmap.CompressFormat.PNG;
                break;
            case "webp":
                format = Bitmap.CompressFormat.WEBP;
                break;
            default:
                format = Bitmap.CompressFormat.JPEG;
                break;
        }

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

            System.out.println("Converted with quality " + quality + " (" + qualityValue + "%): " + filePath);
            return true;
        } catch (Exception e) {
            System.out.println("Error with quality conversion: " + e.getMessage());
            return false;
        }
    }

    // Convert with custom quality
    public boolean convertWithCustomQuality(Bitmap bitmap, String filePath, int quality) {
        if (quality < 0 || quality > 100) {
            throw new IllegalArgumentException("Quality must be between 0 and 100");
        }

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

            System.out.println("Converted with custom quality (" + quality + "%): " + filePath);
            return true;
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
            return false;
        }
    }

    // Compare quality levels
    public Map<String, Long> compareQualities(Bitmap bitmap, String outputDir) {
        Map<String, Long> results = new HashMap<>();
        int[] qualities = {50, 70, 85, 95};

        for (int quality : qualities) {
            String filePath = outputDir + "/quality_" + quality + ".jpg";

            convertWithCustomQuality(bitmap, filePath, quality);

            File file = new File(filePath);
            long fileSize = file.length();
            results.put("quality_" + quality, fileSize);
        }

        return results;
    }

    private String getExtension(String filePath) {
        int lastDot = filePath.lastIndexOf('.');
        return lastDot > 0 ? filePath.substring(lastDot + 1) : "";
    }
}

// 3. Lossless vs Lossy Conversion
class ConversionTypeConverter {

    // Lossless conversion (PNG)
    public boolean convertLossless(Bitmap bitmap, String filePath) {
        try {
            File file = new File(filePath);
            FileOutputStream outputStream = new FileOutputStream(file);

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

            System.out.println("Lossless conversion (PNG): " + filePath);
            return true;
        } catch (Exception e) {
            System.out.println("Error in lossless conversion: " + e.getMessage());
            return false;
        }
    }

    // Lossy conversion (JPEG)
    public boolean convertLossy(Bitmap bitmap, String filePath, int quality) {
        try {
            File file = new File(filePath);
            FileOutputStream outputStream = new FileOutputStream(file);

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

            System.out.println("Lossy conversion (JPEG, quality=" + quality + "): " + filePath);
            return true;
        } catch (Exception e) {
            System.out.println("Error in lossy conversion: " + e.getMessage());
            return false;
        }
    }

    public boolean convertLossy(Bitmap bitmap, String filePath) {
        return convertLossy(bitmap, filePath, 85);
    }

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

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

            System.out.println("WebP near-lossless: " + filePath);
            return true;
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
            return false;
        }
    }
}

// 4. Batch Format Conversion
class BatchConverter {

    // Convert multiple images to same format
    public boolean convertMultipleToFormat(
            java.util.List<String> inputFiles,
            String outputDir,
            Bitmap.CompressFormat format,
            int quality
    ) {
        boolean success = true;

        for (int i = 0; i < inputFiles.size(); i++) {
            try {
                String inputFile = inputFiles.get(i);
                Bitmap bitmap = BitmapFactory.decodeFile(inputFile);

                String extension;
                switch (format) {
                    case PNG:
                        extension = "png";
                        break;
                    case WEBP:
                        extension = "webp";
                        break;
                    default:
                        extension = "jpg";
                        break;
                }

                File outputFile = new File(outputDir, "converted_" + i + "." + extension);
                FileOutputStream outputStream = new FileOutputStream(outputFile);

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

                System.out.println("Converted " + inputFile + " to " + outputFile.getName());

            } catch (Exception e) {
                System.out.println("Error converting: " + e.getMessage());
                success = false;
            }
        }

        return success;
    }

    public boolean convertMultipleToFormat(
            java.util.List<String> inputFiles,
            String outputDir,
            Bitmap.CompressFormat format
    ) {
        return convertMultipleToFormat(inputFiles, outputDir, format, 90);
    }

    // Convert directory of images
    public int convertDirectory(String inputDir, String outputDir, Bitmap.CompressFormat targetFormat, int quality) {
        File inputDirectory = new File(inputDir);
        File outputDirectory = new File(outputDir);

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

        File[] imageFiles = inputDirectory.listFiles(file -> {
            String ext = getExtension(file.getName()).toLowerCase();
            return ext.equals("jpg") || ext.equals("jpeg") || ext.equals("png") || ext.equals("webp");
        });

        if (imageFiles == null) {
            imageFiles = new File[0];
        }

        int convertedCount = 0;

        for (File file : imageFiles) {
            try {
                Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());

                String extension;
                switch (targetFormat) {
                    case PNG:
                        extension = "png";
                        break;
                    case WEBP:
                        extension = "webp";
                        break;
                    default:
                        extension = "jpg";
                        break;
                }

                String nameWithoutExtension = file.getName().substring(0, file.getName().lastIndexOf('.'));
                File outputFile = new File(outputDir, nameWithoutExtension + "." + extension);
                FileOutputStream outputStream = new FileOutputStream(outputFile);

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

                convertedCount++;

            } catch (Exception e) {
                System.out.println("Error converting " + file.getName() + ": " + e.getMessage());
            }
        }

        System.out.println("Converted " + convertedCount + "/" + imageFiles.length + " images");
        return convertedCount;
    }

    public int convertDirectory(String inputDir, String outputDir, Bitmap.CompressFormat targetFormat) {
        return convertDirectory(inputDir, outputDir, targetFormat, 90);
    }

    private String getExtension(String filename) {
        int lastDot = filename.lastIndexOf('.');
        return lastDot > 0 ? filename.substring(lastDot + 1) : "";
    }
}

// 5. Format Comparison
class FormatComparator {

    // Compare file sizes for different formats
    public Map<String, Long> compareFormatSizes(Bitmap bitmap, String outputDir) {
        Map<String, Long> sizes = new HashMap<>();

        try {
            // JPEG with different qualities
            File jpeg85 = new File(outputDir, "compare_85.jpg");
            bitmap.compress(Bitmap.CompressFormat.JPEG, 85, new FileOutputStream(jpeg85));
            sizes.put("JPEG_85", jpeg85.length());

            File jpeg95 = new File(outputDir, "compare_95.jpg");
            bitmap.compress(Bitmap.CompressFormat.JPEG, 95, new FileOutputStream(jpeg95));
            sizes.put("JPEG_95", jpeg95.length());

            // PNG
            File png = new File(outputDir, "compare.png");
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream(png));
            sizes.put("PNG", png.length());

            // WebP
            File webp = new File(outputDir, "compare.webp");
            bitmap.compress(Bitmap.CompressFormat.WEBP, 90, new FileOutputStream(webp));
            sizes.put("WebP", webp.length());

        } catch (IOException e) {
            System.out.println("Error comparing formats: " + e.getMessage());
        }

        return sizes;
    }

    // Get compression ratio
    public double getCompressionRatio(long originalSize, long compressedSize) {
        return ((double) (originalSize - compressedSize) / originalSize) * 100;
    }

    // Format info class
    public static class FormatInfo {
        public String format;
        public int quality;
        public Bitmap.CompressFormat compressFormat;

        public FormatInfo(String format, int quality, Bitmap.CompressFormat compressFormat) {
            this.format = format;
            this.quality = quality;
            this.compressFormat = compressFormat;
        }
    }

    // Compare quality options
    public java.util.List<FormatInfo> compareQuality(Bitmap bitmap) {
        java.util.List<FormatInfo> formats = new java.util.ArrayList<>();
        formats.add(new FormatInfo("JPEG", 85, Bitmap.CompressFormat.JPEG));
        formats.add(new FormatInfo("JPEG", 95, Bitmap.CompressFormat.JPEG));
        formats.add(new FormatInfo("PNG", 100, Bitmap.CompressFormat.PNG));
        formats.add(new FormatInfo("WebP", 90, Bitmap.CompressFormat.WEBP));

        return formats;
    }
}

// 6. Special Conversions
class SpecialConverter {

    // Convert to grayscale and save
    public boolean convertToGrayscale(Bitmap bitmap, String filePath) {
        try {
            Bitmap grayscaleBitmap = Bitmap.createBitmap(
                bitmap.getWidth(),
                bitmap.getHeight(),
                Bitmap.Config.ARGB_8888
            );

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

            paint.setColorFilter(new android.graphics.ColorMatrixColorFilter(colorMatrix));
            canvas.drawBitmap(bitmap, 0, 0, paint);

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

            System.out.println("Converted to grayscale: " + filePath);
            return true;
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
            return false;
        }
    }

    // Convert with color filter
    public boolean convertWithColorFilter(Bitmap bitmap, String filePath, int color) {
        try {
            Bitmap filteredBitmap = Bitmap.createBitmap(
                bitmap.getWidth(),
                bitmap.getHeight(),
                Bitmap.Config.ARGB_8888
            );

            Canvas canvas = new Canvas(filteredBitmap);
            android.graphics.Paint paint = new android.graphics.Paint();

            paint.setColorFilter(new android.graphics.PorterDuffColorFilter(
                color,
                android.graphics.PorterDuff.Mode.SRC_ATOP
            ));

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

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

            System.out.println("Converted with color filter: " + filePath);
            return true;
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
            return false;
        }
    }
}

// Main demonstration
public class ImageFormatConversionDemo {
    public static void demonstrateImageFormatConversion() {
        System.out.println("=== Android Java Image Format Conversion Examples ===\n");

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

        // 1. Basic conversion
        System.out.println("--- 1. Basic Format Conversion ---");
        FormatConverter converter = new FormatConverter();

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

        // 2. Quality conversion
        System.out.println("\n--- 2. Quality Conversion ---");
        QualityConverter qualityConverter = new QualityConverter();

        System.out.println("Converting with quality levels:");
        QualityConverter.QualityLevel[] levels = QualityConverter.QualityLevel.values();
        for (QualityConverter.QualityLevel level : levels) {
            System.out.println("  - " + level);
        }

        // 3. Lossless vs Lossy
        System.out.println("\n--- 3. Lossless vs Lossy ---");
        ConversionTypeConverter typeConverter = new ConversionTypeConverter();

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

        // 4. Format comparison
        System.out.println("\n--- 4. Format Comparison ---");
        FormatComparator comparator = new FormatComparator();

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

        long originalSize = 1000000L; // Example size
        long compressedSize = 150000L;

        double ratio = comparator.getCompressionRatio(originalSize, compressedSize);
        System.out.printf("\nCompression ratio: %.2f%%%n", ratio);

        // 5. Batch conversion
        System.out.println("\n--- 5. Batch Conversion ---");
        BatchConverter batchConverter = new BatchConverter();

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

        // 6. Special conversions
        System.out.println("\n--- 6. Special Conversions ---");
        SpecialConverter specialConverter = new SpecialConverter();

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

        System.out.println("\n=== All Image Format Conversion Examples Completed ===");
    }
}