Skip to content

Commit 0e9b96b

Browse files
authored
Merge pull request #28 from arduino-libraries/marqdevx/vision-shield/bitmap-SD
Portenta Vision Shield, bitmap to SD Card update sketch
2 parents cddb73e + 8dcd04d commit 0e9b96b

File tree

2 files changed

+99
-81
lines changed

2 files changed

+99
-81
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,126 +1,144 @@
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
33
SDMMCBlockDevice blockDevice;
44
mbed::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
88
HM01B0 himax;
99
Camera 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
}

Diff for: library.properties

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
name=Arduino_Pro_Tutorials
2-
version=1.0.5
2+
version=1.0.6
33
author=Martino Facchin, Riccardo Ricco, Dario Pennisi, Sebastian Romero, Lenard George, Ignacio Herrera, Jose García, Pablo Marquínez
44
maintainer=Arduino <[email protected]>
55
sentence=This library contains the complete Arduino sketches from the Pro Tutorials.
66
paragraph=Instructions on how to use these sketches can be found on the Arduino Pro website under Documentation->Tutorials.
77
category=Other
8-
url=https://www.arduino.cc/pro/tutorials/portenta-h7
9-
architectures=mbed,mbed_portenta
8+
url=https://docs.arduino.cc/#pro-family
9+
architectures=mbed,mbed_portenta,mbed_nicla,mbed_edge
1010
precompiled=false
1111
depends=lvgl

0 commit comments

Comments
 (0)