如何解决如何在 ESP32-CAM 上裁剪位图图像?
我整夜都在用头撞到这段代码。我正在尝试在 ESP32 CAM 上裁剪位图。我拍了一张照片,将照片转换为 bmp,然后调用以下函数:
size_t crop_image(uint8_t *fb,size_t len,uint32_t width,uint32_t height,unsigned short crop_left,unsigned short crop_top,unsigned short crop_width,unsigned short crop_height)
{
uint8_t *buf = fb + BMP_HEADER_LEN;
size_t new_size = crop_width * crop_height * 3 + BMP_HEADER_LEN;
unsigned int write_idx = 0;
for(uint32_t y = crop_top * 3; y < (crop_top + crop_height) * width * 3; y += width * 3){
for(int x = crop_left * 3; x < (crop_left + crop_width) * 3; x += 3){
int pix_idx = x + y;
buf[write_idx++] = buf[pix_idx];
buf[write_idx++] = buf[pix_idx+1];
buf[write_idx++] = buf[pix_idx+2];
}
}
// Adjust the BMP Header
*(uint32_t *)(fb + BMP_HEADER_WIDTH_OFFSET) = crop_width;
*(uint32_t *)(fb + BMP_HEADER_HEIGHT_OFFSET) = -1 * crop_height;
*(uint32_t *)(fb + 6) = new_size;
*(uint32_t *)(fb + 34) = crop_width * crop_height * 3;
return new_size;
}
这几乎有效。如果我将图像的宽度和高度作为crop_width 和crop_height 参数传递,则输出与原始输出相同。如果我传递较小的高度和全宽,那么它也可以工作。当我传入一个比原始宽度小的crop_width 时,我得到一个图像,其中有一条从右上角到底部大约1/3 的对角线“移位”线。看起来我的宽度减少了一个字节,导致 3/2 斜线。但我不知道是什么原因。
我附上了一张全尺寸的 jpg 和一张裁剪好的位图。请注意,jpg 不是源(我的代码不保存原始代码),但与裁剪图像的源非常相似。裁剪后的 bmitmap 是通过调用创建的,crop_left = 0,crop_top = 0,crop_width = 799,crop_height = 600。原始图像为 800x600。
我已经删除了所有额外的代码 - 所以没有错误处理,没有从位图标题中提取宽度/高度等
代码太简单了,快把我逼疯了。谢谢
Image very similar to the original Cropped - note not original bmp - a screenshot - but shows issue
解决方法
好的,几个小时的睡眠可以做的很棒。裁剪后的图像宽度需要填充为 4 字节的倍数。我正在测试的数字恰好不能被 4 整除(整个图像测试除外)。位图图像宽度必须在 4 字节边界上 - 或填充为这样,
感谢您的关注
这是工作代码(仍然没有错误处理):
size_t crop_image(uint8_t *fb,size_t len,uint32_t width,uint32_t height,unsigned short crop_left,unsigned short crop_top,unsigned short crop_width,unsigned short crop_height)
{
uint8_t *buf = fb + BMP_HEADER_LEN;
size_t new_size = crop_width * crop_height * 3 + BMP_HEADER_LEN;
unsigned int write_idx = 0;
for(uint32_t y = crop_top * 3; y < (crop_top + crop_height) * width * 3; y += width * 3){
for(int x = crop_left * 3; x < (crop_left + crop_width) * 3; x += 3){
int pix_idx = x + y;
buf[write_idx++] = buf[pix_idx];
buf[write_idx++] = buf[pix_idx+1];
buf[write_idx++] = buf[pix_idx+2];
}
// Pad to four byte boundary
for (int i_pad=0; i_pad < (crop_width % 4); i_pad++) buf[write_idx++] = 0;
}
// Adjust the BMP Header
*(uint32_t *)(fb + BMP_HEADER_WIDTH_OFFSET) = crop_width;
*(uint32_t *)(fb + BMP_HEADER_HEIGHT_OFFSET) = -1 * crop_height;
*(uint32_t *)(fb + 6) = new_size;
*(uint32_t *)(fb + 34) = crop_width * crop_height * 3;
return new_size;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。