[英]PNG Image which received from c++ server, crashes on java android client
I'm developing android marine navigation client.我正在开发 android 海洋导航客户端。 The client should receive nautical chart images from c++ server.客户端应该从 c++ 服务器接收海图图像。 I'm sending data via socket.我正在通过套接字发送数据。 (from c++: ClientSocket.h, to java: java.net.Socket) (从 c++:ClientSocket.h,到 java:java.net.Socket)
Receiving image size was fine.(I bearly noticed that the byte order of java integer type is reversed c++ order)接收图像大小很好。(我很明显地注意到 java integer 类型的字节顺序颠倒了 c++ 顺序)
But Image data are not fine.但是图像数据并不好。 First I converted the image using首先我使用转换图像
BitmapFactory.decodeByteArray(imageAr, 0, imageAr.length);
And the result was null. So I tried saving the data as a png file in android device.结果是null。所以我尝试将数据保存为android设备中的png文件。 But the image files are crashed.但是图像文件崩溃了。 Is there any differences between c++ png format and java png format? c++ png格式和java png格式有什么区别吗?
Here are my codes这是我的代码
server.cpp服务器.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);
}
client.java客户.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();
}
});
}
}
I added my client code like this, and it worked.我像这样添加了我的客户端代码,它起作用了。
The problem is that I tried saving image before the data fully received.问题是我尝试在数据完全接收之前保存图像。
I added do-while to wait complete receiving我添加了 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.