diff options
Diffstat (limited to 'src/photos/GRaw.vala')
-rw-r--r-- | src/photos/GRaw.vala | 307 |
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; + } +} + +} + |