I have a ESP32-S3-WROOM module by Freenove which has a camera and a micro SD card module. I can take a snapshot as a PIXELFORMAT_JPEG photo.
However, when I change the pixelformat to "PIXELFORMAT_GRAYSCALE", the module captures the raw data (1 byte for each pixel) which is 480 kB constant for SVGA (600x800).
How can I compress this raw data to jpg? I also tried the way of saving the photo to a ".jpg" file, however, it did not work.
This is my capturing code for it:
/**********************************************************************
Filename : Camera and SDcard
Description : Use the onboard buttons to take photo and save them to an SD card.
Auther : www.freenove.com
Modification: 2022年11月02日
**********************************************************************/
#include "esp_camera.h"
#define CAMERA_MODEL_ESP32S3_EYE
#include "camera_pins.h"
#include "ws2812.h"
#include "sd_read_write.h"
#define BUTTON_PIN 0
void setup() {
Serial.begin(500000);
Serial.setDebugOutput(false);
Serial.println();
pinMode(BUTTON_PIN, INPUT_PULLUP);
ws2812Init();
sdmmcInit();
//removeDir(SD_MMC, "/camera");
createDir(SD_MMC, "/camera");
listDir(SD_MMC, "/camera", 0);
if(cameraSetup()==1){
ws2812SetColor(2);
}
else{
ws2812SetColor(1);
return;
}
}
void loop() {
if (digitalRead(BUTTON_PIN)==LOW) {
delay(20);
if (digitalRead(BUTTON_PIN)==LOW) {
ws2812SetColor(3);
while (digitalRead(BUTTON_PIN)==LOW);
camera_fb_t * fb = NULL;
fb = esp_camera_fb_get();
if (fb != NULL) {
int photo_index = readFileNum(SD_MMC, "/camera");
if (photo_index!=-1) {
String path = "/camera/" + String(photo_index) +".jpg";
Serial.println(fb->len);
writejpg(SD_MMC, path.c_str(), fb->buf, fb->len);
}
esp_camera_fb_return(fb);
}
else {
Serial.println("Camera capture failed.");
}
ws2812SetColor(2);
}
}
}
int cameraSetup(void) {
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.frame_size = FRAMESIZE_SVGA;
config.pixel_format = PIXFORMAT_GRAYSCALE; // for streaming
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.jpeg_quality = 20;
config.fb_count = 1;
// if PSRAM IC present, init with UXGA resolution and higher JPEG quality
// for larger pre-allocated frame buffer.
if (psramFound()) {
config.jpeg_quality = 10;
config.fb_count = 2;
config.grab_mode = CAMERA_GRAB_LATEST;
} else {
// Limit the frame size when PSRAM is not available
config.frame_size = FRAMESIZE_SVGA;
config.fb_location = CAMERA_FB_IN_DRAM;
}
// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return 0;
}
sensor_t * s = esp_camera_sensor_get();
// initial sensors are flipped vertically and colors are a bit saturated
s->set_vflip(s, 1); // flip it back
s->set_brightness(s, 1); // up the brightness just a bit
s->set_saturation(s, 0); // lower the saturation
Serial.println("Camera configuration complete!");
return 1;
}
This is the writejpg()
function that the code snippet used:
void writejpg(fs::FS &fs, const char * path, const uint8_t *buf, size_t size){
File file = fs.open(path, FILE_WRITE);
if (!file) {
Serial.println("Failed to open file for writing");
ws2812SetColor(1);
delay(100);
return;
}
file.write(buf, size);
// Define the chunk size
const size_t chunkSize = 2048;
// Write to serial in chunks
for (size_t i = 0; i < size; i += chunkSize) {
// Calculate the size of the current chunk
size_t currentChunkSize = ((i + chunkSize) <= size) ? chunkSize : (size - i);
// Write the current chunk in hex format to serial
for (size_t j = 0; j < currentChunkSize; ++j) {
Serial.printf("%02X ", buf[i + j]);
// if ((j + 1) % 128 == 0) { // Print a new line every 16 bytes for better readability
// Serial.println();
// }
}
}
Serial.println();
Serial.printf("Saved file to path: %s\r\n", path);
}
This function also prints out the hexadecimal values of the image for debugging.
So, do you guys have any ideas for compressing this image into a jpg file?
1 Answer 1
I just managed to solve this problem with using frame2jpg()
function.
Hope it helps!
-
1Perhaps you would like to expand this answer to include a little more detail?sempaiscuba– sempaiscuba2024年01月30日 11:07:47 +00:00Commented Jan 30, 2024 at 11:07
-
Of course! There is a code that to_jpg() which located in esp32 github repo. You can find the "frame2jpg()" function in it. Also the usage will be like "frame2jpg(fb, quality, &jpg_buf, &jpg_buf_len)" it will return a boolean value which indicating the success situation. If you dont understand, I'm here to help!BehicMV– BehicMV2024年01月31日 07:51:13 +00:00Commented Jan 31, 2024 at 7:51