From 33ad437064de04f6bc83815ac6232e094ee7c0fa Mon Sep 17 00:00:00 2001 From: Emmanuel Pacaud Date: Sun, 26 Feb 2023 18:39:33 +0100 Subject: [PATCH 1/6] uvdevice: fix srbm_u3vcp_capability register size It is 8 byte long according to wireshark u3v dissector. Fixes #578 --- src/arvuvdevice.c | 67 +++++++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/src/arvuvdevice.c b/src/arvuvdevice.c index 0cabc4e5b..0e67f5dfe 100644 --- a/src/arvuvdevice.c +++ b/src/arvuvdevice.c @@ -462,7 +462,7 @@ _bootstrap (ArvUvDevice *uv_device) guint64 device_capability; guint32 max_cmd_transfer; guint32 max_ack_transfer; - guint32 u3vcp_capability; + guint64 u3vcp_capability; guint64 sirm_offset; guint32 si_info; guint32 si_control; @@ -493,10 +493,14 @@ _bootstrap (ArvUvDevice *uv_device) manufacturer[63] = 0; arv_info_device ("MANUFACTURER_NAME = '%s'", manufacturer); - success = success && arv_device_read_memory (device, ARV_ABRM_SBRM_ADDRESS, sizeof (guint64), &offset, NULL); - success = success && arv_device_read_memory (device, ARV_ABRM_MAX_DEVICE_RESPONSE_TIME, sizeof (guint32), &response_time, NULL); - success = success && arv_device_read_memory (device, ARV_ABRM_DEVICE_CAPABILITY, sizeof (guint64), &device_capability, NULL); - success = success && arv_device_read_memory (device, ARV_ABRM_MANIFEST_TABLE_ADDRESS, sizeof (guint64), &manifest_table_address, NULL); + success = success && arv_device_read_memory (device, ARV_ABRM_SBRM_ADDRESS, + sizeof (offset), &offset, NULL); + success = success && arv_device_read_memory (device, ARV_ABRM_MAX_DEVICE_RESPONSE_TIME, + sizeof (response_time), &response_time, NULL); + success = success && arv_device_read_memory (device, ARV_ABRM_DEVICE_CAPABILITY, + sizeof (device_capability), &device_capability, NULL); + success = success && arv_device_read_memory (device, ARV_ABRM_MANIFEST_TABLE_ADDRESS, + sizeof (manifest_table_address), &manifest_table_address, NULL); if (!success) { arv_warning_device ("[UvDevice::_bootstrap] Error during memory read"); return FALSE; @@ -509,16 +513,20 @@ _bootstrap (ArvUvDevice *uv_device) priv->timeout_ms = MAX (ARV_UVCP_DEFAULT_RESPONSE_TIME_MS, response_time); - success = success && arv_device_read_memory (device, offset + ARV_SBRM_U3VCP_CAPABILITY, sizeof (guint32), &u3vcp_capability, NULL); - success = success && arv_device_read_memory (device, offset + ARV_SBRM_MAX_CMD_TRANSFER, sizeof (guint32), &max_cmd_transfer, NULL); - success = success && arv_device_read_memory (device, offset + ARV_SBRM_MAX_ACK_TRANSFER, sizeof (guint32), &max_ack_transfer, NULL); - success = success && arv_device_read_memory (device, offset + ARV_SBRM_SIRM_ADDRESS, sizeof (guint64), &sirm_offset, NULL); + success = success && arv_device_read_memory (device, offset + ARV_SBRM_U3VCP_CAPABILITY, + sizeof (u3vcp_capability), &u3vcp_capability, NULL); + success = success && arv_device_read_memory (device, offset + ARV_SBRM_MAX_CMD_TRANSFER, + sizeof (max_cmd_transfer), &max_cmd_transfer, NULL); + success = success && arv_device_read_memory (device, offset + ARV_SBRM_MAX_ACK_TRANSFER, + sizeof (max_ack_transfer), &max_ack_transfer, NULL); + success = success && arv_device_read_memory (device, offset + ARV_SBRM_SIRM_ADDRESS, + sizeof (sirm_offset), &sirm_offset, NULL); if (!success) { arv_warning_device ("[UvDevice::_bootstrap] Error during memory read"); return FALSE; } - arv_info_device ("U3VCP_CAPABILITY = 0x%08x", u3vcp_capability); + arv_info_device ("U3VCP_CAPABILITY = 0x%016" G_GINT64_MODIFIER "x", u3vcp_capability); arv_info_device ("MAX_CMD_TRANSFER = 0x%08x", max_cmd_transfer); arv_info_device ("MAX_ACK_TRANSFER = 0x%08x", max_ack_transfer); arv_info_device ("SIRM_OFFSET = 0x%016" G_GINT64_MODIFIER "x", sirm_offset); @@ -526,17 +534,28 @@ _bootstrap (ArvUvDevice *uv_device) priv->cmd_packet_size_max = MIN (priv->cmd_packet_size_max, max_cmd_transfer); priv->ack_packet_size_max = MIN (priv->ack_packet_size_max, max_ack_transfer); - success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_INFO, sizeof (si_info), &si_info, NULL); - success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_CONTROL, sizeof (si_control), &si_control, NULL); - success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_REQ_PAYLOAD_SIZE, sizeof (si_req_payload_size), &si_req_payload_size, NULL); - success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_REQ_LEADER_SIZE, sizeof (si_req_leader_size), &si_req_leader_size, NULL); - success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_REQ_TRAILER_SIZE, sizeof (si_req_trailer_size), &si_req_trailer_size, NULL); - success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_MAX_LEADER_SIZE, sizeof (si_max_leader_size), &si_max_leader_size, NULL); - success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_PAYLOAD_SIZE, sizeof (si_payload_size), &si_payload_size, NULL); - success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_PAYLOAD_COUNT, sizeof (si_payload_count), &si_payload_count, NULL); - success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_TRANSFER1_SIZE, sizeof (si_transfer1_size), &si_transfer1_size, NULL); - success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_TRANSFER2_SIZE, sizeof (si_transfer2_size), &si_transfer2_size, NULL); - success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_MAX_TRAILER_SIZE, sizeof (si_max_trailer_size), &si_max_trailer_size, NULL); + success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_INFO, + sizeof (si_info), &si_info, NULL); + success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_CONTROL, + sizeof (si_control), &si_control, NULL); + success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_REQ_PAYLOAD_SIZE, + sizeof (si_req_payload_size), &si_req_payload_size, NULL); + success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_REQ_LEADER_SIZE, + sizeof (si_req_leader_size), &si_req_leader_size, NULL); + success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_REQ_TRAILER_SIZE, + sizeof (si_req_trailer_size), &si_req_trailer_size, NULL); + success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_MAX_LEADER_SIZE, + sizeof (si_max_leader_size), &si_max_leader_size, NULL); + success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_PAYLOAD_SIZE, + sizeof (si_payload_size), &si_payload_size, NULL); + success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_PAYLOAD_COUNT, + sizeof (si_payload_count), &si_payload_count, NULL); + success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_TRANSFER1_SIZE, + sizeof (si_transfer1_size), &si_transfer1_size, NULL); + success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_TRANSFER2_SIZE, + sizeof (si_transfer2_size), &si_transfer2_size, NULL); + success = success && arv_device_read_memory (device, sirm_offset + ARV_SIRM_MAX_TRAILER_SIZE, + sizeof (si_max_trailer_size), &si_max_trailer_size, NULL); if (!success) { arv_warning_device ("[UvDevice::_bootstrap] Error during memory read"); return FALSE; @@ -554,8 +573,10 @@ _bootstrap (ArvUvDevice *uv_device) arv_info_device ("SIRM_TRANSFER2_SIZE = 0x%08x", si_transfer2_size); arv_info_device ("SIRM_MAX_TRAILER_SIZE = 0x%08x", si_max_trailer_size); - success = success && arv_device_read_memory (device, manifest_table_address, sizeof (guint64), &manifest_n_entries, NULL); - success = success && arv_device_read_memory (device, manifest_table_address + 0x08, sizeof (entry), &entry, NULL); + success = success && arv_device_read_memory (device, manifest_table_address, + sizeof (manifest_n_entries), &manifest_n_entries, NULL); + success = success && arv_device_read_memory (device, manifest_table_address + 0x08, + sizeof (entry), &entry, NULL); if (!success) { arv_warning_device ("[UvDevice::_bootstrap] Error during memory read"); return FALSE; From a67514c157a62e26d60f1d5fcc30dfcd8e2fb8bf Mon Sep 17 00:00:00 2001 From: Victhor Foster Date: Sun, 21 May 2023 19:25:19 -0300 Subject: [PATCH 2/6] Hack: Added Bayer 16 bit format as grayscale 16 bit --- src/arvmisc.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/arvmisc.c b/src/arvmisc.c index c9a1c5798..a2b8c774e 100644 --- a/src/arvmisc.c +++ b/src/arvmisc.c @@ -720,7 +720,34 @@ ArvGstCapsInfos arv_gst_caps_infos[] = { "video/x-raw-bayer, format=(string)bggr, bpp=(int)8, depth=(int)8", "video/x-raw-bayer", 8, 8, ARV_MAKE_FOURCC ('b','g','g','r') }, - + { + ARV_PIXEL_FORMAT_BAYER_GR_16, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)grbg, bpp=(int)16, depth=(int)16", + "video/x-raw-gray", 16, 16, ARV_MAKE_FOURCC ('g','r','b','g') + }, + { + ARV_PIXEL_FORMAT_BAYER_RG_16, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)rggb, bpp=(int)16, depth=(int)16", + "video/x-raw-gray", 16, 16, ARV_MAKE_FOURCC ('r','g','g','b') + }, + { + ARV_PIXEL_FORMAT_BAYER_GB_16, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)gbrg, bpp=(int)16, depth=(int)16", + "video/x-raw-gray", 16, 16, ARV_MAKE_FOURCC ('g','b','r','g') + }, + { + ARV_PIXEL_FORMAT_BAYER_BG_16, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-gray, format=(string)bggr, bpp=(int)16, depth=(int)16", + "video/x-raw-gray", 16, 16, ARV_MAKE_FOURCC ('b','g','g','r') + }, /* Non 8bit bayer formats are not supported by gstreamer bayer plugin. * This feature is discussed in bug https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/issues/86 .*/ From d0c27f1d2b26a4406a5d051549b4d15e4d3498c5 Mon Sep 17 00:00:00 2001 From: Victhor Foster Date: Sun, 21 May 2023 22:07:48 -0300 Subject: [PATCH 3/6] Added DNG file extension for raw output to file picker dialog --- viewer/arvviewer.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/viewer/arvviewer.c b/viewer/arvviewer.c index 24a9dacb0..c318db39d 100644 --- a/viewer/arvviewer.c +++ b/viewer/arvviewer.c @@ -820,6 +820,7 @@ _save_gst_sample_to_file (GstSample *sample, const char *path, const char *mime_ return success; } + static void snapshot_cb (GtkButton *button, ArvViewer *viewer) { @@ -902,6 +903,12 @@ snapshot_cb (GtkButton *button, ArvViewer *viewer) gtk_file_filter_add_pattern (filter_all, "*.raw"); gtk_file_filter_set_name (filter, "Raw images (*.raw)"); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + filter = gtk_file_filter_new (); + gtk_file_filter_add_mime_type (filter, "image/x-adobe-dng"); + gtk_file_filter_add_mime_type (filter_all, "image/x-adobe-dng"); + gtk_file_filter_set_name (filter, "DNG raw image (*.dng)"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); } gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter_all); @@ -924,7 +931,12 @@ snapshot_cb (GtkButton *button, ArvViewer *viewer) success = _save_gst_sample_to_file (sample, filename, "image/png", NULL); } else if (GST_IS_SAMPLE (sample) && g_content_type_is_mime_type (content_type, "image/jpeg")) { success = _save_gst_sample_to_file (sample, filename, "image/jpeg", NULL); - } else if (ARV_IS_BUFFER (buffer)) { + } else if (ARV_IS_BUFFER (buffer) && g_content_type_is_mime_type (content_type, "image/x-adobe-dng")) { + // TODO: implement DNG support + success = g_file_set_contents (filename, data, size, &error); + g_free (filename); + } else if (ARV_IS_BUFFER (buffer) && g_content_type_is_mime_type (content_type, "image/x-panasonic-rw")) { + // GIO guesses that MIME type for ".raw" files, so this is what we look for when writing unformatted raw files success = g_file_set_contents (filename, data, size, &error); g_free (filename); } From 1a7522f9ffad54869e4048942da30cb1b6980e41 Mon Sep 17 00:00:00 2001 From: Victhor Foster Date: Mon, 22 May 2023 22:11:30 -0300 Subject: [PATCH 4/6] New feature: DNG raw image support (WIP). --- meson.build | 4 +- viewer/arvviewer.c | 178 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 179 insertions(+), 3 deletions(-) diff --git a/meson.build b/meson.build index 0672ed943..61b3b0a70 100644 --- a/meson.build +++ b/meson.build @@ -61,6 +61,7 @@ gobject_dep = dependency ('gobject-2.0', required: true) gio_dep = dependency ('gio-2.0', required: true) xml2_dep = dependency ('libxml-2.0', required: true) libz_dep = dependency ('zlib', required: true) +libtiff_dep = dependency ('libtiff-4', required: true) usb_dep = dependency ('libusb-1.0', required: get_option ('usb')) aravis_public_dependencies = [glib_dep, gobject_dep, gio_dep] @@ -106,7 +107,8 @@ viewer_option = get_option ('viewer') viewer_deps = aravis_dependencies + [dependency ('gtk+-3.0', version: '>=3.12', required: viewer_option), dependency ('gstreamer-base-1.0', required: viewer_option), dependency ('gstreamer-app-1.0', required: viewer_option), - dependency ('gstreamer-video-1.0', required: viewer_option)] + dependency ('gstreamer-video-1.0', required: viewer_option), + dependency ('libtiff-4', required: viewer_option)] subdir ('po', if_found: viewer_deps) subdir ('viewer', if_found: viewer_deps) diff --git a/viewer/arvviewer.c b/viewer/arvviewer.c index c318db39d..d41d0f7f4 100644 --- a/viewer/arvviewer.c +++ b/viewer/arvviewer.c @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef GDK_WINDOWING_X11 #include // for GDK_WINDOW_XID #endif @@ -820,6 +821,180 @@ _save_gst_sample_to_file (GstSample *sample, const char *path, const char *mime_ return success; } +static gboolean +_save_arv_buffer_to_dng_file (ArvBuffer *buffer, GstSample *sample, const char *path, GError **error) +{ + + TIFF *tif; + GstSample *converted = NULL; + GstSample *scaled = NULL; + GstCaps *caps = NULL; + GstBuffer *scaled_buffer; + size_t size; + int width, height, bpp; + char *vendor, *model; + const char *data; + const char *caps_string; + static int white_level; + const static int black_level = 0; + guint32 pixel_format; + GstVideoScaler *h_scale = NULL; + GstVideoScaler *v_scale = NULL; + // TODO: implement camera/sensor specific color conversion matrix + const float cc_matrix[] = { 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 }; + // TODO: implement white balance + const float neutral[] = { 1.0, 1.0, 1.0 }; + const unsigned short cfa_dimensions[] = { 2, 2 }; + const char dng_version[] = { 1, 1, 0, 0 }; + const char dng_compatversion[] = { 1, 0, 0, 0 }; + char cfa_pattern[4]; + static const long sub_offset = 0; + gboolean success = FALSE; + + tif = TIFFOpen (path, "w"); + if (!tif) return FALSE; + + arv_buffer_get_image_region (buffer, NULL, NULL, &width, &height); + data = arv_buffer_get_image_data (buffer, &size); + pixel_format = arv_buffer_get_image_pixel_format (buffer); + + switch (pixel_format) { + case ARV_PIXEL_FORMAT_BAYER_GR_8: + bpp = 8; + cfa_pattern[0] = 1; + cfa_pattern[1] = 0; + cfa_pattern[2] = 2; + cfa_pattern[3] = 1; + break; + case ARV_PIXEL_FORMAT_BAYER_RG_8: + bpp = 8; + cfa_pattern[0] = 0; + cfa_pattern[1] = 1; + cfa_pattern[2] = 1; + cfa_pattern[3] = 2; + break; + case ARV_PIXEL_FORMAT_BAYER_GB_8: + bpp = 8; + cfa_pattern[0] = 1; + cfa_pattern[1] = 2; + cfa_pattern[2] = 0; + cfa_pattern[3] = 1; + break; + case ARV_PIXEL_FORMAT_BAYER_BG_8: + bpp = 8; + cfa_pattern[0] = 2; + cfa_pattern[1] = 1; + cfa_pattern[2] = 1; + cfa_pattern[3] = 0; + break; + case ARV_PIXEL_FORMAT_BAYER_GR_16: + bpp = 16; + cfa_pattern[0] = 1; + cfa_pattern[1] = 0; + cfa_pattern[2] = 2; + cfa_pattern[3] = 1; + break; + case ARV_PIXEL_FORMAT_BAYER_RG_16: + bpp = 16; + cfa_pattern[0] = 0; + cfa_pattern[1] = 1; + cfa_pattern[2] = 1; + cfa_pattern[3] = 2; + break; + case ARV_PIXEL_FORMAT_BAYER_GB_16: + bpp = 16; + cfa_pattern[0] = 1; + cfa_pattern[1] = 2; + cfa_pattern[2] = 0; + cfa_pattern[3] = 1; + break; + case ARV_PIXEL_FORMAT_BAYER_BG_16: + bpp = 16; + cfa_pattern[0] = 2; + cfa_pattern[1] = 1; + cfa_pattern[2] = 1; + cfa_pattern[3] = 0; + break; + default: + bpp = 8; + cfa_pattern[0] = 1; + cfa_pattern[1] = 0; + cfa_pattern[2] = 2; + cfa_pattern[3] = 1; + } + + white_level = pow(2, bpp) - 1; + + caps = gst_caps_from_string ("video/x-raw-gray, bpp=(int)8, depth=(int)8"); + converted = gst_video_convert_sample (sample, caps, GST_CLOCK_TIME_NONE, NULL); + + h_scale = gst_video_scaler_new (GST_VIDEO_RESAMPLER_METHOD_NEAREST, GST_VIDEO_SCALER_FLAG_NONE, 1, 1, 1, NULL); + v_scale = gst_video_scaler_new (GST_VIDEO_RESAMPLER_METHOD_NEAREST, GST_VIDEO_SCALER_FLAG_NONE, 1, 1, 1, NULL); + + gst_video_scaler_2d (h_scale, v_scale, GST_VIDEO_FORMAT_GRAY8, converted, 1, scaled, 1, 0, 0, (width >> 2), (height >> 2)); + + TIFFSetField (tif, TIFFTAG_SUBFILETYPE, 1); // Reduced resolution preview image + TIFFSetField (tif, TIFFTAG_IMAGEWIDTH, (width >> 2)); + TIFFSetField (tif, TIFFTAG_IMAGELENGTH, (height >> 2)); + TIFFSetField (tif, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField (tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); + TIFFSetField (tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); + //TIFFSetField (tif, TIFFTAG_MAKE, vendor); + //TIFFSetField (tif, TIFFTAG_MODEL, model); + TIFFSetField (tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, 1); + TIFFSetField (tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField (tif, TIFFTAG_SOFTWARE, "arv-viewer-0.8"); + //TIFFSetField (tif, TIFFTAG_DATETIME, datetime); + TIFFSetField (tif, TIFFTAG_SUBIFD, 1, &sub_offset); + TIFFSetField (tif, TIFFTAG_DNGVERSION, dng_version); + TIFFSetField (tif, TIFFTAG_DNGBACKWARDVERSION, dng_compatversion); + //TIFFSetField (tif, TIFFTAG_UNIQUECAMERAMODEL, model); + TIFFSetField (tif, TIFFTAG_COLORMATRIX1, 9, cc_matrix); + TIFFSetField (tif, TIFFTAG_ASSHOTNEUTRAL, 3, neutral); + //TIFFSetField (tif, TIFFTAG_CAMERASERIALNUMBER, serial); + TIFFSetField (tif, TIFFTAG_CALIBRATIONILLUMINANT1, 21); + + scaled_buffer = gst_sample_get_buffer (scaled); + if (scaled_buffer) { + GstMapInfo map; + + gst_buffer_map (scaled_buffer, &map, GST_MAP_READ); + for (int row = 0; row < (height >> 2); row ++) + TIFFWriteScanline (tif, map.data[row * (width >> 2)], row, 0); + gst_buffer_unmap (scaled_buffer, &map); + } else { + gst_sample_unref (converted); + gst_sample_unref (scaled); + gst_caps_unref (caps); + gst_video_scaler_free (h_scale); + gst_video_scaler_free (v_scale); + } + + TIFFWriteDirectory (tif); + + TIFFSetField (tif, TIFFTAG_SUBFILETYPE, 0); // Full size image + TIFFSetField (tif, TIFFTAG_IMAGEWIDTH, width); + TIFFSetField (tif, TIFFTAG_IMAGELENGTH, height); + TIFFSetField (tif, TIFFTAG_BITSPERSAMPLE, bpp); + TIFFSetField (tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CFA); + TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, 1); + TIFFSetField (tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField (tif, TIFFTAG_CFAREPEATPATTERNDIM, cfa_dimensions); + TIFFSetField (tif, TIFFTAG_CFAPATTERN, 4, cfa_pattern); + TIFFSetField (tif, TIFFTAG_WHITELEVEL, 1, &white_level); + TIFFSetField (tif, TIFFTAG_WHITELEVEL, 1, &black_level); + + for (int row = 0; row < height; row ++) + TIFFWriteScanline (tif, &data[row * width * (bpp >> 3)], row, 0); + + TIFFClose (tif); + success = TRUE; + + return success; +} static void snapshot_cb (GtkButton *button, ArvViewer *viewer) @@ -932,8 +1107,7 @@ snapshot_cb (GtkButton *button, ArvViewer *viewer) } else if (GST_IS_SAMPLE (sample) && g_content_type_is_mime_type (content_type, "image/jpeg")) { success = _save_gst_sample_to_file (sample, filename, "image/jpeg", NULL); } else if (ARV_IS_BUFFER (buffer) && g_content_type_is_mime_type (content_type, "image/x-adobe-dng")) { - // TODO: implement DNG support - success = g_file_set_contents (filename, data, size, &error); + success = _save_arv_buffer_to_dng_file (buffer, sample, filename, &error); g_free (filename); } else if (ARV_IS_BUFFER (buffer) && g_content_type_is_mime_type (content_type, "image/x-panasonic-rw")) { // GIO guesses that MIME type for ".raw" files, so this is what we look for when writing unformatted raw files From 4ce2316141cb9e5fa3f9889b3a4f0b193c21653e Mon Sep 17 00:00:00 2001 From: Victhor Foster Date: Fri, 2 Jun 2023 10:20:02 -0300 Subject: [PATCH 5/6] Make TIFF support optional for arv-viewer --- meson.build | 11 +++++++--- meson_options.txt | 1 + viewer/arvviewer.c | 15 +++++++++++-- viewer/arvviewerfeatures.h.in | 40 +++++++++++++++++++++++++++++++++++ viewer/meson.build | 7 ++++++ 5 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 viewer/arvviewerfeatures.h.in diff --git a/meson.build b/meson.build index 61b3b0a70..ce91771b2 100644 --- a/meson.build +++ b/meson.build @@ -61,7 +61,7 @@ gobject_dep = dependency ('gobject-2.0', required: true) gio_dep = dependency ('gio-2.0', required: true) xml2_dep = dependency ('libxml-2.0', required: true) libz_dep = dependency ('zlib', required: true) -libtiff_dep = dependency ('libtiff-4', required: true) +tiff_dep = dependency ('libtiff-4', required: get_option ('tiff')) usb_dep = dependency ('libusb-1.0', required: get_option ('usb')) aravis_public_dependencies = [glib_dep, gobject_dep, gio_dep] @@ -107,11 +107,15 @@ viewer_option = get_option ('viewer') viewer_deps = aravis_dependencies + [dependency ('gtk+-3.0', version: '>=3.12', required: viewer_option), dependency ('gstreamer-base-1.0', required: viewer_option), dependency ('gstreamer-app-1.0', required: viewer_option), - dependency ('gstreamer-video-1.0', required: viewer_option), - dependency ('libtiff-4', required: viewer_option)] + dependency ('gstreamer-video-1.0', required: viewer_option)] +if tiff_dep.found() + viewer_deps += tiff_dep +endif subdir ('po', if_found: viewer_deps) subdir ('viewer', if_found: viewer_deps) + + gst_enabled = false gst_option = get_option ('gst-plugin') gst_deps = aravis_dependencies + [dependency ('gstreamer-base-1.0', required: gst_option), @@ -138,6 +142,7 @@ summary ( 'Viewer': viewer_enabled, 'GStreamer plugin': gst_enabled, 'USB support': usb_dep.found(), + 'TIFF viewer support': tiff_dep.found(), }, section: 'Options' ) diff --git a/meson_options.txt b/meson_options.txt index eba1b30ae..e752704f7 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -3,6 +3,7 @@ option('viewer', type: 'feature', value: 'auto', description : 'Build simple viewer') option('gst-plugin', type: 'feature', value: 'auto', description : 'Build GStreamer plugin') option('usb', type: 'feature', value: 'auto', description : 'Enable USB support') +option('tiff', type: 'feature', value: 'auto', description : 'Enable viewer TIFF support') option('packet-socket', type: 'feature', value: 'auto', description : 'Enable packet socket support') option('tests', type: 'boolean', value: true, description: 'Build tests') diff --git a/viewer/arvviewer.c b/viewer/arvviewer.c index d41d0f7f4..a6440e5a6 100644 --- a/viewer/arvviewer.c +++ b/viewer/arvviewer.c @@ -29,9 +29,12 @@ #include #include #include +#include #include #include +#ifdef ARAVIS_HAS_TIFF #include +#endif #ifdef GDK_WINDOWING_X11 #include // for GDK_WINDOW_XID #endif @@ -821,6 +824,7 @@ _save_gst_sample_to_file (GstSample *sample, const char *path, const char *mime_ return success; } +#ifdef ARAVIS_HAS_TIFF static gboolean _save_arv_buffer_to_dng_file (ArvBuffer *buffer, GstSample *sample, const char *path, GError **error) { @@ -995,6 +999,7 @@ _save_arv_buffer_to_dng_file (ArvBuffer *buffer, GstSample *sample, const char * return success; } +#endif static void snapshot_cb (GtkButton *button, ArvViewer *viewer) @@ -1079,11 +1084,13 @@ snapshot_cb (GtkButton *button, ArvViewer *viewer) gtk_file_filter_set_name (filter, "Raw images (*.raw)"); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + #ifdef ARAVIS_HAS_TIFF filter = gtk_file_filter_new (); gtk_file_filter_add_mime_type (filter, "image/x-adobe-dng"); gtk_file_filter_add_mime_type (filter_all, "image/x-adobe-dng"); gtk_file_filter_set_name (filter, "DNG raw image (*.dng)"); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + #endif } gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter_all); @@ -1106,10 +1113,14 @@ snapshot_cb (GtkButton *button, ArvViewer *viewer) success = _save_gst_sample_to_file (sample, filename, "image/png", NULL); } else if (GST_IS_SAMPLE (sample) && g_content_type_is_mime_type (content_type, "image/jpeg")) { success = _save_gst_sample_to_file (sample, filename, "image/jpeg", NULL); - } else if (ARV_IS_BUFFER (buffer) && g_content_type_is_mime_type (content_type, "image/x-adobe-dng")) { + } + #ifdef ARAVIS_HAS_TIFF + else if (ARV_IS_BUFFER (buffer) && g_content_type_is_mime_type (content_type, "image/x-adobe-dng")) { success = _save_arv_buffer_to_dng_file (buffer, sample, filename, &error); g_free (filename); - } else if (ARV_IS_BUFFER (buffer) && g_content_type_is_mime_type (content_type, "image/x-panasonic-rw")) { + } + #endif + else if (ARV_IS_BUFFER (buffer) && g_content_type_is_mime_type (content_type, "image/x-panasonic-rw")) { // GIO guesses that MIME type for ".raw" files, so this is what we look for when writing unformatted raw files success = g_file_set_contents (filename, data, size, &error); g_free (filename); diff --git a/viewer/arvviewerfeatures.h.in b/viewer/arvviewerfeatures.h.in new file mode 100644 index 000000000..65fa05f53 --- /dev/null +++ b/viewer/arvviewerfeatures.h.in @@ -0,0 +1,40 @@ +/* Aravis - Digital camera library + * + * Copyright © 2009-2016 Emmanuel Pacaud + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * Author: Emmanuel Pacaud + */ + +#ifndef ARV_VIEWER_FEATURES_H +#define ARV_VIEWER_FEATURES_H + +/*#if !defined (ARV_H_INSIDE) && !defined (ARAVIS_COMPILATION) +#error "Only can be included directly." +#endif*/ + +/** + * ARAVIS_HAS_TIFF + * + * ARAVIS_HAS_TIFF is defined as 1 if aravis viewer is compiled with TIFF support, 0 if not. + * + * Since: 0.8.27 + */ + +#define ARAVIS_HAS_TIFF @ARAVIS_HAS_TIFF@ + +#endif diff --git a/viewer/meson.build b/viewer/meson.build index 0928e6b01..678d840e9 100644 --- a/viewer/meson.build +++ b/viewer/meson.build @@ -19,6 +19,13 @@ viewer_c_args = [ '-DARAVIS_GETTEXT="aravis-@0@"'.format (aravis_api_version) ] +viewer_include_dir = get_option ('includedir') / 'aravis-@0@'.format (aravis_api_version) + +features_viewer_config_data = configuration_data () +features_viewer_config_data.set10 ('ARAVIS_HAS_TIFF', tiff_dep.found()) +configure_file (input: 'arvviewerfeatures.h.in', output: 'arvviewerfeatures.h', + configuration: features_viewer_config_data, install_dir: viewer_include_dir) + viewer_resources = gnome.compile_resources ( 'arvviewerresources', 'arvviewerresources.xml' ) From 1b578a4c8444a1ba6e51998712aa8f812229d2e4 Mon Sep 17 00:00:00 2001 From: Victhor Foster Date: Thu, 8 Jun 2023 14:13:50 -0300 Subject: [PATCH 6/6] Added more bayer formats as grayscale fallback formats --- src/arvmisc.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 171 insertions(+), 3 deletions(-) diff --git a/src/arvmisc.c b/src/arvmisc.c index a2b8c774e..82515c440 100644 --- a/src/arvmisc.c +++ b/src/arvmisc.c @@ -720,6 +720,65 @@ ArvGstCapsInfos arv_gst_caps_infos[] = { "video/x-raw-bayer, format=(string)bggr, bpp=(int)8, depth=(int)8", "video/x-raw-bayer", 8, 8, ARV_MAKE_FOURCC ('b','g','g','r') }, +/* Non 8bit bayer formats are not supported by gstreamer bayer plugin. + * This feature is discussed in bug https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/issues/86 . + * This is a fallback for these bayer formats, displaying a grayscale image. */ + { + ARV_PIXEL_FORMAT_BAYER_GR_10, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)grbg, bpp=(int)16, depth=(int)10", + "video/x-raw-gray", 16, 10, ARV_MAKE_FOURCC ('g','r','b','g') + }, + { + ARV_PIXEL_FORMAT_BAYER_RG_10, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)rggb, bpp=(int)16, depth=(int)10", + "video/x-raw-gray", 16, 10, ARV_MAKE_FOURCC ('r','g','g','b') + }, + { + ARV_PIXEL_FORMAT_BAYER_GB_10, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)gbrg, bpp=(int)16, depth=(int)10", + "video/x-raw-gray", 16, 10, ARV_MAKE_FOURCC ('g','b','r','g') + }, + { + ARV_PIXEL_FORMAT_BAYER_BG_10, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-gray, format=(string)bggr, bpp=(int)16, depth=(int)10", + "video/x-raw-gray", 16, 10, ARV_MAKE_FOURCC ('b','g','g','r') + }, + { + ARV_PIXEL_FORMAT_BAYER_GR_12, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)grbg, bpp=(int)16, depth=(int)12", + "video/x-raw-gray", 16, 12, ARV_MAKE_FOURCC ('g','r','b','g') + }, + { + ARV_PIXEL_FORMAT_BAYER_RG_12, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)rggb, bpp=(int)16, depth=(int)12", + "video/x-raw-gray", 16, 12, ARV_MAKE_FOURCC ('r','g','g','b') + }, + { + ARV_PIXEL_FORMAT_BAYER_GB_12, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)gbrg, bpp=(int)16, depth=(int)12", + "video/x-raw-gray", 16, 12, ARV_MAKE_FOURCC ('g','b','r','g') + }, + { + ARV_PIXEL_FORMAT_BAYER_BG_12, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-gray, format=(string)bggr, bpp=(int)16, depth=(int)12", + "video/x-raw-gray", 16, 12, ARV_MAKE_FOURCC ('b','g','g','r') + }, { ARV_PIXEL_FORMAT_BAYER_GR_16, "video/x-raw, format=(string)GRAY16_LE", @@ -748,9 +807,118 @@ ArvGstCapsInfos arv_gst_caps_infos[] = { "video/x-raw-gray, format=(string)bggr, bpp=(int)16, depth=(int)16", "video/x-raw-gray", 16, 16, ARV_MAKE_FOURCC ('b','g','g','r') }, -/* Non 8bit bayer formats are not supported by gstreamer bayer plugin. - * This feature is discussed in bug https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/issues/86 .*/ - + { + ARV_PIXEL_FORMAT_BAYER_GR_10P, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)grbg, bpp=(int)10, depth=(int)10", + "video/x-raw-gray", 10, 10, ARV_MAKE_FOURCC ('g','r','b','g') + }, + { + ARV_PIXEL_FORMAT_BAYER_RG_10P, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)rggb, bpp=(int)10, depth=(int)10", + "video/x-raw-gray", 10, 10, ARV_MAKE_FOURCC ('r','g','g','b') + }, + { + ARV_PIXEL_FORMAT_BAYER_GB_10P, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)gbrg, bpp=(int)10, depth=(int)10", + "video/x-raw-gray", 10, 10, ARV_MAKE_FOURCC ('g','b','r','g') + }, + { + ARV_PIXEL_FORMAT_BAYER_BG_10P, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-gray, format=(string)bggr, bpp=(int)10, depth=(int)10", + "video/x-raw-gray", 10, 10, ARV_MAKE_FOURCC ('b','g','g','r') + }, + { + ARV_PIXEL_FORMAT_BAYER_GR_12P, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)grbg, bpp=(int)12, depth=(int)12", + "video/x-raw-gray", 12, 12, ARV_MAKE_FOURCC ('g','r','b','g') + }, + { + ARV_PIXEL_FORMAT_BAYER_RG_12P, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)rggb, bpp=(int)12, depth=(int)12", + "video/x-raw-gray", 12, 12, ARV_MAKE_FOURCC ('r','g','g','b') + }, + { + ARV_PIXEL_FORMAT_BAYER_GB_12P, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)gbrg, bpp=(int)12, depth=(int)12", + "video/x-raw-gray", 12, 12, ARV_MAKE_FOURCC ('g','b','r','g') + }, + { + ARV_PIXEL_FORMAT_BAYER_BG_12P, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-gray, format=(string)bggr, bpp=(int)12, depth=(int)12", + "video/x-raw-gray", 12, 12, ARV_MAKE_FOURCC ('b','g','g','r') + }, + { + ARV_PIXEL_FORMAT_BAYER_GR_10_PACKED, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)grbg, bpp=(int)10, depth=(int)10", + "video/x-raw-gray", 10, 10, ARV_MAKE_FOURCC ('g','r','b','g') + }, + { + ARV_PIXEL_FORMAT_BAYER_RG_10_PACKED, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)rggb, bpp=(int)10, depth=(int)10", + "video/x-raw-gray", 10, 10, ARV_MAKE_FOURCC ('r','g','g','b') + }, + { + ARV_PIXEL_FORMAT_BAYER_GB_10_PACKED, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)gbrg, bpp=(int)10, depth=(int)10", + "video/x-raw-gray", 10, 10, ARV_MAKE_FOURCC ('g','b','r','g') + }, + { + ARV_PIXEL_FORMAT_BAYER_BG_10_PACKED, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-gray, format=(string)bggr, bpp=(int)10, depth=(int)10", + "video/x-raw-gray", 10, 10, ARV_MAKE_FOURCC ('b','g','g','r') + }, + { + ARV_PIXEL_FORMAT_BAYER_GR_12_PACKED, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)grbg, bpp=(int)12, depth=(int)12", + "video/x-raw-gray", 12, 12, ARV_MAKE_FOURCC ('g','r','b','g') + }, + { + ARV_PIXEL_FORMAT_BAYER_RG_12_PACKED, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)rggb, bpp=(int)12, depth=(int)12", + "video/x-raw-gray", 12, 12, ARV_MAKE_FOURCC ('r','g','g','b') + }, + { + ARV_PIXEL_FORMAT_BAYER_GB_12_PACKED, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-bayer, format=(string)gbrg, bpp=(int)12, depth=(int)12", + "video/x-raw-gray", 12, 12, ARV_MAKE_FOURCC ('g','b','r','g') + }, + { + ARV_PIXEL_FORMAT_BAYER_BG_12_PACKED, + "video/x-raw, format=(string)GRAY16_LE", + "video/x-raw", "GRAY16_LE", + "video/x-raw-gray, format=(string)bggr, bpp=(int)12, depth=(int)12", + "video/x-raw-gray", 12, 12, ARV_MAKE_FOURCC ('b','g','g','r') + }, { ARV_PIXEL_FORMAT_YUV_422_PACKED, "video/x-raw, format=(string)UYVY",