11#include " SDMMCBlockDevice.h" // Multi Media Card APIs
2- #include " FATFileSystem.h" // Mbed API for portable and embedded systems
2+ #include " FATFileSystem.h" // API to run operations on a FAT file system
33SDMMCBlockDevice blockDevice;
44mbed::FATFileSystem fileSystem (" fs" );
55
66#include " camera.h" // Arduino Mbed Core Camera APIs
7- #include " himax.h" // Exclusive Camera library for the Portenta Vision Shield
7+ #include " himax.h" // API to read from the Himax camera found on the Portenta Vision Shield
88HM01B0 himax;
99Camera cam (himax);
1010
11- FrameBuffer fb ; // Buffer to save the capture
11+ FrameBuffer frameBuffer ; // Buffer to save the camera stream
1212
1313// Settings for our setup
14- #define RES_H (unsigned int )240
15- #define RES_W (unsigned int )320
14+ #define IMAGE_HEIGHT (unsigned int )240
15+ #define IMAGE_WIDTH (unsigned int )320
1616#define IMAGE_MODE CAMERA_GRAYSCALE
17- #define IMAGE_BPP (unsigned int )8
17+ #define BITS_PER_PIXEL (unsigned int )8
18+ #define PALETTE_COLORS_AMOUNT (unsigned int )(pow(2 , BITS_PER_PIXEL))
19+ #define PALETTE_SIZE (unsigned int )(PALETTE_COLORS_AMOUNT * 4 ) // 4 bytes = 32bit per color (3 bytes RGB and 1 byte 0x00)
20+ #define IMAGE_PATH " /fs/image.bmp"
21+
1822// Headers info
19- #define HEADER_FILE_HEADER (unsigned int )14
20- #define HEADER_DIB_SIZE (unsigned int )40
21- #define HEADER_FULL_SIZE (HEADER_FILE_HEADER + HEADER_DIB_SIZE)
22- #define PALETTE_SIZE (2 ^ IMAGE_BPP) * 4 // 4 bytes per color
23+ #define BITMAP_FILE_HEADER_SIZE (unsigned int )14 // For storing general information about the bitmap image file
24+ #define DIB_HEADER_SIZE (unsigned int )40 // For storing information about the image and define the pixel format
25+ #define HEADER_SIZE (BITMAP_FILE_HEADER_SIZE + DIB_HEADER_SIZE)
2326
24- void setup ()
25- {
26- Serial.begin (115200 );
27- while (!Serial)
28- ;
2927
30- // Mount SD Card
31- mountSD ();
28+ void setup (){
29+ Serial.begin (115200 );
30+ while (!Serial && millis () < 5000 );
31+
32+ Serial.println (" Mounting SD Card..." );
33+ mountSDCard ();
34+ Serial.println (" SD Card mounted." );
3235
3336 // Init the cam QVGA, 30FPS, Grayscale
34- if (!cam.begin (CAMERA_R320x240, IMAGE_MODE, 30 ))
35- {
37+ if (!cam.begin (CAMERA_R320x240, IMAGE_MODE, 30 )){
3638 Serial.println (" Unable to find the camera" );
3739 }
38-
39- // Save the headers and the image data into the .bmp file
40- parseData ();
40+ countDownBlink ();
41+ Serial.println (" Fetching camera image..." );
42+ unsigned char *imageData = captureImage ();
43+ digitalWrite (LEDB, HIGH);
44+
45+ Serial.println (" Saving image to SD card..." );
46+ saveImage (imageData, IMAGE_PATH);
47+
48+ fileSystem.unmount ();
49+ Serial.println (" Done. You can now remove the SD card." );
4150}
4251
43- void loop ()
44- {
45- while (1 )
46- ;
52+ void loop (){
4753}
4854
4955// Mount File system block
50- void mountSD ()
51- {
52- Serial.println (" Mounting SD Card..." );
53-
56+ void mountSDCard (){
5457 int error = fileSystem.mount (&blockDevice);
55- if (error)
56- {
57- Serial.println (" No SD Card found" );
58- while (1 )
59- ;
58+ if (error){
59+ Serial.println (" Trying to reformat..." );
60+ int formattingError = fileSystem.reformat (&blockDevice);
61+ if (formattingError) {
62+ Serial.println (" No SD Card found" );
63+ while (1 );
64+ }
6065 }
6166}
6267
63- void parseData ()
64- {
65- unsigned char *imgData = NULL ;
66- int fileSize = HEADER_FILE_HEADER + RES_W * RES_H;
67-
68- FILE *file = fopen (" /fs/image.bmp" , " w+" );
69-
70- // Get a Frame
71- if (cam.grabFrame (fb, 3000 ) == 0 )
72- {
73- // Save the raw image data (8bpp grayscale)
74- imgData = fb.getBuffer ();
75- }
76- else
77- {
68+ // Get the raw image data (8bpp grayscale)
69+ unsigned char * captureImage (){
70+ if (cam.grabFrame (frameBuffer, 3000 ) == 0 ){
71+ return frameBuffer.getBuffer ();
72+ } else {
7873 Serial.println (" could not grab the frame" );
79- while (1 )
80- ;
74+ while (1 );
8175 }
82- // Bitmap structure (Head + DIB Head + ColorMap + binary image)
83- unsigned char bitmapFileHeader[HEADER_FILE_HEADER];
84- unsigned char bitmapDIBHeader[HEADER_DIB_SIZE];
85- unsigned char colorMap[PALETTE_SIZE]; // Needed for <=8bpp grayscale bitmaps
76+ }
8677
87- // Set the file headers to 0
88- memset (bitmapFileHeader, (unsigned char )(0 ), HEADER_FILE_HEADER);
89- memset (bitmapDIBHeader, (unsigned char )(0 ), HEADER_DIB_SIZE);
90- memset (colorMap, (unsigned char )(0 ), PALETTE_SIZE);
78+ // Set the headers data
79+ void setFileHeaders (unsigned char *bitmapFileHeader, unsigned char *bitmapDIBHeader, int fileSize){
80+ // Set the headers to 0
81+ memset (bitmapFileHeader, (unsigned char )(0 ), BITMAP_FILE_HEADER_SIZE);
82+ memset (bitmapDIBHeader, (unsigned char )(0 ), DIB_HEADER_SIZE);
9183
92- // Write the headers info
9384 // File header
9485 bitmapFileHeader[0 ] = ' B' ;
9586 bitmapFileHeader[1 ] = ' M' ;
9687 bitmapFileHeader[2 ] = (unsigned char )(fileSize);
9788 bitmapFileHeader[3 ] = (unsigned char )(fileSize >> 8 );
9889 bitmapFileHeader[4 ] = (unsigned char )(fileSize >> 16 );
9990 bitmapFileHeader[5 ] = (unsigned char )(fileSize >> 24 );
100- bitmapFileHeader[10 ] = (unsigned char )HEADER_FULL_SIZE + PALETTE_SIZE;
91+ bitmapFileHeader[10 ] = (unsigned char )HEADER_SIZE + PALETTE_SIZE;
10192
10293 // Info header
103- bitmapDIBHeader[0 ] = (unsigned char )(HEADER_DIB_SIZE);
104- bitmapDIBHeader[4 ] = (unsigned char )(RES_W);
105- bitmapDIBHeader[5 ] = (unsigned char )(RES_W >> 8 );
106- bitmapDIBHeader[8 ] = (unsigned char )(RES_H);
107- bitmapDIBHeader[8 ] = (unsigned char )(RES_H >> 8 );
108- bitmapDIBHeader[14 ] = (unsigned char )(IMAGE_BPP);
109-
110- // Color palette for grayscale Bitmaps (8bpp)
111- for (int i = 0 ; i < (2 ^ IMAGE_BPP); i++)
112- {
94+ bitmapDIBHeader[0 ] = (unsigned char )(DIB_HEADER_SIZE);
95+ bitmapDIBHeader[4 ] = (unsigned char )(IMAGE_WIDTH);
96+ bitmapDIBHeader[5 ] = (unsigned char )(IMAGE_WIDTH >> 8 );
97+ bitmapDIBHeader[8 ] = (unsigned char )(IMAGE_HEIGHT);
98+ bitmapDIBHeader[9 ] = (unsigned char )(IMAGE_HEIGHT >> 8 );
99+ bitmapDIBHeader[14 ] = (unsigned char )(BITS_PER_PIXEL);
100+ }
101+
102+ void setColorMap (unsigned char *colorMap){
103+ // Init the palette with zeroes
104+ memset (colorMap, (unsigned char )(0 ), PALETTE_SIZE);
105+
106+ // Gray scale color palette, 4 bytes per color (R, G, B, 0x00)
107+ for (int i = 0 ; i < PALETTE_COLORS_AMOUNT; i++) {
113108 colorMap[i * 4 ] = i;
114109 colorMap[i * 4 + 1 ] = i;
115110 colorMap[i * 4 + 2 ] = i;
116111 }
112+ }
113+
114+ // Save the headers and the image data into the .bmp file
115+ void saveImage (unsigned char *imageData, const char * imagePath){
116+ int fileSize = BITMAP_FILE_HEADER_SIZE + DIB_HEADER_SIZE + IMAGE_WIDTH * IMAGE_HEIGHT;
117+ FILE *file = fopen (imagePath, " w" );
117118
118- // Write theh bitmap file
119- fwrite (bitmapFileHeader, 1 , HEADER_FILE_HEADER, file);
120- fwrite (bitmapDIBHeader, 1 , HEADER_DIB_SIZE, file);
121- fwrite (colorMap, 1 , PALETTE_SIZE, file); // Color map
122- fwrite (imgData, 1 , RES_H * RES_W, file);
119+ // Bitmap structure (Head + DIB Head + ColorMap + binary image)
120+ unsigned char bitmapFileHeader[BITMAP_FILE_HEADER_SIZE];
121+ unsigned char bitmapDIBHeader[DIB_HEADER_SIZE];
122+ unsigned char colorMap[PALETTE_SIZE]; // Needed for <= 8bpp grayscale bitmaps
123+
124+ setFileHeaders (bitmapFileHeader, bitmapDIBHeader, fileSize);
125+ setColorMap (colorMap);
126+
127+ // Write the bitmap file
128+ fwrite (bitmapFileHeader, 1 , BITMAP_FILE_HEADER_SIZE, file);
129+ fwrite (bitmapDIBHeader, 1 , DIB_HEADER_SIZE, file);
130+ fwrite (colorMap, 1 , PALETTE_SIZE, file);
131+ fwrite (imageData, 1 , IMAGE_HEIGHT * IMAGE_WIDTH, file);
123132
124- // Close the stream (bitmap file)
133+ // Close the file stream
125134 fclose (file);
135+ }
136+
137+ void countDownBlink (){
138+ for (int i = 0 ; i < 6 ; i++){
139+ digitalWrite (LEDG, i % 2 );
140+ delay (500 );
141+ }
142+ digitalWrite (LEDG, HIGH);
143+ digitalWrite (LEDB, LOW);
126144}
0 commit comments