0

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?

ocrdu
1,7953 gold badges12 silver badges24 bronze badges
asked Jan 30, 2024 at 6:12

1 Answer 1

0

I just managed to solve this problem with using frame2jpg() function.

Hope it helps!

answered Jan 30, 2024 at 10:48
2
  • 1
    Perhaps you would like to expand this answer to include a little more detail? Commented 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! Commented Jan 31, 2024 at 7:51

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.