繁体   English   中英

从 c++ 服务器接收到的 PNG 图片在 java android 客户端崩溃

[英]PNG Image which received from c++ server, crashes on java android client

我正在开发 android 海洋导航客户端。 客户端应该从 c++ 服务器接收海图图像。 我正在通过套接字发送数据。 (从 c++:ClientSocket.h,到 java:java.net.Socket)

接收图像大小很好。(我很明显地注意到 java integer 类型的字节顺序颠倒了 c++ 顺序)

但是图像数据并不好。 首先我使用转换图像

BitmapFactory.decodeByteArray(imageAr, 0, imageAr.length);

结果是null。所以我尝试将数据保存为android设备中的png文件。 但是图像文件崩溃了。 c++ png格式和java png格式有什么区别吗?

这是我的代码

服务器.cpp

HBITMAP bmp = hencCaptureBuffer();//get bitmap from nautical chart library
if (bmp == NULL)
{
    std::cout << "Failed to create bitmap\n";
    return;
}
CImage img;
img.Attach(bmp);

HGLOBAL h_buffer = ::GlobalAlloc(GMEM_MOVEABLE, MAX_IMAGE_SIZE);
if (h_buffer != NULL) {
    int png_data_size = 0;
    IStream* p_stream = NULL;
    if (::CreateStreamOnHGlobal(h_buffer, FALSE, &p_stream) == S_OK) {
        img.Save(p_stream, ImageFormatPNG);

        p_stream->Release();
    }
    void* p_png_data = ::GlobalLock(h_buffer);
    char* new_png_data = (char*)p_png_data;

    int pos = 0;
    while (true)
    {
        if (*(new_png_data + pos) == 0x00 &&
            *(new_png_data + pos + 1) == 0x00 &&
            *(new_png_data + pos + 2) == 0x00 &&
            *(new_png_data + pos + 3) == 0x00 &&
            *(new_png_data + pos + 4) == 0x00 &&
            *(new_png_data + pos + 5) == 0x00 &&
            *(new_png_data + pos + 6) == 0x00 &&
            *(new_png_data + pos + 7) == 0x00)
            break;
        pos++;
    }

    int p_size = pos - 1;
    double p_rate = horiRate;

    cs->Send(&p_size, 4, 0);//send image size
    cs->Send(new_png_data, p_size, 0);//send image data
    cs->Send(&p_rate, 8, 0);

    ::GlobalUnlock(h_buffer);
    ::GlobalFree(h_buffer);
}

客户.java

package com.mapsea.test002;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.Button;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStream;
import java.net.Socket;
import java.nio.ByteBuffer;
import  java.util.Arrays;
import java.util.Base64;

public class MainActivity extends AppCompatActivity {

    private ImageView img;
    private Socket socket;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    socket = new Socket("192.168.20.102", 4578);
                } catch (
                        IOException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
        img = (ImageView) findViewById(R.id.ENCImageView);
        ((Button) findViewById(R.id.button_display))
                .setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        Thread thread = new Thread(new Runnable() {
                            @RequiresApi(api = Build.VERSION_CODES.O)
                            @Override
                            public void run() {
                                try {
                                    OutputStream outputStream = socket.getOutputStream();
                                    String encString = "1920&1080&126.3457&37.2222&10000&0&10&1&";
                                    byte[] masks = new byte[49];
                                    for (int i = 0; i < masks.length - 1; i++) {
                                        masks[i] = -127;
                                    }
                                    masks[masks.length - 1] = 0;
                                    byte[] tmpParam = encString.getBytes();
                                    byte[] encParam = new byte[tmpParam.length + masks.length];
                                    System.arraycopy(tmpParam, 0, encParam, 0, tmpParam.length);
                                    System.arraycopy(masks, 0, encParam, tmpParam.length, masks.length);
                                    outputStream.write(encParam);
                                    outputStream.flush();

                                    InputStream inputStream = socket.getInputStream();

                                    byte[] sizeAr = new byte[4];
                                    inputStream.read(sizeAr);
                                    byte[] reverseSize = new byte[sizeAr.length];
                                    for (int i = 0; i < sizeAr.length; i++) {
                                        reverseSize[sizeAr.length - i - 1] = sizeAr[i];
                                    }
                                    int size = ByteBuffer.wrap(reverseSize).asIntBuffer().get();

                                    byte[] imageAr = new byte[size];
                                    inputStream.read(imageAr);
                                    File file = new File("/sdcard/DCIM/file3.png");
                                    FileOutputStream fos = new FileOutputStream(file);
                                    fos.write(imageAr);
                                    fos.flush();
                                    fos.close();

                                    Bitmap encbmp = BitmapFactory.decodeByteArray(imageAr, 0, imageAr.length);

                                    if(encbmp == null)
                                    {
                                        encbmp = null;
                                    }

                                    synchronized (this) {
                                        runOnUiThread(new Runnable() {
                                            @Override
                                            public void run() {
                                                //img.setImageBitmap(encbmp);
                                            }
                                        });
                                    }


                                    byte[] rateAr = new byte[8];
                                    inputStream.read(rateAr);
                                    byte[] reverseRate = new byte[rateAr.length];
                                    for (int i = 0; i < rateAr.length; i++) {
                                        reverseRate[rateAr.length - i - 1] = rateAr[i];
                                    }
                                    double rate = ByteBuffer.wrap(reverseRate).asDoubleBuffer().get();

                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                        thread.start();
                    }
                });
    }
}

我像这样添加了我的客户端代码,它起作用了。

问题是我尝试在数据完全接收之前保存图像。

我添加了 do-while 等待完成接收

                                    byte[] imageAr = new byte[size];
                                    int sumLength = 0;
                                    do {
                                        byte[] tmpImage = new byte[size];
                                        int nRead = inputStream.read(tmpImage, 0, size - sumLength);

                                        for(int i = 0; i < nRead; i++)
                                        {
                                            imageAr[sumLength + i] = tmpImage[i];
                                        }

                                        sumLength += nRead;
                                    }while (sumLength < size);
                                    Bitmap encbmp = BitmapFactory.decodeByteArray(imageAr, 0, imageAr.length);

暂无
暂无

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

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