【问题标题】:Can't decode string to image using Base64无法使用 Base64 将字符串解码为图像
【发布时间】:2018-07-13 07:04:37
【问题描述】:

在我正在构建的 android 应用程序中,我使用 Base64.encodeToString() 将 jpg 图像转换为字符串并通过 TCP 套接字发送到服务器。

问题是当我尝试将字符串解码回图像时。 我可以打印收到的字符串,它在文件末尾看起来像这样(我可以复制的唯一部分,因为文件太大,无法在终端上打印所有内容):

....+77DgjRKHqbxBmYCDOzv9vLzFwff4N146snCWin6ZlzbN++HJOIIPodB/JTOoc1NjczeqoHwOju
iWdI6ePeSO0ADz46vh4LODnM7FCJYhbTX0TizmNatXvxSFoVzLiqfn19iYjvAPD/AQnRoUxtpJij
AAAAAElFTkSuQmCC

但是当我再次尝试解码并保存到 jpg 文件时,我收到以下错误:

Traceback (most recent call last):
  File "tcp.py", line 20, in <module>
    file.write(base64.decodestring(msg))
  File "/usr/lib/python2.7/base64.py", line 328, in decodestring
    return binascii.a2b_base64(s)
binascii.Error: Incorrect padding

这是我用于编码和发送消息的一段 Android 应用程序代码:

//Function that encodes the Bitmapfile into string
    public String BitMapToString(Bitmap bitmap){
        ByteArrayOutputStream baos=new  ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG,100, baos);
        byte [] arr=baos.toByteArray();
        String result=Base64.encodeToString(arr, Base64.DEFAULT);
        return result;
    }

    class myTask extends AsyncTask<Void,Void,Void>
    {
        //Faz a conexao entre aparelho e servidor
        @Override
        protected Void doInBackground(Void... params){

            try
            {
                //create socket and buffer to send the string message
                newSocket = new Socket(ipAdress,5000);
                printWriter = new PrintWriter(newSocket.getOutputStream());
                bufferedWriter = new BufferedWriter(new OutputStreamWriter(newSocket.getOutputStream()));

                //Reads the internal storage image and converts into string using Base64
                File file  = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM+"/Reccoon3D/123.jpg");
                Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
                message = BitMapToString(bitmap); //encodes the bitmap
                //sends the enconded image
                bufferedWriter.write(message);
                bufferedWriter.flush();
                bufferedWriter.close();
                newSocket.close();
            }catch (Exception e)
            {
                e.printStackTrace();
            }
            return null;
        }
    }

这是我接收消息并尝试再次将其解码为图像的python代码:

import socket
import base64 

host = '192.168.1.16'
port = 5000
tcp=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
orig = (host,port)
tcp.bind(orig)
tcp.listen(1)
file=open('file.png','wb')

while True:
    con, client = tcp.accept()
    print('Conected by', client)
    while True:
        msg = con.recv(1024000) #Initially 1024 but changet so the message
                                #would not be sliced into pieces
        if not msg: break
        #print(msg)
        file.write(base64.decodestring(msg))

    print('Finalizado com sucesso')
    con.close

【问题讨论】:

  • 你没有错过一些(最多 2 个)= base64 blob 末尾的字符吗?
  • 首先检查发送的字节数是否等于接收的字节数。请说出金额。
  • `recv´ 不能保证一次返回所有数据,即使您提供较大的数据。 Receive all of the data when using python socket 的可能重复项
  • I convert the jpg image to string。一点都不。您将 jpg 图像转换为位图。然后把位图转成一个png。然后你对 png 进行 base64 编码。

标签: android python sockets tcp base64


【解决方案1】:
    msg = con.recv(1024000) #Initially 1024 but changet so the message

这将从套接字读取最多 1024000 个字节。可能比这个少。并且,使用recv读取的块大小不需要与对端写入的块大小有任何关联,除了读取所有recv的总大小与发送的总大小相匹配。

    file.write(base64.decodestring(msg))

base64 字符串的大小始终是 4 字节的倍数。即使解码的数据只有一个字节,编码的字符串也将是 4 个字节:2 个对输入进行编码,2 个 '=' 用于填充。如果与 decodestring 一起使用的字符串的长度不是 4 的倍数,它将假定填充错误,即 raise binascii.Error: Incorrect padding

您的代码盲目地假设msg 的长度始终是4 的倍数,因为您有点假设recv 将返回所有发送的数据。但是,这个假设是错误的,如果 msg 的长度不是 4 的倍数,您就会看到您看到的错误。

【讨论】:

    【解决方案2】:

    我做的和你说的一模一样。

    在我正在构建的 android 应用程序中,我将 jpg 图像转换为 使用 Base64.encodeToString() 并通过 TCP 发送到服务器的字符串 插座。

    我终于明白了。

    首先我将this项目用作模板。在这里,您可以拍摄快照,然后将其作为位图加载。然后你必须把它转换成一个字节数组编码为PNG文件,然后通过base64算法(已经在Java中实现)进行编码。

    然后我用 python 和其他一些东西制作了一个套接字服务器来处理传输。获得编码字符串后,您只需对其进行解码并将生成的字符串保存为 .png 文件,然后使用 cv2.imread() 和 Vuala 加载它!

    如果你想看看我是如何做到的,这里是我的项目: Android side Python side

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-16
      • 1970-01-01
      相关资源
      最近更新 更多