【问题标题】:Unable to save right jpg format picture taken from ESP32Cam module and it does not open in Windows无法保存从 ESP32Cam 模块拍摄的正确 jpg 格式图片,并且无法在 Windows 中打开
【发布时间】:2021-09-22 11:59:13
【问题描述】:

尝试将 ESP32Cam 模块拍摄的图片以 JPG 文件格式保存到 SD 卡中,但无法在 Windows 中打开。

我已按照以下链接中的代码拍照: https://github.com/espressif/esp32-camera/blob/6a9497bbe909165663d958986e621e98dabcf994/examples/main/take_picture.c

拍照后,我使用“frame2jpg”将其转换为 jpg 文件。使用的相机是OV2640。转换后,我将 as.jpg 文件保存在 SD 卡中。我移动到 Windows PC 的 SD 卡并试图打开保存的 .jpg 文件,但它没有打开。它给出了一条消息,表明文件无法识别。

除了“frame2jpg”之外,我还需要做更多的事情来将其转换为正确的格式吗?
[编辑]:在 fclose 之后移动了“esp_camera_fb_return”。

void app_main()
{
mount_sdcard();

if(ESP_OK != init_camera()) {
    return;
}

int     suffix = 0;
char    fnsuffix[25];

size_t cnv_buf_len;
uint8_t * cnv_buf = NULL;

while (suffix < 3) {
    ESP_LOGI(TAG, "Taking picture...");
    camera_fb_t *pic = esp_camera_fb_get();

    // 20210922 convert to jpg -start
//  bool isConverted = frame2bmp(pic, &cnv_buf, &cnv_buf_len);
    bool isConverted = frame2jpg(pic, 80, &cnv_buf, &cnv_buf_len);
    if(!isConverted){   ESP_LOGE(TAG,"failed to convert");  }
    // 20210922 convert to jpg -end

    // picture in a file-------------
    suffix++;
    char* cntStr= itoa(suffix,countFile,10);

    // create a file.
    ESP_LOGI(TAG, "Opening file");
    strcpy(fnsuffix, MOUNT_POINT);
    strcat(fnsuffix, "/fnb");
    strcat(fnsuffix, cntStr);
//  strcat(fnsuffix, ".bmp");
    strcat(fnsuffix, ".jpg");
    ESP_LOGI(TAG, "Opening file %s",fnsuffix);
    FILE *f = fopen(fnsuffix, "wb");
    if (f == NULL) {ESP_LOGE(TAG, "Failed to open file for writing"); return;}
    fwrite(pic->buf, pic->len,1,f);
    fclose(f);
    ESP_LOGI(TAG, " picture file written as %s. size=%zu",fnsuffix,pic->len);
    //save done-----------------------------

    esp_camera_fb_return(pic);

    vTaskDelay(5000 / portTICK_RATE_MS);
}


}

添加了 JPG 的十六进制编辑器

43 4b 43 4b 43 68 43 68 4b 2b 4b 2b 52 ec 4a cb
52 cb 52 cb 52 ea 52 ea 4a eb 42 cb 42 eb 42 ec
4b 2c 4b 2c 42 ea 43 0a 4a ea 53 0b 4a ec 4a
..... first 3 lines above


.... last 2 lines
18 e4 18 e4 18 c5 18 c4 18 c4 18 c4 18 c3 18 c3
18 c3 18 c3 18 a3 18 a2 18 c3 18 a3 18 a4 18 a4

控制台日志

    I (785) cpu_start: Application information:
    I (787) cpu_start: Project name:     camera_example
    I (793) cpu_start: App version:      3022601-dirty
    I (799) cpu_start: Compile time:     Sep 19 2021 20:46:16
    I (805) cpu_start: ELF file SHA256:  b574883f4e49fb5a...
    I (811) cpu_start: ESP-IDF:          baseline-dirty
    I (816) heap_init: Initializing. RAM available for dynamic allocation:
    I (823) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
    I (829) heap_init: At 3FFB6650 len 000299B0 (166 KiB): DRAM
    I (836) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
    I (842) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
    I (848) heap_init: At 40093438 len 0000CBC8 (50 KiB): IRAM
    I (855) spiram: Adding pool of 4096K of external SPI memory to heap allocator
    I (863) spi_flash: detected chip: generic
    I (867) spi_flash: flash io: qio
    I (872) cpu_start: Starting scheduler on PRO CPU.
    I (0) cpu_start: Starting scheduler on APP CPU.
    I (887) spiram: Reserving pool of 32K of internal memory for DMA/internal allocations
    I (895) example:take_picture: format_if_mount_failed is 0
    I (901) example:take_picture: Initializing SD card
    I (907) example:take_picture: Using SDMMC peripheral
    I (913) gpio: GPIO[13]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 
    Name: SU08G
    Type: SDHC/SDXC
    Speed: 20 MHz
    Size: 7580MB
    I (1081) gpio: GPIO[25]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:2 
    I (1084) cam_hal: cam init ok
    I (1088) sccb: pin_sda 26 pin_scl 27
    I (1092) gpio: GPIO[32]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 
    I (1131) camera: Detected camera at address=0x30
    I (1134) camera: Detected OV2640 camera
    I (1134) camera: Camera PID=0x26 VER=0x42 MIDL=0x7f MIDH=0xa2
    I (1214) esp32 ll_cam: node_size: 2560, nodes_per_line: 1, lines_per_node: 1, dma_half_buffer_min:  2560, dma_half_buffer: 15360, lines_per_half_buffer:  6, dma_buffer_size: 30720, image_size: 153600
    I (1222) cam_hal: buffer_size: 30720, half_buffer_size: 15360, node_buffer_size: 2560, node_cnt: 12, total_cnt: 10
    I (1233) cam_hal: Allocating 153600 Byte frame buffer in PSRAM
    I (1240) cam_hal: cam config ok
    I (1243) ov2640: Set PLL: clk_2x: 0, clk_div: 3, pclk_auto: 1, pclk_div: 8
    I (1321) example:take_picture: Taking picture...
    I (1570) example:take_picture: Opening file
    I (1570) example:take_picture: Opening file /sdcard/fnb1.jpg
    I (2221) example:take_picture:  picture file written as /sdcard/fnb1.jpg. size=153600
    I (7221) example:take_picture: Taking picture...
    I (7351) example:take_picture: Opening file
    I (7351) example:take_picture: Opening file /sdcard/fnb2.jpg
    I (7976) example:take_picture:  picture file written as /sdcard/fnb2.jpg. size=153600
    I (12976) example:take_picture: Taking picture...
    I (13105) example:take_picture: Opening file
    I (13105) example:take_picture: Opening file /sdcard/fnb3.jpg
    I (13726) example:take_picture:  picture file written as /sdcard/fnb3.jpg. size=153600

JPG 的已编辑十六进制仍未打开 将 ff d8 ff e0 添加到标题 还添加了预告片字节为 8a 28 03 ff d9

我在照片中打开的创建文件 (Windows)。它用日语显示消息,意思是“对不起,我们不支持这种文件格式或它已损坏。我们无法在照片中打开它”。

我还在浏览器中拖放了 JPG,但似乎为生成 jpg 而写入的字节不正确。

【问题讨论】:

  • 您是否尝试在写入内容后返回帧缓冲区,即将esp_camera_fb_return 移动到fwrite 之后?
  • fwrite(pic-&gt;buf, pic-&gt;len,1,f); esp_camera_fb_return(pic); fclose(f); 我改变了它,但它仍然没有帮助。
  • 请根据 Gerhardh 的建议更新您帖子中的代码,以便我们了解发生了什么。正如他已经说过的那样,您无法真正将已释放的缓冲区保存到 SD 卡中。但在调用fclose() 之后,我将释放缓冲区作为最后一件事。另外请添加控制台输出。信息试图打开保存的 .jpg 文件,但没有打开并没有真正说明文件有什么问题。大小是否正确(即与写入的字节数相同)?你有没有用十六进制编辑器打开文件看看里面有什么?
  • 我已经更新了代码并在帖子中进行了编辑。接下来尝试上面 cmets 中提供的指针。

标签: c image automation camera iot


【解决方案1】:

太好了,现在问题更容易调试了。文件中的数据缺少 JPEG 标头 (ff d8 ff e0 00 10 4a 46 ...),因此它可能是原始图像数据。如果您查看documentation for frame2jpg(),则表明缓冲区cnv_buf 将接收JPEG 图像。但是,这不是您要写入文件的内容。您正在使用原始数据编写原始的、未转换的帧:

    fwrite(pic->buf, pic->len,1,f);

相反,您应该从 JPEG 转换写入输出缓冲区。您还必须稍后手动释放该缓冲区。例如。 (省略错误处理):

    fwrite(cnv_buf, cnv_buf_len, 1, f);
    fclose(f);
    free(cnv_buf);
    esp_camera_fb_return(pic);

请参阅项目自述文件中的HTTP stream example 以获得更详尽的示例。

【讨论】:

  • 谢谢。我错过了转换后的输出缓冲区不同。
猜你喜欢
  • 2019-12-24
  • 1970-01-01
  • 2017-09-20
  • 1970-01-01
  • 2011-09-30
  • 1970-01-01
  • 1970-01-01
  • 2012-05-07
  • 1970-01-01
相关资源
最近更新 更多