You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 18:06:03