Android

关注公众号 jb51net

关闭
首页 > 软件编程 > Android > Android png转jpg图片

Android实现png转jpg图片的方法

作者:Katie。

在 Android 应用开发中,图像处理是非常常见的需求,本文介绍了如何在 Android平台上实现一个 PNG 转 JPG 的模块,用户可以从相册或文件中选取 PNG 图片,一键将其转换为 JPG 并保存到本地,需要的朋友可以参考下

一、项目概述

在 Android 应用开发中,图像处理是非常常见的需求。PNG 与 JPG 是两种最常见的图片格式:

本项目的目标是:

在 Android 平台上实现一个 PNG 转 JPG 的模块,用户可以从相册或文件中选取 PNG 图片,一键将其转换为 JPG 并保存到本地。

核心功能点:

二、技术背景与相关知识

要完成上述功能,需要掌握以下技术点:

1. 图片格式基础

2. Android Bitmap 原理

3. Canvas 与 Paint

绘制流程:

  1. 创建一个目标 Bitmap

  2. 用 Canvas 绑定该 Bitmap

  3. 通过 Canvas.drawXXX() 方法绘制

4. Android 文件存储

本项目使用外部私有目录,避免申请繁琐权限。

5. Uri 与 ContentResolver

6. Java I/O 与异常处理

7. 动态权限(API 23+)

三、项目实现思路

  1. UI 交互

    • 主界面提供“选择 PNG”“开始转换”按钮与 ImageView

  2. 选择图片

    • 使用 Intent.ACTION_PICK 或 Intent.ACTION_OPEN_DOCUMENT 限定类型为 image/png

  3. 加载 Bitmap

    • 通过 ContentResolver 打开 Uri 的 InputStream

    • 使用 BitmapFactory.decodeStream() 解码

  4. 创建目标 Bitmap

    • 调用 Bitmap.createBitmap(width, height, Config.ARGB_8888)

  5. 处理透明通道

    • 在 Canvas 上先绘制纯白背景,再绘制原 PNG

  6. 压缩与保存

    • 使用 Bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream)

    • 保存到 getExternalFilesDir("converted")

  7. 资源回收

    • 调用 bitmap.recycle() 并关闭流

  8. 结果反馈

    • 返回文件路径,UI 层显示预览并提示用户

四、完整代码(整合且注释详尽)

package com.example.pngtojpgconverter;
 
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
 
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
 
public class MainActivity extends Activity {
    private static final int REQUEST_PICK_PNG = 1001;
    private ImageView imageView;
    private Button btnSelect, btnConvert;
    private Uri selectedUri;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        // 绑定 UI 控件
        imageView = findViewById(R.id.imageView);
        btnSelect = findViewById(R.id.btnSelect);
        btnConvert = findViewById(R.id.btnConvert);
 
        // 选择 PNG 按钮点击
        btnSelect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 启动系统相册,仅显示 PNG
                Intent intent = new Intent(Intent.ACTION_PICK);
                intent.setType("image/png");
                startActivityForResult(intent, REQUEST_PICK_PNG);
            }
        });
 
        // 转换按钮点击
        btnConvert.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 确保已选图片
                if (selectedUri == null) {
                    Toast.makeText(MainActivity.this, "请先选择 PNG 图片", Toast.LENGTH_SHORT).show();
                    return;
                }
                // 调用工具类执行转换
                String jpgPath = ImageConverter.convertPngToJpg(MainActivity.this, selectedUri);
                if (jpgPath != null) {
                    // 转换成功:提示并预览
                    Toast.makeText(MainActivity.this, "转换成功: " + jpgPath, Toast.LENGTH_LONG).show();
                    imageView.setImageURI(Uri.fromFile(new File(jpgPath)));
                } else {
                    // 转换失败:提示
                    Toast.makeText(MainActivity.this, "转换失败", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
 
    // 处理选择结果
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_PICK_PNG && resultCode == RESULT_OK) {
            selectedUri = data.getData();
            imageView.setImageURI(selectedUri);
        }
    }
}
 
// 工具类:执行 PNG 转 JPG
class ImageConverter {
    private static final String TAG = "ImageConverter";
 
    /**
     * 将 PNG 图像转换为 JPG 并保存
     *
     * @param context 应用上下文
     * @param pngUri  PNG 图像的 Uri
     * @return 返回 JPG 文件绝对路径,失败返回 null
     */
    public static String convertPngToJpg(Context context, Uri pngUri) {
        Bitmap srcBitmap = null;
        Bitmap dstBitmap = null;
        FileOutputStream fos = null;
 
        try {
            // 1. 打开 PNG 输入流
            InputStream is = context.getContentResolver().openInputStream(pngUri);
            // 2. 解码为 Bitmap
            srcBitmap = BitmapFactory.decodeStream(is);
            if (srcBitmap == null) {
                Log.e(TAG, "解码 PNG Bitmap 失败");
                return null;
            }
 
            // 3. 创建目标 Bitmap,使用 ARGB_8888 保留高质量
            dstBitmap = Bitmap.createBitmap(
                    srcBitmap.getWidth(),
                    srcBitmap.getHeight(),
                    Bitmap.Config.ARGB_8888
            );
 
            // 4. 使用 Canvas 绘制:白底 + 原图
            Canvas canvas = new Canvas(dstBitmap);
            canvas.drawColor(Color.WHITE); // 填充白色背景
            Paint paint = new Paint();
            paint.setAntiAlias(true);     // 抗锯齿
            canvas.drawBitmap(srcBitmap, 0, 0, paint);
 
            // 5. 准备输出文件
            File outDir = context.getExternalFilesDir("converted");
            if (outDir != null && !outDir.exists()) {
                outDir.mkdirs();
            }
            File jpgFile = new File(outDir, "img_" + System.currentTimeMillis() + ".jpg");
            fos = new FileOutputStream(jpgFile);
 
            // 6. 压缩为 JPG,质量 90%
            boolean ok = dstBitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
            fos.flush();
            if (ok) {
                Log.i(TAG, "JPG 保存成功: " + jpgFile.getAbsolutePath());
                return jpgFile.getAbsolutePath();
            } else {
                Log.e(TAG, "Bitmap.compress 返回 false");
                return null;
            }
 
        } catch (IOException e) {
            Log.e(TAG, "转换异常: " + e.getMessage());
            return null;
 
        } finally {
            // 7. 资源释放
            if (srcBitmap != null) srcBitmap.recycle();
            if (dstBitmap != null) dstBitmap.recycle();
            if (fos != null) {
                try { fos.close(); } catch (IOException ignored) {}
            }
        }
    }
}

五、代码解读

六、项目总结与拓展

  1. 核心技术点回顾

    • Bitmap 解码与创建

    • Canvas 绘图与透明处理

    • Bitmap.compress 压缩与文件写入

    • Uri → InputStream → Bitmap 的流程

    • 外部私有目录的使用,避免权限复杂化

  2. 性能与稳定性

    • 使用 ARGB_8888 保证质量,必要时可改为 RGB_565 以节省内存;

    • 对大图可先按需缩放,避免 OOM;

    • 确保在 finally 中释放资源,防止内存泄漏。

  3. 可扩展功能

    • 批量转换:遍历多张图片,使用线程池并发处理;

    • 动态压缩质量:在 UI 上添加 SeekBar,用户可调整质量值;

    • 其他格式支持:扩展到 PNG→WEBP、BMP→JPG 等;

    • 保存到系统相册:通过 MediaStore API 将 JPG 添加到相册;

    • 透明背景自定义:允许用户选择背景色,而非固定白色;

    • 错误反馈:增强异常捕获,向用户展示详细错误原因;

    • 进度展示:批量转换时显示进度条或通知。

  4. 学习要点

    • 深入理解 Android 图像处理流程;

    • 掌握文件存储最佳实践;

    • 熟悉常见 Bitmap 配置与内存优化技巧;

    • 掌握使用 Canvas 对位图进行二次加工。

以上就是Android实现png转jpg图片的方法的详细内容,更多关于Android png转jpg图片的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文