图片的编码存储与解码输出(基于Android将图片转Base64编码后再次解码会导致图片失真的解决办法)

    Android将经Bsae64编码后的图片存储到MySQL,并解码输出查看(问题:图片失真)

    Android项目下载:

链接:https://pan.baidu.com/s/1hvVupGcCf1f41fizF08SNg?pwd=9988 
提取码:9988

部分源码:

package com.example.testandroidmysqlphplogin;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Message;
import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod;
import android.util.Base64;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;


import android.os.Handler;

import android.app.Activity;
import android.content.Intent;


public class MainActivity extends AppCompatActivity {
    protected static final int ERROR = 2;
    protected static final int SUCCESS = 1;
    private EditText et_qq;
    private EditText et_psd;

    Button button,button1;



    private Handler handler = new Handler(){
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SUCCESS:
                    Toast.makeText(MainActivity.this,(String)msg.obj, Toast.LENGTH_LONG).show();
                    break;

                case ERROR:
                    Toast.makeText(MainActivity.this,"传输失败", Toast.LENGTH_LONG).show();
                    break;

            }
        };
    };



    private Object StreamTools;

    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et_qq = (EditText) findViewById(R.id.et_qq);
        et_psd = (EditText) findViewById(R.id.et_pwd);




        button1 = findViewById(R.id.button1);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                ImageView image1 = (ImageView) findViewById(R.id.image1);
                EditText et_pwd = (EditText) findViewById(R.id.et_pwd);
                et_pwd.setMovementMethod(new ScrollingMovementMethod());
                et_pwd.setVerticalScrollBarEnabled(true);
                et_pwd.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);


                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.qq);
                bitmap.compress(Bitmap.CompressFormat.JPEG, 0, baos);
                byte[] imageBytes = baos.toByteArray();
                String imageString = Base64.encodeToString(imageBytes, Base64.DEFAULT);
                et_pwd.setText(imageString);

                /*decode base64 string to image*/
                imageBytes = Base64.decode(imageString, Base64.DEFAULT);
                Bitmap decodedImage = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
                image1.setImageBitmap(decodedImage);



            }});




        button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                ImageView image = (ImageView) findViewById(R.id.image);
                TextView et_pwd = (EditText) findViewById(R.id.et_qq);
                et_qq.setMovementMethod(new ScrollingMovementMethod());
                et_qq.setVerticalScrollBarEnabled(true);
                et_qq.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);


                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ww);
                bitmap.compress(Bitmap.CompressFormat.JPEG, 0, baos);
                byte[] imageBytes = baos.toByteArray();
                String imageString = Base64.encodeToString(imageBytes, Base64.DEFAULT);


                imageBytes = Base64.decode(imageString, Base64.DEFAULT);
                Bitmap decodedImage = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
                image.setImageBitmap(decodedImage);
                et_pwd.setText(imageString);




            }});




        }

    public void login(View view){
        final String qq = et_qq.getText().toString();

        Intent i=new Intent(MainActivity.this,MainActivity.class);
        startActivity(i);

        if(TextUtils.isEmpty(qq)){
            Toast.makeText(this, "不能为空", Toast.LENGTH_SHORT).show();
            return;
        }
        new Thread(){
            public void run(){
                try {
                    String path = "http://192.168.228.1/PHP/MySQL/10.php";
                    URL url = new  URL(path);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    //区别2、请求方式post
                    conn.setRequestMethod("POST");
                    conn.setRequestProperty("User-Agent", "Mozilla/5.0(compatible;MSIE 9.0;Windows NT 6.1;Trident/5.0)");
                    //区别3、必须指定两个请求的参数
                    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");//请求的类型  表单数据
                    String data = "username="+qq+"&button=";
                    ;
                    conn.setRequestProperty("Content-Length", data.length()+"");//数据的长度
                    //区别4、记得设置把数据写给服务器
                    conn.setDoOutput(true);//设置向服务器写数据
                    byte[] bytes = data.getBytes();
                    conn.getOutputStream().write(bytes);//把数据以流的方式写给服务器
                    int code = conn.getResponseCode();
                    System.out.println(code);
                    if(code == 200){
                        InputStream is = conn.getInputStream();
                        String  result = com.example.testandroidmysqlphplogin.StreamTools.readStream(is);
                        Message mas= Message.obtain();
                        mas.what = SUCCESS;
                        mas.obj = result;
                        handler.sendMessage(mas);

                    }else{
                        Message mas = Message.obtain();
                        mas.what = ERROR;
                        handler.sendMessage(mas);
                    }
                }catch (IOException e) {
                    // TODO Auto-generated catch block
                    Message mas = Message.obtain();
                    mas.what = ERROR;
                    handler.sendMessage(mas);
                }
            }
        }.start();

    }




    public void login1(View view){

        Intent i=new Intent(MainActivity.this,MainActivity.class);
        startActivity(i);

        final String psd = et_psd.getText().toString();

        if(TextUtils.isEmpty(psd)){
            Toast.makeText(this, "不能为空", Toast.LENGTH_SHORT).show();
            return;
        }
        new Thread(){
            public void run(){
                try {
                    String path = "http://192.168.228.1/PHP/MySQL/10.php";
                    URL url = new  URL(path);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    //区别2、请求方式post
                    conn.setRequestMethod("POST");
                    conn.setRequestProperty("User-Agent", "Mozilla/5.0(compatible;MSIE 9.0;Windows NT 6.1;Trident/5.0)");
                    //区别3、必须指定两个请求的参数
                    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");//请求的类型  表单数据
                    String data = "username="+psd+"&button=";
                    ;
                    conn.setRequestProperty("Content-Length", data.length()+"");//数据的长度
                    //区别4、记得设置把数据写给服务器
                    conn.setDoOutput(true);//设置向服务器写数据
                    byte[] bytes = data.getBytes();
                    conn.getOutputStream().write(bytes);//把数据以流的方式写给服务器
                    int code = conn.getResponseCode();
                    System.out.println(code);
                    if(code == 200){
                        InputStream is = conn.getInputStream();
                        String  result = com.example.testandroidmysqlphplogin.StreamTools.readStream(is);
                        Message mas= Message.obtain();
                        mas.what = SUCCESS;
                        mas.obj = result;
                        handler.sendMessage(mas);

                    }else{
                        Message mas = Message.obtain();
                        mas.what = ERROR;
                        handler.sendMessage(mas);
                    }
                }catch (IOException e) {
                    // TODO Auto-generated catch block
                    Message mas = Message.obtain();
                    mas.what = ERROR;
                    handler.sendMessage(mas);
                }
            }
        }.start();

    }
}

转Base64编码部分:

ByteArrayOutputStream baos = new ByteArrayOutputStream()Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ww);
bitmap.compress(Bitmap.CompressFormat.JPEG, 0, baos);
byte[] imageBytes = baos.toByteArray();
String imageString = Base64.encodeToString(imageBytes, Base64.DEFAULT);


imageBytes = Base64.decode(imageString, Base64.DEFAULT);
Bitmap decodedImage = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
image.setImageBitmap(decodedImage);
et_pwd.setText(imageString);

Android要存储的目标图片:

    Android项目运行:

以上Android程序运行后会将图片的转为Base64编码进行存储,以下是图片转码后的结果。

     php将MySQL中编码解码后输出验证:

下面是进行验证的php代码:

<?php

$link=mysqli_connect("localhost","your_username","your_password","your_database");
$sql = "SELECT * FROM user WHERE Id =1";

$res =    mysqli_query($link,$sql);

$data = array();

$imgStr = '';
while ($row = mysqli_fetch_assoc($res)) {

    $imgStr .= $row['ws_username'];

}

$binaryStr = base64_decode($imgStr);
header("Content-type:image/jpg");
echo $binaryStr;

?>

但是解码后输出后的照片出现了严重失真

     图片失真原因:

  1. 数据量增加:Base64 编码使用64个字符表示原始二进制数据,因此会对原始图片数据进行扩展。编码后的数据量通常会比原始二进制数据大约 33%。这意味着编码后的数据量更大,可能导致传输和存储方面的效率下降。

  2. 在写程序时对图片进行了压缩,导致很多像素点丢失,致使图片存储时就是不完整的。

经过资料查询与多次验证,找到了解决方法:

将图片转为二进制数存储到MySQL,再通过对二进制码转为图片输出可以完整的输出图片,通过php对图片的存储过可以确定,Android不失真的存储图片,可以将图片转为二进制图片进行存储。

存储图片:

转码后存到MySQL:

 将二进制码转图片输出:

 该理论应用于上传的Android程序中可顺利解决Android存图片输出失真问题。

php将图片转二进制码:

<?php
// 连接到数据库
$conn = mysqli_connect("localhost", "rttt", "128", "my");

$imageData = file_get_contents("F:/编号图片/手指/001.jpg");// 读取图片文件的二进制数据

$escapedImageData = mysqli_real_escape_string($conn, $imageData);
//echo $escapedImageData;


// 执行INSERT语句将图片数据插入到数据库表中
$sql = "INSERT INTO images (`image_data`) VALUES ('$escapedImageData')";



mysqli_query($conn, $sql);
?>

php将二进制码转图片验证:

<?php
// 连接到数据库
$conn = mysqli_connect("localhost", "rttt", "128", "my");


// 执行查询语句获取图片数据
$sql = "SELECT image_data FROM images WHERE id = '1'";
$result = mysqli_query($conn, $sql);
$row = mysqli_fetch_assoc($result);


header("Content-type: image/jpeg");// 设置HTTP标头为图像类型


echo $row['image_data'];


mysqli_close($conn);// 关闭数据库连接
?>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值