|
@@ -481,24 +481,51 @@ process_image_for_preview(const uint8_t *image)
|
|
|
static void
|
|
|
process_image_for_capture(const uint8_t *image, int count)
|
|
|
{
|
|
|
- time_t rawtime;
|
|
|
- time(&rawtime);
|
|
|
- struct tm tim = *(localtime(&rawtime));
|
|
|
-
|
|
|
- char datetime[20] = { 0 };
|
|
|
- strftime(datetime, 20, "%Y:%m:%d %H:%M:%S", &tim);
|
|
|
-
|
|
|
char fname[255];
|
|
|
sprintf(fname, "%s/%d.dng", burst_dir, count);
|
|
|
|
|
|
+ uint16_t orientation;
|
|
|
+ if (state_proc.device_rotation == 0) {
|
|
|
+ orientation = state_proc.mode->mirrored ?
|
|
|
+ LIBDNG_ORIENTATION_TOPRIGHT :
|
|
|
+ LIBDNG_ORIENTATION_TOPLEFT;
|
|
|
+ } else if (state_proc.device_rotation == 90) {
|
|
|
+ orientation = state_proc.mode->mirrored ?
|
|
|
+ LIBDNG_ORIENTATION_RIGHTBOT :
|
|
|
+ LIBDNG_ORIENTATION_LEFTBOT;
|
|
|
+ } else if (state_proc.device_rotation == 180) {
|
|
|
+ orientation = state_proc.mode->mirrored ?
|
|
|
+ LIBDNG_ORIENTATION_BOTLEFT :
|
|
|
+ LIBDNG_ORIENTATION_BOTRIGHT;
|
|
|
+ } else {
|
|
|
+ orientation = state_proc.mode->mirrored ?
|
|
|
+ LIBDNG_ORIENTATION_LEFTTOP :
|
|
|
+ LIBDNG_ORIENTATION_RIGHTTOP;
|
|
|
+ }
|
|
|
+
|
|
|
libdng_info dng = { 0 };
|
|
|
libdng_new(&dng);
|
|
|
|
|
|
+ libdng_set_datetime_now(&dng);
|
|
|
libdng_set_mode_from_pixfmt(&dng, state_proc.mode->v4l_pixfmt);
|
|
|
libdng_set_make_model(&dng,
|
|
|
state_proc.configuration->make,
|
|
|
state_proc.configuration->model);
|
|
|
+ libdng_set_orientation(&dng, orientation);
|
|
|
+ libdng_set_software(&dng, "Megapixels");
|
|
|
+ libdng_set_neutral(&dng, state_proc.red, 1.0f, state_proc.blue);
|
|
|
+ libdng_set_analog_balance(&dng,
|
|
|
+ state_proc.balance[0],
|
|
|
+ state_proc.balance[1],
|
|
|
+ state_proc.balance[2]);
|
|
|
+
|
|
|
+ if (!state_proc.exposure.manual) {
|
|
|
+ libdng_set_exposure_program(&dng, LIBDNG_EXPOSUREPROGRAM_NORMAL);
|
|
|
+ } else {
|
|
|
+ libdng_set_exposure_program(&dng, LIBDNG_EXPOSUREPROGRAM_MANUAL);
|
|
|
+ }
|
|
|
|
|
|
+ printf("Writing frame to %s\n", fname);
|
|
|
libdng_write(&dng,
|
|
|
fname,
|
|
|
state_proc.mode->width,
|
|
@@ -507,84 +534,6 @@ process_image_for_capture(const uint8_t *image, int count)
|
|
|
count);
|
|
|
libdng_free(&dng);
|
|
|
|
|
|
- uint16_t orientation;
|
|
|
- if (state_proc.device_rotation == 0) {
|
|
|
- orientation = state_proc.mode->mirrored ? ORIENTATION_TOPRIGHT :
|
|
|
- ORIENTATION_TOPLEFT;
|
|
|
- } else if (state_proc.device_rotation == 90) {
|
|
|
- orientation = state_proc.mode->mirrored ? ORIENTATION_RIGHTBOT :
|
|
|
- ORIENTATION_LEFTBOT;
|
|
|
- } else if (state_proc.device_rotation == 180) {
|
|
|
- orientation = state_proc.mode->mirrored ? ORIENTATION_BOTLEFT :
|
|
|
- ORIENTATION_BOTRIGHT;
|
|
|
- } else {
|
|
|
- orientation = state_proc.mode->mirrored ? ORIENTATION_LEFTTOP :
|
|
|
- ORIENTATION_RIGHTTOP;
|
|
|
- }
|
|
|
- TIFFSetField(tif, TIFFTAG_ORIENTATION, orientation);
|
|
|
- TIFFSetField(tif, TIFFTAG_DATETIME, datetime);
|
|
|
- TIFFSetField(tif, TIFFTAG_SOFTWARE, "Megapixels");
|
|
|
-
|
|
|
- static float neutral[] = { 1.0f, 1.0f, 1.0f };
|
|
|
- neutral[0] = state_proc.red;
|
|
|
- neutral[2] = state_proc.blue;
|
|
|
- TIFFSetField(tif, TIFFTAG_ASSHOTNEUTRAL, 3, neutral);
|
|
|
- TIFFSetField(tif, TIFFTAG_ANALOGBALANCE, 3, state_proc.balance);
|
|
|
-
|
|
|
- // Write black thumbnail, only windows uses this
|
|
|
- {
|
|
|
- unsigned char *buf = (unsigned char *)calloc(
|
|
|
- 1, (state_proc.mode->width >> 4) * 3);
|
|
|
- for (int row = 0; row < (state_proc.mode->height >> 4); row++) {
|
|
|
- TIFFWriteScanline(tif, buf, row, 0);
|
|
|
- }
|
|
|
- free(buf);
|
|
|
- }
|
|
|
- TIFFWriteDirectory(tif);
|
|
|
-
|
|
|
- printf("TIFF version %d\n", TIFFLIB_VERSION);
|
|
|
- int whitelevel =
|
|
|
- (1 << libmegapixels_format_bits_per_pixel(state_proc.mode->format)) -
|
|
|
- 1;
|
|
|
- TIFFSetField(tif, TIFFTAG_WHITELEVEL, 1, &whitelevel);
|
|
|
- TIFFCheckpointDirectory(tif);
|
|
|
- printf("Writing frame to %s\n", fname);
|
|
|
-
|
|
|
- uint8_t *output_image = (uint8_t *)image;
|
|
|
-
|
|
|
- // Repack 10-bit image from sensor format into a sequencial format
|
|
|
- if (libmegapixels_format_bits_per_pixel(state_proc.mode->format) == 10) {
|
|
|
- output_image = malloc(
|
|
|
- libmegapixels_mode_width_to_bytes(state_proc.mode->format,
|
|
|
- state_proc.mode->width) *
|
|
|
- state_proc.mode->height);
|
|
|
-
|
|
|
- repack_image_sequencial(image, output_image, state_proc.mode);
|
|
|
- }
|
|
|
-
|
|
|
- for (int row = 0; row < state_proc.mode->height; row++) {
|
|
|
- TIFFWriteScanline(tif,
|
|
|
- (void *)output_image +
|
|
|
- (row * libmegapixels_mode_width_to_bytes(
|
|
|
- state_proc.mode->format,
|
|
|
- state_proc.mode->width)),
|
|
|
- row,
|
|
|
- 0);
|
|
|
- }
|
|
|
- TIFFWriteDirectory(tif);
|
|
|
-
|
|
|
- if (output_image != image)
|
|
|
- free(output_image);
|
|
|
-
|
|
|
- // Add an EXIF block to the tiff
|
|
|
- TIFFCreateEXIFDirectory(tif);
|
|
|
- // 1 = manual, 2 = full auto, 3 = aperture priority, 4 = shutter priority
|
|
|
- if (!state_proc.exposure.manual) {
|
|
|
- TIFFSetField(tif, EXIFTAG_EXPOSUREPROGRAM, 2);
|
|
|
- } else {
|
|
|
- TIFFSetField(tif, EXIFTAG_EXPOSUREPROGRAM, 1);
|
|
|
- }
|
|
|
-
|
|
|
/*
|
|
|
TIFFSetField(tif,
|
|
|
EXIFTAG_EXPOSURETIME,
|
|
@@ -610,8 +559,6 @@ process_image_for_capture(const uint8_t *image, int count)
|
|
|
}
|
|
|
*/
|
|
|
|
|
|
- TIFFSetField(tif, EXIFTAG_DATETIMEORIGINAL, datetime);
|
|
|
- TIFFSetField(tif, EXIFTAG_DATETIMEDIGITIZED, datetime);
|
|
|
/*
|
|
|
if (pr_camera->fnumber) {
|
|
|
TIFFSetField(tif, EXIFTAG_FNUMBER, pr_camera->fnumber);
|
|
@@ -626,16 +573,6 @@ process_image_for_capture(const uint8_t *image, int count)
|
|
|
pr_camera->cropfactor));
|
|
|
}
|
|
|
*/
|
|
|
- uint64_t exif_offset = 0;
|
|
|
- TIFFWriteCustomDirectory(tif, &exif_offset);
|
|
|
- TIFFFreeDirectory(tif);
|
|
|
-
|
|
|
- // Update exif pointer
|
|
|
- TIFFSetDirectory(tif, 0);
|
|
|
- TIFFSetField(tif, TIFFTAG_EXIFIFD, exif_offset);
|
|
|
- TIFFRewriteDirectory(tif);
|
|
|
-
|
|
|
- TIFFClose(tif);
|
|
|
}
|
|
|
|
|
|
static void
|