Skip to content

Commit d991016

Browse files
committed
config: light mode and special effect
1 parent 5c42f60 commit d991016

File tree

3 files changed

+90
-37
lines changed

3 files changed

+90
-37
lines changed

examples/AsyncCam/handlers.cpp

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ static const char FRONTPAGE[] = R"EOT(
77
<body>
88
<h1>esp32cam AsyncCam example</h1>
99
<form id="update"><p>
10-
<select name="resolution" required>%resolution%</select>
10+
<select name="resolution">%resolution%</select>
1111
%brightness%
1212
%contrast%
1313
%saturation%
14+
<select name="lightMode" title="light mode">%lightMode%</select>
15+
<select name="specialEffect" title="special effect">%specialEffect%</select>
1416
%hmirror%
1517
%vflip%
1618
<input type="submit" value="update">
@@ -38,7 +40,7 @@ const $display = document.querySelector("#display");
3840
try {
3941
await fetchText("/update.cgi", {
4042
method: "POST",
41-
body: new URLSearchParams(new FormData($update)),
43+
body: new FormData($update),
4244
});
4345
} catch (err) {
4446
$display.textContent = err.toString();
@@ -79,30 +81,52 @@ rewriteFrontpage(const esp32cam::Settings& s, const String& var) {
7981
b.print(r);
8082
b.print("</option>");
8183
}
84+
} else if (var == "lightMode") {
85+
#define SHOW_LM(MODE, SYMBOL) \
86+
b.printf("<option value=\"%d\" title=\"%s\"%s>%s</option>", \
87+
static_cast<int>(esp32cam::LightMode::MODE), #MODE, \
88+
s.lightMode == esp32cam::LightMode::MODE ? " selected" : "", SYMBOL)
89+
SHOW_LM(AUTO, "&#x2B55;");
90+
SHOW_LM(SUNNY, "&#x2600;&#xFE0F;");
91+
SHOW_LM(CLOUDY, "&#x2601;&#xFE0F;");
92+
SHOW_LM(OFFICE, "&#x1F3E2;");
93+
SHOW_LM(HOME, "&#x1F3E0;");
94+
#undef SHOW_LM
95+
} else if (var == "specialEffect") {
96+
#define SHOW_SE(MODE, SYMBOL) \
97+
b.printf("<option value=\"%d\" title=\"%s\"%s>%s</option>", \
98+
static_cast<int>(esp32cam::SpecialEffect::MODE), #MODE, \
99+
s.specialEffect == esp32cam::SpecialEffect::MODE ? " selected" : "", SYMBOL)
100+
SHOW_SE(NONE, "&#x1F6AB;");
101+
SHOW_SE(NEGATIVE, "&#x2B1C;");
102+
SHOW_SE(BLACKWHITE, "&#x2B1B;");
103+
SHOW_SE(REDDISH, "&#x1F7E5;");
104+
SHOW_SE(GREENISH, "&#x1F7E9;");
105+
SHOW_SE(BLUISH, "&#x1F7E6;");
106+
SHOW_SE(ANTIQUE, "&#x1F5BC;&#xFE0F;");
107+
#undef SHOW_SE
82108
}
83109

84-
#define SETTING_INT(MEM, MIN, MAX) \
110+
#define SHOW_INT(MEM, MIN, MAX) \
85111
else if (var == #MEM) { \
86112
b.printf("<label>" #MEM "=<input type=\"number\" name=\"" #MEM \
87113
"\" value=\"%d\" min=\"%d\" max=\"%d\"></label>", \
88114
s.MEM, MIN, MAX); \
89115
}
90116

91-
#define SETTING_BOOL(MEM) \
117+
#define SHOW_BOOL(MEM) \
92118
else if (var == #MEM) { \
93119
b.printf("<label><input type=\"checkbox\" name=\"" #MEM "\" value=\"1\"%s>" #MEM "</label>", \
94120
s.MEM ? " checked" : ""); \
95121
}
96122

97-
SETTING_INT(brightness, -2, 2)
98-
SETTING_INT(contrast, -2, 2)
99-
SETTING_INT(saturation, -2, 2)
100-
SETTING_BOOL(hmirror)
101-
SETTING_BOOL(vflip)
102-
103-
#undef SETTING_INT
104-
#undef SETTING_BOOL
105-
123+
SHOW_INT(brightness, -2, 2)
124+
SHOW_INT(contrast, -2, 2)
125+
SHOW_INT(saturation, -2, 2)
126+
SHOW_BOOL(hmirror)
127+
SHOW_BOOL(vflip)
128+
#undef SHOW_INT
129+
#undef SHOW_BOOL
106130
return b;
107131
}
108132

@@ -116,22 +140,18 @@ handleFrontpage(AsyncWebServerRequest* req) {
116140
static void
117141
handleUpdate(AsyncWebServerRequest* req) {
118142
bool ok = esp32cam::Camera.update([=](esp32cam::Settings& s) {
119-
#define UPDATE(MEM) \
120-
do { \
121-
if constexpr (std::is_same_v<decltype(s.MEM), bool>) { \
122-
s.MEM = req->hasArg(#MEM); \
123-
} else { \
124-
s.MEM = static_cast<decltype(s.MEM)>(req->arg(#MEM).toInt()); \
125-
} \
126-
} while (false)
127-
s.resolution = esp32cam::Resolution(static_cast<int>(req->arg("resolution").toInt()));
128-
UPDATE(brightness);
129-
UPDATE(contrast);
130-
UPDATE(saturation);
131-
UPDATE(hmirror);
132-
UPDATE(vflip);
133-
134-
#undef UPDATE
143+
#define SAVE_BOOL(MEM) s.MEM = req->hasArg(#MEM)
144+
#define SAVE_INT(MEM) s.MEM = decltype(s.MEM)(req->arg(#MEM).toInt())
145+
SAVE_INT(resolution);
146+
SAVE_INT(brightness);
147+
SAVE_INT(contrast);
148+
SAVE_INT(saturation);
149+
SAVE_INT(lightMode);
150+
SAVE_INT(specialEffect);
151+
SAVE_BOOL(hmirror);
152+
SAVE_BOOL(vflip);
153+
#undef SAVE_BOOL
154+
#undef SAVE_INT
135155
});
136156

137157
if (!ok) {

src/esp32cam/config.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ CameraClass::status() const {
104104
result.brightness = sensor->status.brightness;
105105
result.contrast = sensor->status.contrast;
106106
result.saturation = sensor->status.saturation;
107+
result.lightMode = static_cast<LightMode>(sensor->status.wb_mode);
108+
result.specialEffect = static_cast<SpecialEffect>(sensor->status.special_effect);
107109
result.hmirror = sensor->status.hmirror != 0;
108110
result.vflip = sensor->status.vflip != 0;
109111
return result;
@@ -118,20 +120,21 @@ CameraClass::update(const Settings& settings, int sleepFor) {
118120

119121
#define CHECK_RANGE(MEM, MIN, MAX) \
120122
do { \
121-
if (!(settings.MEM >= MIN && settings.MEM <= MAX)) { \
122-
ESP32CAM_LOG("update " #MEM " %d out of range [%d,%d]", static_cast<int>(settings.MEM), MIN, \
123-
MAX); \
123+
int next = static_cast<int>(settings.MEM); \
124+
if (!(next >= MIN && next <= MAX)) { \
125+
ESP32CAM_LOG("update " #MEM " %d out of range [%d,%d]", next, MIN, MAX); \
124126
return false; \
125127
} \
126128
} while (false)
127129

128130
#define UPDATE(STATUS_MEM, SETTING_MEM, SETTER_TYP) \
129131
do { \
130-
auto prev = sensor->status.STATUS_MEM; \
131-
if (prev != static_cast<decltype(prev)>(settings.SETTING_MEM)) { \
132-
int res = sensor->set_##STATUS_MEM(sensor, static_cast<SETTER_TYP>(settings.SETTING_MEM)); \
133-
ESP32CAM_LOG("update " #STATUS_MEM " %d => %d %s", static_cast<int>(prev), \
134-
static_cast<int>(settings.SETTING_MEM), res == 0 ? "success" : "failure"); \
132+
int prev = static_cast<int>(sensor->status.STATUS_MEM); \
133+
int next = static_cast<int>(settings.SETTING_MEM); \
134+
if (prev != static_cast<int>(settings.SETTING_MEM)) { \
135+
int res = sensor->set_##STATUS_MEM(sensor, static_cast<SETTER_TYP>(next)); \
136+
ESP32CAM_LOG("update " #STATUS_MEM " %d => %d %s", prev, next, \
137+
res == 0 ? "success" : "failure"); \
135138
if (res != 0) { \
136139
return false; \
137140
} \
@@ -142,11 +145,15 @@ CameraClass::update(const Settings& settings, int sleepFor) {
142145
CHECK_RANGE(brightness, -2, 2);
143146
CHECK_RANGE(contrast, -2, 2);
144147
CHECK_RANGE(saturation, -2, 2);
148+
CHECK_RANGE(lightMode, 0, 4);
149+
CHECK_RANGE(specialEffect, 0, 6);
145150

146151
UPDATE(framesize, resolution.as<framesize_t>(), framesize_t);
147152
UPDATE1(brightness);
148153
UPDATE1(contrast);
149154
UPDATE1(saturation);
155+
UPDATE(wb_mode, lightMode, int);
156+
UPDATE(special_effect, specialEffect, int);
150157
UPDATE1(hmirror);
151158
UPDATE1(vflip);
152159

src/esp32cam/config.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,26 @@ class Config {
5252
friend class CameraClass;
5353
};
5454

55+
/** @brief Light mode / white balance values. */
56+
enum class LightMode {
57+
AUTO = 0,
58+
SUNNY = 1,
59+
CLOUDY = 2,
60+
OFFICE = 3,
61+
HOME = 4,
62+
};
63+
64+
/** @brief Special effect values. */
65+
enum class SpecialEffect {
66+
NONE = 0,
67+
NEGATIVE = 1,
68+
BLACKWHITE = 2,
69+
REDDISH = 3,
70+
GREENISH = 4,
71+
BLUISH = 5,
72+
ANTIQUE = 6,
73+
};
74+
5575
/** @brief Camera runtime settings. */
5676
struct Settings {
5777
/** @brief Picture resolution. */
@@ -66,6 +86,12 @@ struct Settings {
6686
/** @brief Image saturation, between -2 and +2. */
6787
int8_t saturation;
6888

89+
/** @brief Image light mode. */
90+
LightMode lightMode;
91+
92+
/** @brief Image special effect. */
93+
SpecialEffect specialEffect;
94+
6995
/** @brief Horizontal flip. */
7096
bool hmirror = false;
7197

0 commit comments

Comments
 (0)