Android客户端通过Socket发送ImageView到PC端收到黑图问题求解
问题原因
- 核心问题:
getBitmapFromDrawable方法中未给Drawable设置绘制边界,Drawable默认边界为(0,0,0,0),即使Drawable有内容也无法绘制到创建的Bitmap上,最终生成空图像。 - 格式不匹配:安卓端将图像压缩为PNG格式,服务端却以
.jpg后缀存储,部分图像查看器无法识别格式错位的文件,会显示为全黑。 - 缺少有效性校验:未判断Bitmap压缩是否成功,也未确认
mImageView.getDrawable()是否为有效对象,可能出现无效数据传输。 - 前置逻辑遗漏:布局中
ImageView仅覆盖在相机预览层之上,默认无内容,若未手动将相机帧赋值给ImageView,拿到的Drawable本身就是空的。
修复方案
1. 修复Drawable绘制逻辑
修改getBitmapFromDrawable方法,增加边界设置和空判断:
public Bitmap getBitmapFromDrawable(Drawable drawable){ if (drawable == null) { return null; } int width = drawable.getIntrinsicWidth(); int height = drawable.getIntrinsicHeight(); // 兼容无固有宽高的Drawable,取ImageView实际宽高 if (width <= 0 || height <= 0) { width = mImageView.getWidth(); height = mImageView.getHeight(); if (width <=0 || height <=0) { return null; } } Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); canvas.drawColor(Color.WHITE); // 核心新增:设置Drawable绘制边界 drawable.setBounds(0, 0, width, height); drawable.draw(canvas); return bitmap; }
2. 统一图像格式
二选一即可:
- 方案A:安卓端保持PNG压缩,修改服务端存储文件后缀
# 把jpg后缀改成png with open('/home/pi/Desktop/frames_saved/image.png', 'wb') as file:
- 方案B:服务端保持JPG存储,修改安卓端压缩格式
// 第二个参数为质量,0-100之间,数值越高画质越好 bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
3. 增加有效性校验
在点击事件中增加判断,避免无效数据传输:
Drawable drawable = mImageView.getDrawable(); if (drawable == null) { return; } Bitmap bitmap = getBitmapFromDrawable(drawable); if (bitmap == null) { return; } ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 校验压缩是否成功 boolean compressSuccess = bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); if (!compressSuccess) { baos.close(); return; } byte[] array = baos.toByteArray(); baos.close(); // 后续执行发送逻辑
4. (可选)优化传输完整性
TCP是流协议,建议发送前先传输图像总长度,避免少收/粘包问题:
安卓端发送逻辑修改:
DataOutputStream dataOutputStream= new DataOutputStream(out); // 先发送4字节的文件长度 dataOutputStream.writeInt(array.length); dataOutputStream.write(array,0,array.length); dataOutputStream.flush();
服务端接收逻辑修改:
import struct # 先接收4字节长度 len_data = conn.recv(4) file_len = struct.unpack('!I', len_data)[0] received_len = 0 with open('/home/pi/Desktop/frames_saved/image.png', 'wb') as file: while received_len < file_len: data = conn.recv(min(1024*8, file_len - received_len)) if not data: break file.write(data) received_len += len(data)
内容的提问来源于stack exchange,提问作者user11597888
相关产品推荐
相关产品推荐

