简体   繁体   English

无法使用Base64将字符串解码为图像

[英]Can't decode string to image using Base64

In a android application I'm building, I convert the jpg image to string using Base64.encodeToString() and sending to a server via TCP socket. 在我正在构建的android应用程序中,我使用Base64.encodeToString()将jpg图像转换为字符串,然后通过TCP套接字发送到服务器。

The problem is when I try to decode the string back to the image. 问题是当我尝试将字符串解码回图像时。 I can print the string that I receive, it looks like this at the end of the file(The only part I can copy because the file is to big to print everything on the terminal): 我可以打印收到的字符串,在文件末尾看起来像这样(我可以复制的唯一部分是因为文件很大,可以在终端上打印所有内容):

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

But when I try to decode and save into a jpg file again I get the following error: 但是,当我尝试解码并再次保存为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

Here is a piece of my Android application code used to encode and send the message: 这是我的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;
        }
    }

And here is my python code that receives the message and try to decode it to image again: 这是我的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
  msg = con.recv(1024000) #Initially 1024 but changet so the message 

This will read up to 1024000 bytes from the socket. 这将从套接字读取最多 1024000字节。 It might be less than this. 它可能小于此。 And, the size of the chunks read using recv do not need to have any correlation with the size of the chunks written by the peer, apart from that the total size read over all recv matches the total size sent. 而且,除了在所有recv读取的总大小与发送的总大小相匹配之外,使用recv读取的块的大小不需要与对等方写入的块的大小有任何关联。

  file.write(base64.decodestring(msg)) 

A base64 string has always a size which is a multiple of 4 bytes. base64字符串的大小始终是4个字节的倍数。 Even if the decoded data are only one byte the encoded string will be 4 bytes: 2 encoding the input and 2 '=' for padding. 即使解码的数据只有一个字节,编码的字符串也将是4个字节:2个对输入进行编码,2个“ =”用于填充。 If the length of the string used with decodestring is not a multiple of 4 it will assume a bad padding, ie raise binascii.Error: Incorrect padding . 如果与decodestring字符串一起使用的字符串的长度不是4的倍数,则将假定填充binascii.Error: Incorrect padding ,即引发binascii.Error: Incorrect padding

Your code blindly assumes that the length of msg will always be a multiple of 4 since you kind of assume that recv will return all data sent. 您的代码盲目地假定msg的长度将始终为4的倍数,因为您假设recv将返回所有发送的数据。 But, this assumption is wrong and if the length of msg is not a multiple of 4 you get the error you see. 但是,这种假设是错误的,如果msg的长度不是4的倍数,则会看到错误。

I was doing the exact same thing that you said. 我在做和你说的完全一样的事情。

In a android application I'm building, I convert the jpg image to string using Base64.encodeToString() and sending to a server via TCP socket. 在我正在构建的android应用程序中,我使用Base64.encodeToString()将jpg图像转换为字符串,然后通过TCP套接字发送到服务器。

And I finally got it. 我终于明白了。

First I used as template this project. 首先,我将此项目用作模板。 Here you are able to take a snap and then load it as a BitMap. 在这里,您可以进行捕捉,然后将其作为BitMap加载。 Then you have to convert that into a byte array coded as PNG file, then encode it through base64 algorithm (that is already implemented in Java). 然后,您必须将其转换为编码为PNG文件的字节数组,然后通过base64算法(已在Java中实现)对其进行编码。

Then I made a socket server with python and some other stuff to handle the transmision. 然后,我用python和其他一些东西制作了一个套接字服务器来处理传输。 Once you get the coded string, you only have to decode it and save the resulting string as a .png file then load it with cv2.imread() and Vuala! 获得编码字符串后,只需解码它,并将结果字符串另存为.png文件,然后使用cv2.imread()和Vuala加载它即可!

Here are my projects if you want to check how I did it: Android side Python side 如果您想检查一下我的工作方式,这是我的项目: Android端 Python端

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM