无法正确保存从 ESP32Cam 模块拍摄的 jpg 格式图片,并且无法在 Windows 中打开
Unable to save right jpg format picture taken from ESP32Cam module and it does not open in Windows
试图将 ESP32Cam 模块拍摄的照片以 JPG 文件格式保存到 SD 卡中,但在 Windows 中无法打开。
我已经按照下面的代码拍照了 link:
https://github.com/espressif/esp32-camera/blob/6a9497bbe909165663d958986e621e98dabcf994/examples/main/take_picture.c
拍完照片后,我正在使用“frame2jpg”将其转换为 jpg 文件。使用的相机是OV2640。转换后我将 as.jpg 文件保存在 SD 卡中。 SD 卡我移动到 Windows PC 并试图打开保存的 .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 Hex还是打不开
将 ff d8 ff e0 添加到 header
还添加了尾部字节作为
8a 28 03 ff d9
我在照片中打开的创建文件 (Windows)。它以日语显示消息,意思是“抱歉,我们不支持此文件格式或它已损坏。我们无法在照片中打开它”。
我也在浏览器中拖放了 JPG,但似乎为制作 jpg 而写入的字节不正确。
太好了,现在问题更容易调试了。文件中的数据缺少 JPEG header (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。
试图将 ESP32Cam 模块拍摄的照片以 JPG 文件格式保存到 SD 卡中,但在 Windows 中无法打开。
我已经按照下面的代码拍照了 link: https://github.com/espressif/esp32-camera/blob/6a9497bbe909165663d958986e621e98dabcf994/examples/main/take_picture.c
拍完照片后,我正在使用“frame2jpg”将其转换为 jpg 文件。使用的相机是OV2640。转换后我将 as.jpg 文件保存在 SD 卡中。 SD 卡我移动到 Windows PC 并试图打开保存的 .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 Hex还是打不开 将 ff d8 ff e0 添加到 header 还添加了尾部字节作为 8a 28 03 ff d9
我在照片中打开的创建文件 (Windows)。它以日语显示消息,意思是“抱歉,我们不支持此文件格式或它已损坏。我们无法在照片中打开它”。
我也在浏览器中拖放了 JPG,但似乎为制作 jpg 而写入的字节不正确。
太好了,现在问题更容易调试了。文件中的数据缺少 JPEG header (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。