Nano Hash - криптовалюты, майнинг, программирование

Не удается декодировать строку в изображение с помощью Base64

В приложении для Android, которое я создаю, я конвертирую изображение jpg в строку с помощью Base64.encodeToString() и отправляю на сервер через сокет 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


Ответы:


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, это предполагает неправильное заполнение, т. е. повышение binascii.Error: Incorrect padding.

Ваш код слепо предполагает, что длина msg всегда будет кратна 4, поскольку вы как бы предполагаете, что recv вернет все отправленные данные. Но это предположение неверно, и если длина msg не кратна 4, вы получите ошибку, которую видите.

02.02.2018

2

Я делал то же самое, что ты сказал.

В приложении для Android, которое я создаю, я конвертирую изображение jpg в строку с помощью Base64.encodeToString() и отправляю на сервер через сокет TCP.

И я, наконец, понял.

Сначала я использовал в качестве шаблона этот проект. Здесь вы можете сделать снимок, а затем загрузить его в виде растрового изображения. Затем вам нужно преобразовать его в массив байтов, закодированный как файл PNG, а затем закодировать его с помощью алгоритма base64 (который уже реализован в Java).

Затем я сделал сервер сокетов с Python и некоторыми другими вещами для обработки передачи. Как только вы получите закодированную строку, вам нужно только декодировать ее и сохранить полученную строку в виде файла .png, а затем загрузить ее с помощью cv2.imread() и Vuala!

Вот мои проекты, если вы хотите проверить, как я это сделал: на стороне Android на стороне Python

30.03.2019
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..