summaryrefslogtreecommitdiff
path: root/src/photos/GRaw.vala
diff options
context:
space:
mode:
Diffstat (limited to 'src/photos/GRaw.vala')
-rw-r--r--src/photos/GRaw.vala307
1 files changed, 307 insertions, 0 deletions
diff --git a/src/photos/GRaw.vala b/src/photos/GRaw.vala
new file mode 100644
index 0000000..915a861
--- /dev/null
+++ b/src/photos/GRaw.vala
@@ -0,0 +1,307 @@
+/* Copyright 2010-2014 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+namespace GRaw {
+
+public const double HD_POWER = 2.222;
+public const double HD_SLOPE = 4.5;
+
+public const double SRGB_POWER = 2.4;
+public const double SRGB_SLOPE = 12.92;
+
+public enum Colorspace {
+ RAW = 0,
+ SRGB = 1,
+ ADOBE = 2,
+ WIDE = 3,
+ PROPHOTO = 4,
+ XYZ = 5
+}
+
+public errordomain Exception {
+ UNSPECIFIED,
+ UNSUPPORTED_FILE,
+ NONEXISTANT_IMAGE,
+ OUT_OF_ORDER_CALL,
+ NO_THUMBNAIL,
+ UNSUPPORTED_THUMBNAIL,
+ OUT_OF_MEMORY,
+ DATA_ERROR,
+ IO_ERROR,
+ CANCELLED_BY_CALLBACK,
+ BAD_CROP,
+ SYSTEM_ERROR
+}
+
+public enum Flip {
+ FROM_SOURCE = -1,
+ NONE = 0,
+ UPSIDE_DOWN = 3,
+ COUNTERCLOCKWISE = 5,
+ CLOCKWISE = 6
+}
+
+public enum FujiRotate {
+ USE = -1,
+ DONT_USE = 0
+}
+
+public enum HighlightMode {
+ CLIP = 0,
+ UNCLIP = 1,
+ BLEND = 2,
+ REBUILD = 3
+}
+
+public enum InterpolationQuality {
+ LINEAR = 0,
+ VNG = 1,
+ PPG = 2,
+ AHD = 3
+}
+
+public class ProcessedImage {
+ private LibRaw.ProcessedImage image;
+ private Gdk.Pixbuf pixbuf = null;
+
+ public ushort width {
+ get {
+ return image.width;
+ }
+ }
+
+ public ushort height {
+ get {
+ return image.height;
+ }
+ }
+
+ public ushort colors {
+ get {
+ return image.colors;
+ }
+ }
+
+ public ushort bits {
+ get {
+ return image.bits;
+ }
+ }
+
+ public uint8* data {
+ get {
+ return image.data;
+ }
+ }
+
+ public uint data_size {
+ get {
+ return image.data_size;
+ }
+ }
+
+ public ProcessedImage(LibRaw.Processor proc) throws Exception {
+ LibRaw.Result result = LibRaw.Result.SUCCESS;
+ image = proc.make_mem_image(ref result);
+ throw_exception("ProcessedImage", result);
+ assert(image != null);
+
+ // A regular mem image comes back with raw RGB data ready for pixbuf (data buffer is shared
+ // between the ProcessedImage and the Gdk.Pixbuf)
+ pixbuf = new Gdk.Pixbuf.with_unowned_data(image.data, Gdk.Colorspace.RGB, false, image.bits,
+ image.width, image.height, image.width * image.colors, null);
+ }
+
+ public ProcessedImage.from_thumb(LibRaw.Processor proc) throws Exception {
+ LibRaw.Result result = LibRaw.Result.SUCCESS;
+ image = proc.make_mem_thumb(ref result);
+ throw_exception("ProcessedImage.from_thumb", result);
+ assert(image != null);
+
+ // A mem thumb comes back as the raw bytes from the data segment in the file -- this needs
+ // to be decoded before being useful. This will throw an error if the format is not
+ // supported
+ try {
+ pixbuf = new Gdk.Pixbuf.from_stream(new MemoryInputStream.from_data(image.data, null),
+ null);
+ } catch (Error err) {
+ throw new Exception.UNSUPPORTED_THUMBNAIL(err.message);
+ }
+
+ // fix up the ProcessedImage fields (which are unset when decoding the thumb)
+ image.width = (ushort) pixbuf.width;
+ image.height = (ushort) pixbuf.height;
+ image.colors = (ushort) pixbuf.n_channels;
+ image.bits = (ushort) pixbuf.bits_per_sample;
+ }
+
+ // This method returns a copy of a pixbuf representing the ProcessedImage.
+ public Gdk.Pixbuf get_pixbuf_copy() {
+ return pixbuf.copy();
+ }
+}
+
+public class Processor {
+ public LibRaw.OutputParams* output_params {
+ get {
+ return &proc.params;
+ }
+ }
+
+ private LibRaw.Processor proc;
+
+ public Processor(LibRaw.Options options = LibRaw.Options.NONE) {
+ proc = new LibRaw.Processor(options);
+ }
+
+ public void adjust_sizes_info_only() throws Exception {
+ throw_exception("adjust_sizes_info_only", proc.adjust_sizes_info_only());
+ }
+
+ public unowned LibRaw.ImageOther get_image_other() {
+ return proc.get_image_other();
+ }
+
+ public unowned LibRaw.ImageParams get_image_params() {
+ return proc.get_image_params();
+ }
+
+ public unowned LibRaw.ImageSizes get_sizes() {
+ return proc.get_sizes();
+ }
+
+ public unowned LibRaw.Thumbnail get_thumbnail() {
+ return proc.get_thumbnail();
+ }
+
+ public ProcessedImage make_mem_image() throws Exception {
+ return new ProcessedImage(proc);
+ }
+
+ public ProcessedImage make_thumb_image() throws Exception {
+ return new ProcessedImage.from_thumb(proc);
+ }
+
+ public void open_buffer(uint8[] buffer) throws Exception {
+ throw_exception("open_buffer", proc.open_buffer(buffer));
+ }
+
+ public void open_file(string filename) throws Exception {
+ throw_exception("open_file", proc.open_file(filename));
+ }
+
+ public void process() throws Exception {
+ throw_exception("process", proc.process());
+ }
+
+ public void ppm_tiff_writer(string filename) throws Exception {
+ throw_exception("ppm_tiff_writer", proc.ppm_tiff_writer(filename));
+ }
+
+ public void thumb_writer(string filename) throws Exception {
+ throw_exception("thumb_writer", proc.thumb_writer(filename));
+ }
+
+ public void recycle() {
+ proc.recycle();
+ }
+
+ public void unpack() throws Exception {
+ throw_exception("unpack", proc.unpack());
+ }
+
+ public void unpack_thumb() throws Exception {
+ throw_exception("unpack_thumb", proc.unpack_thumb());
+ }
+
+ // This configures output_params for reasonable settings for turning a RAW image into an
+ // RGB ProcessedImage suitable for display. Tweaks can occur after this call and before
+ // process().
+ public void configure_for_rgb_display(bool half_size) {
+ // Fields in comments are left to their defaults and/or should be modified by the caller.
+ // These fields are set to reasonable defaults by libraw.
+
+ // greybox
+ output_params->set_chromatic_aberrations(1.0, 1.0);
+ output_params->set_gamma_curve(GRaw.SRGB_POWER, GRaw.SRGB_SLOPE);
+ // user_mul
+ // shot_select
+ // multi_out
+ output_params->bright = 1.0f;
+ // threshold
+ output_params->half_size = half_size;
+ // four_color_rgb
+ output_params->highlight = GRaw.HighlightMode.CLIP;
+ output_params->use_auto_wb = true;
+ output_params->use_camera_wb = true;
+ output_params->use_camera_matrix = true;
+ output_params->output_color = GRaw.Colorspace.SRGB;
+ // output_profile
+ // camera_profile
+ // bad_pixels
+ // dark_frame
+ output_params->output_bps = 8;
+ // output_tiff
+ output_params->user_flip = GRaw.Flip.FROM_SOURCE;
+ output_params->user_qual = GRaw.InterpolationQuality.PPG;
+ // user_black
+ // user_sat
+ // med_passes
+ output_params->no_auto_bright = true;
+ output_params->auto_bright_thr = 0.01f;
+ output_params->use_fuji_rotate = GRaw.FujiRotate.USE;
+ }
+}
+
+private void throw_exception(string caller, LibRaw.Result result) throws Exception {
+ if (result == LibRaw.Result.SUCCESS)
+ return;
+ else if (result > 0)
+ throw new Exception.SYSTEM_ERROR("%s: System error %d: %s", caller, (int) result, strerror(result));
+
+ string msg = "%s: %s".printf(caller, result.to_string());
+
+ switch (result) {
+ case LibRaw.Result.UNSPECIFIED_ERROR:
+ throw new Exception.UNSPECIFIED(msg);
+
+ case LibRaw.Result.FILE_UNSUPPORTED:
+ throw new Exception.UNSUPPORTED_FILE(msg);
+
+ case LibRaw.Result.REQUEST_FOR_NONEXISTENT_IMAGE:
+ throw new Exception.NONEXISTANT_IMAGE(msg);
+
+ case LibRaw.Result.OUT_OF_ORDER_CALL:
+ throw new Exception.OUT_OF_ORDER_CALL(msg);
+
+ case LibRaw.Result.NO_THUMBNAIL:
+ throw new Exception.NO_THUMBNAIL(msg);
+
+ case LibRaw.Result.UNSUPPORTED_THUMBNAIL:
+ throw new Exception.UNSUPPORTED_THUMBNAIL(msg);
+
+ case LibRaw.Result.UNSUFFICIENT_MEMORY:
+ throw new Exception.OUT_OF_MEMORY(msg);
+
+ case LibRaw.Result.DATA_ERROR:
+ throw new Exception.DATA_ERROR(msg);
+
+ case LibRaw.Result.IO_ERROR:
+ throw new Exception.IO_ERROR(msg);
+
+ case LibRaw.Result.CANCELLED_BY_CALLBACK:
+ throw new Exception.CANCELLED_BY_CALLBACK(msg);
+
+ case LibRaw.Result.BAD_CROP:
+ throw new Exception.BAD_CROP(msg);
+
+ default:
+ return;
+ }
+}
+
+}
+