it编程 > App开发 > Android

Android实现png转jpg图片的方法

12人参与 2025-04-24 Android

一、项目概述

在 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图片的资料请关注代码网其它相关文章!

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

基于Android实现系统重启reboot功能

04-24

在Android平台上实现消息推送功能

04-24

在kotlin的安卓项目中使用dagger的操作方法

04-24

如何在Android中实现断点续传功能

04-24

android studio如何通过 jni 调用第三方非标准 so库

04-24

Kotlin中实现多线程数据刷新的完整方案

04-24

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论