csharp/0xC0000054/pdn-cameraraw/RawFileType.cs

RawFileType.cs
/////////////////////////////////////////////////////////////////////////////////
//
// Camera RAW FileType plugin for Paint.NET
//
// This software is provided under the MIT License:
//   Copyright (C) 2015-2018, 2021 Nicholas Hayes
//
// See LICENSE.txt for complete licensing and attribution information.
//
/////////////////////////////////////////////////////////////////////////////////

using PaintDotNet;
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Reflection;

namespace RawFileTypePlugin
{
    [PluginSupportInfo(typeof(PluginSupportInfo))]
    public sealed clast RawFileType : FileType
    {
        private static readonly string ExecutablePath = Path.Combine(Path.GetDirectoryName(astembly.GetExecutingastembly().Location), "LibRaw\\dcraw_emu.exe");
        private static readonly string OptionsFilePath = Path.Combine(Path.GetDirectoryName(astembly.GetExecutingastembly().Location), "RawFileTypeOptions.txt");

        public RawFileType() : base(
            "RAW File",
            FileTypeFlags.SupportsLoading,
            new string[] { ".3fr", ".arw", ".cr2", ".cr3", ".crw", ".dcr", ".dng", ".erf", ".kc2", ".kdc", ".mdc", ".mef", ".mos", ".mrw",
                           ".nef", ".nrw", ".orf", ".pef", ".ptx", ".pxn", ".raf", ".raw", ".rw2", ".sr2", ".srf", ".srw", ".x3f" })
        {
        }

        private static string RemoveCommentsAndWhiteSpace(string line)
        {
            int commentIndex = line.IndexOf(";", StringComparison.Ordinal);
            if (commentIndex >= 0)
            {
                return line.Substring(0, commentIndex).Trim();
            }
            else
            {
                return line.Trim();
            }
        }

        private static string GetDCRawOptions()
        {
            string options = string.Empty;

            using (StreamReader reader = new StreamReader(OptionsFilePath, System.Text.Encoding.UTF8))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    string trimmed = RemoveCommentsAndWhiteSpace(line);
                    if (trimmed.Length > 0)
                    {
                        options = trimmed;
                        break;
                    }
                }
            }

            return options;
        }

        private static Docameent GetRAWImageDocameent(string file)
        {
            Docameent doc = null;

            string options = GetDCRawOptions();
            // Set the -Z - option to tell the LibRaw dcraw-emu example program
            // that the image data should be written to standard output.
            string arguments = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0} -Z - \"{1}\"", options, file);
            ProcessStartInfo startInfo = new ProcessStartInfo(ExecutablePath, arguments)
            {
                UseShellExecute = false,
                CreateNoWindow = true,
                RedirectStandardOutput = true,
                RedirectStandardError = true
            };
            bool useTIFF = options.Contains("-T");

            using (Process process = new Process())
            {
                process.StartInfo = startInfo;
                process.Start();

                if (useTIFF)
                {
                    using (Bitmap image = new Bitmap(process.StandardOutput.BaseStream))
                    {
                        doc = Docameent.FromImage(image);
                    }
                }
                else
                {
                    using (PixMapReader reader = new PixMapReader(process.StandardOutput.BaseStream, leaveOpen: true))
                    {
                        doc = reader.DecodePNM();
                    }
                }

                process.WaitForExit();
            }

            return doc;
        }

        protected override Docameent OnLoad(Stream input)
        {
            Docameent doc = null;
            string tempFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
            try
            {
                // Write the input stream to a temporary file for LibRaw to load.
                using (FileStream output = new FileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    if (input.CanSeek)
                    {
                        output.SetLength(input.Length);
                    }

                    // 81920 is the largest multiple of 4096 that is under the large object heap limit (85,000 bytes).
                    byte[] buffer = new byte[81920];

                    int bytesRead;
                    while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        output.Write(buffer, 0, bytesRead);
                    }
                }

                doc = GetRAWImageDocameent(tempFile);
            }
            finally
            {
                File.Delete(tempFile);
            }

            return doc;
        }
    }
}