summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2025-02-19 18:55:55 -0500
committerpommicket <pommicket@gmail.com>2025-02-19 18:55:55 -0500
commit0ab2c540d442997360830fb1ab76284c318c28ca (patch)
tree3916d91d269192db9b4ea68a594116fd38e0bebc
parent0b2293a1b44748e494d9db2ae72c72a16b693a9d (diff)
flash effects
-rw-r--r--camera.c16
-rw-r--r--camera.h4
-rw-r--r--main.c49
-rw-r--r--meson.build10
4 files changed, 51 insertions, 28 deletions
diff --git a/camera.c b/camera.c
index f064073..e82c29a 100644
--- a/camera.c
+++ b/camera.c
@@ -298,16 +298,24 @@ static uint8_t *camera_curr_frame(Camera *camera) {
assert(camera->userp_frames[camera->curr_frame_idx]);
return camera->userp_frames[camera->curr_frame_idx];
}
-void camera_save_jpg(Camera *camera, const char *name, int quality) {
+bool camera_save_jpg(Camera *camera, const char *name, int quality) {
uint8_t *frame = camera_curr_frame(camera);
if (frame) {
- stbi_write_jpg(name, camera_frame_width(camera), camera_frame_height(camera), 3, frame, quality);
+ uint32_t frame_width = camera_frame_width(camera);
+ uint32_t frame_height = camera_frame_height(camera);
+ return stbi_write_jpg(name, frame_width, frame_height, 3, frame, quality) != 0;
+ } else {
+ return false;
}
}
-void camera_save_png(Camera *camera, const char *name) {
+bool camera_save_png(Camera *camera, const char *name) {
uint8_t *frame = camera_curr_frame(camera);
if (frame) {
- stbi_write_png(name, camera_frame_width(camera), camera_frame_height(camera), 3, frame, camera_frame_width(camera) * 3);
+ uint32_t frame_width = camera_frame_width(camera);
+ uint32_t frame_height = camera_frame_height(camera);
+ return stbi_write_png(name, frame_width, frame_height, 3, frame, frame_width * 3) != 0;
+ } else {
+ return false;
}
}
bool camera_next_frame(Camera *camera) {
diff --git a/camera.h b/camera.h
index 4888729..5fe1c4d 100644
--- a/camera.h
+++ b/camera.h
@@ -103,8 +103,8 @@ PictureFormat camera_closest_resolution(Camera *camera, uint32_t pixfmt, int32_t
int32_t camera_frame_width(Camera *camera);
int32_t camera_frame_height(Camera *camera);
PictureFormat camera_picture_format(Camera *camera);
-void camera_save_jpg(Camera *camera, const char *path, int quality);
-void camera_save_png(Camera *camera, const char *path);
+bool camera_save_jpg(Camera *camera, const char *path, int quality);
+bool camera_save_png(Camera *camera, const char *path);
bool camera_next_frame(Camera *camera);
void camera_update_gl_textures(Camera *camera, const GLuint textures[3]);
const char *camera_name(Camera *camera);
diff --git a/main.c b/main.c
index 6e7b58d..52ecdd6 100644
--- a/main.c
+++ b/main.c
@@ -1,8 +1,6 @@
/*
TODO
--set saved image format
-add support for more pixfmts
--screen effect when picture is taken
-view previous pictures (thumbnails)
-click in menus
-left/right in resolution menu
@@ -381,6 +379,7 @@ void main() {\n\
in vec2 tex_coord;\n\
uniform sampler2D u_sampler;\n\
uniform int u_pixel_format;\n\
+uniform float u_flash;\n\
uniform float u_opacity;\n\
void main() {\n\
vec3 color;\n\
@@ -396,7 +395,7 @@ void main() {\n\
color = texture2D(u_sampler, tex_coord).xyz;\n\
break;\n\
}\n\
- gl_FragColor = vec4(color, opacity);\n\
+ gl_FragColor = vec4(mix(color, vec3(1.0), u_flash), opacity);\n\
}\n\
";
char err[256] = {0};
@@ -410,6 +409,7 @@ void main() {\n\
gl.GenVertexArrays(1, &vao);
const GLuint u_sampler = gl.GetUniformLocation(program, "u_sampler");
const GLuint u_offset = gl.GetUniformLocation(program, "u_offset");
+ const GLuint u_flash = gl.GetUniformLocation(program, "u_flash");
const GLuint u_pixel_format = gl.GetUniformLocation(program, "u_pixel_format");
const GLuint u_scale = gl.GetUniformLocation(program, "u_scale");
const GLuint u_opacity = gl.GetUniformLocation(program, "u_opacity");
@@ -508,6 +508,7 @@ void main() {\n\
if (!camera_open(state->camera))
return EXIT_FAILURE;
}
+ double flash_time = INFINITY;
while(true) {
struct udev_device *dev = NULL;
while (udev_monitor && (dev = udev_monitor_receive_device(udev_monitor))) {
@@ -525,24 +526,29 @@ void main() {\n\
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) goto quit;
if (event.type == SDL_KEYDOWN) switch (event.key.keysym.sym) {
- case SDLK_SPACE: {
- time_t t = time(NULL);
- struct tm *tm = localtime(&t);
- static char name[64];
- strftime(name, sizeof name, "%Y-%m-%d-%H-%M-%S", tm);
- sprintf(name + strlen(name), ".%s", image_format_extensions[state->image_format]);
- switch (state->image_format) {
- case IMG_FMT_JPEG:
- camera_save_jpg(state->camera, name, 90);
- break;
- case IMG_FMT_PNG:
- camera_save_png(state->camera, name);
- break;
- case IMG_FMT_COUNT:
- assert(false);
- break;
+ case SDLK_SPACE:
+ if (state->camera) {
+ time_t t = time(NULL);
+ struct tm *tm = localtime(&t);
+ static char name[64];
+ strftime(name, sizeof name, "%Y-%m-%d-%H-%M-%S", tm);
+ sprintf(name + strlen(name), ".%s", image_format_extensions[state->image_format]);
+ bool success = false;
+ switch (state->image_format) {
+ case IMG_FMT_JPEG:
+ success = camera_save_jpg(state->camera, name, 90);
+ break;
+ case IMG_FMT_PNG:
+ success = camera_save_png(state->camera, name);
+ break;
+ case IMG_FMT_COUNT:
+ assert(false);
+ break;
+ }
+ if (success)
+ flash_time = 0;
}
- } break;
+ break;
case SDLK_ESCAPE:
if (state->curr_menu == MENU_NONE) {
state->curr_menu = MENU_MAIN;
@@ -779,6 +785,7 @@ void main() {\n\
clock_gettime(CLOCK_MONOTONIC, &ts);
double curr_time = (double)ts.tv_sec + (double)ts.tv_nsec * 1e-9;
double frame_time = curr_time - last_time;
+ flash_time += frame_time;
last_time = curr_time;
gl.UseProgram(program);
@@ -824,7 +831,9 @@ void main() {\n\
gl.Disable(GL_BLEND);
gl.BindBuffer(GL_ARRAY_BUFFER, vbo);
gl.BindVertexArray(vao);
+ gl.Uniform1f(u_flash, expf(-flash_time * 3));
gl.DrawArrays(GL_TRIANGLES, 0, 6);
+ gl.Uniform1f(u_flash, 0);
if (state->curr_menu) {
gl.Enable(GL_BLEND);
gl.ActiveTexture(GL_TEXTURE0);
diff --git a/meson.build b/meson.build
index b4acbd6..7d721bf 100644
--- a/meson.build
+++ b/meson.build
@@ -4,7 +4,7 @@ project('camlet',
'warning_level=3',
]
)
-
+cc = meson.get_compiler('c')
v4l2 = dependency('libv4l2')
sdl2 = dependency('SDL2')
sdl2_ttf = dependency('SDL2_ttf')
@@ -12,9 +12,15 @@ udev = dependency('libudev')
gl = dependency('GL')
sodium = dependency('libsodium')
fontconfig = dependency('fontconfig')
+m_dep = cc.find_library('m', required: false)
+if m_dep.found()
+ add_project_link_arguments('-lm', language: 'c')
+endif
if get_option('debug')
debug_def = '-DDEBUG=1'
else
debug_def = '-DDEBUG=0'
endif
-executable('camlet', 'main.c', 'camera.c', '3rd_party/stb_image_write.c', dependencies: [v4l2, sdl2, sdl2_ttf, gl, udev, sodium, fontconfig], c_args: ['-Wno-unused-function', '-Wno-format-truncation', '-Wshadow', debug_def])
+executable('camlet', 'main.c', 'camera.c', '3rd_party/stb_image_write.c',
+ dependencies: [v4l2, sdl2, sdl2_ttf, gl, udev, sodium, fontconfig],
+ c_args: ['-Wno-unused-function', '-Wno-format-truncation', '-Wshadow', debug_def])