소스 검색

Write YUV frames to jpeg directly instead of DNG

Martijn Braam 4 달 전
부모
커밋
dbacf8a005
3개의 변경된 파일110개의 추가작업 그리고 2개의 파일을 삭제
  1. 5 0
      CMakeLists.txt
  2. 2 1
      meson.build
  3. 103 1
      src/process_pipeline.c

+ 5 - 0
CMakeLists.txt

@@ -15,6 +15,7 @@ PKG_CHECK_MODULES(DNG REQUIRED libdng)
 PKG_CHECK_MODULES(XLIB REQUIRED x11)
 PKG_CHECK_MODULES(XRANDR REQUIRED xrandr)
 PKG_CHECK_MODULES(WAYLAND REQUIRED wayland-client)
+PKG_CHECK_MODULES(JPEG REQUIRED libjpeg)
 
 # Setup CMake to use GTK+, tell the compiler where to look for headers
 # and to the linker where to look for libraries
@@ -28,6 +29,7 @@ INCLUDE_DIRECTORIES(
         ${XLIB_INCLUDE_DIRS}
         ${XRANDR_INCLUDE_DIRS}
         ${WAYLAND_INCLUDE_DIRS}
+        ${JPEG_INCLUDE_DIRS}
 )
 LINK_DIRECTORIES(
         ${GTK4_LIBRARY_DIRS}
@@ -39,6 +41,7 @@ LINK_DIRECTORIES(
         ${XLIB_LIBRARY_DIRS}
         ${XRANDR_LIBRARY_DIRS}
         ${WAYLAND_LIBRARY_DIRS}
+        ${JPEG_DIRS}
 )
 
 # Add other flags to the compiler
@@ -52,6 +55,7 @@ ADD_DEFINITIONS(
         ${XLIB_CFLAGS_OTHER}
         ${XRANDR_CFLAGS_OTHER}
         ${WAYLAND_CFLAGS_OTHER}
+        ${JPEG_OTHER}
 )
 
 find_program(GLIB_COMPILE_RESOURCES NAMES glib-compile-resources REQUIRED)
@@ -93,6 +97,7 @@ target_link_libraries(megapixels-gtk
         ${XLIB_LIBRARIES}
         ${XRANDR_LIBRARIES}
         ${WAYLAND_LIBRARIES}
+        ${JPEG_LIBRARIES}
         )
 
 add_compile_definitions(VERSION="${PROJECT_VERSION}")

+ 2 - 1
meson.build

@@ -4,6 +4,7 @@ gnome = import('gnome')
 gtkdep = dependency('gtk4')
 libfeedback = dependency('libfeedback-0.0')
 zbar = dependency('zbar')
+jpeg = dependency('libjpeg')
 threads = dependency('threads')
 # gl = dependency('gl')
 epoxy      = dependency('epoxy')
@@ -63,7 +64,7 @@ executable('megapixels',
   'src/dcp.c',
   resources,
   include_directories: 'src/',
-  dependencies: [gtkdep, libfeedback, libm, zbar, threads, epoxy, libmp, libdng] + optdeps,
+  dependencies: [gtkdep, libfeedback, libm, zbar, threads, epoxy, libmp, libdng, jpeg] + optdeps,
   install: true,
   link_args: '-Wl,-ldl')
 

+ 103 - 1
src/process_pipeline.c

@@ -16,6 +16,7 @@
 #include "dcp.h"
 #include "gl_util.h"
 #include "libdng.h"
+#include <jpeglib.h>
 #include <sys/mman.h>
 #include <sys/prctl.h>
 
@@ -481,7 +482,92 @@ process_image_for_preview(const uint8_t *image)
 }
 
 static void
-process_image_for_capture(const uint8_t *image, int count)
+process_image_for_capture_yuv(const uint8_t *image, int count)
+{
+        char fname[255];
+        sprintf(fname, "%s/%d.jpg", burst_dir, count);
+        FILE *outfile;
+        if ((outfile = fopen(fname, "wb")) == NULL) {
+                g_printerr("jpeg open %s: error %d, %s\n",
+                           fname,
+                           errno,
+                           strerror(errno));
+                return;
+        }
+        int width = state_proc.mode->width;
+
+        struct jpeg_compress_struct cinfo;
+        struct jpeg_error_mgr jerr;
+
+        cinfo.err = jpeg_std_error(&jerr);
+        jpeg_create_compress(&cinfo);
+        jpeg_stdio_dest(&cinfo, outfile);
+
+        cinfo.image_width = state_proc.mode->width & -1;
+        cinfo.image_height = state_proc.mode->height & -1;
+        cinfo.input_components = 3;
+        cinfo.in_color_space = JCS_YCbCr;
+        jpeg_set_defaults(&cinfo);
+        jpeg_set_quality(&cinfo, 92, TRUE);
+        jpeg_start_compress(&cinfo, TRUE);
+        uint8_t *row = malloc(width * 3);
+        JSAMPROW row_pointer[1];
+        row_pointer[0] = row;
+
+        unsigned int y1 = 0;
+        unsigned int u = 1;
+        unsigned int y2 = 2;
+        unsigned int v = 3;
+
+        switch (state_proc.mode->v4l_pixfmt) {
+        case V4L2_PIX_FMT_UYVY:
+                u = 0;
+                y1 = 1;
+                v = 2;
+                y2 = 3;
+                break;
+        case V4L2_PIX_FMT_YUYV:
+                y1 = 0;
+                u = 1;
+                y2 = 2;
+                v = 3;
+                break;
+        case V4L2_PIX_FMT_YVYU:
+                y1 = 0;
+                v = 1;
+                y2 = 2;
+                u = 3;
+                break;
+        case V4L2_PIX_FMT_VYUY:
+                v = 0;
+                y1 = 1;
+                u = 2;
+                y2 = 3;
+                break;
+        }
+
+        while (cinfo.next_scanline < cinfo.image_height) {
+                unsigned int i, j = 0;
+                unsigned int offset = cinfo.next_scanline * cinfo.image_width * 2;
+                for (i = 0; i < cinfo.image_width * 2; i += 4) {
+                        row[j + 0] = image[offset + i + y1];
+                        row[j + 1] = image[offset + i + u];
+                        row[j + 2] = image[offset + i + v];
+                        row[j + 3] = image[offset + i + y2];
+                        row[j + 4] = image[offset + i + u];
+                        row[j + 5] = image[offset + i + v];
+                        j += 6;
+                }
+                jpeg_write_scanlines(&cinfo, row_pointer, 1);
+        }
+
+        jpeg_finish_compress(&cinfo);
+        fclose(outfile);
+        jpeg_destroy_compress(&cinfo);
+}
+
+static void
+process_image_for_capture_bayer(const uint8_t *image, int count)
 {
         char fname[255];
         sprintf(fname, "%s/%d.dng", burst_dir, count);
@@ -580,6 +666,22 @@ process_image_for_capture(const uint8_t *image, int count)
          */
 }
 
+static void
+process_image_for_capture(const uint8_t *image, int count)
+{
+        switch (state_proc.mode->v4l_pixfmt) {
+        case V4L2_PIX_FMT_UYVY:
+        case V4L2_PIX_FMT_YUYV:
+        case V4L2_PIX_FMT_YVYU:
+        case V4L2_PIX_FMT_VYUY:
+                process_image_for_capture_yuv(image, count);
+                break;
+        default:
+                process_image_for_capture_bayer(image, count);
+                break;
+        }
+}
+
 static void
 post_process_finished(GSubprocess *proc, GAsyncResult *res, GdkTexture *thumb)
 {