.NET打造的RAW照片解析利器

科技   2024-11-06 08:03   北京  


 利用周末的闲暇时光,我选择了远离都市的喧嚣,投身于山水之间,以陶冶情操。

经过一番搜寻,我选择了相对较近的三清山作为目的地,亲身体验了苏轼笔下“揽胜遍五岳,绝境在人间”的意境。对于山东和河南的游客来说,这里还有一个额外的福利——免门票。那里的景色之美,简直无法用言语形容,一个字“绝”。一旦置身其中,使我产生一种不愿离去的感觉。

在拍照时,我通常保存RAW和JPG两种格式。遗憾的是,在这次旅行中,由于风景太过迷人和拍了一个视频,导致我那仅有的32GB存储卡很快就被填满了,而且我忘记了携带额外的存储卡。比较好一点的是,我随身携带了USB数据线,通过一番操作,我选择了删除JPG格式的照片以释放空间。我打算自己处理这些图片,却遇到了一些问题。

文件格式

  • • ARW:这是索尼相机的原始图像格式,文件较大,适合专业编辑。

  • • TIFF:这是一种高质量的图像格式,支持无损压缩,常用于印刷行业。

  • • JPG:这是一种广泛用于网络的有损压缩图像格式,文件体积小,适合快速传输。

问题1:我原本以为之前介绍的ImageSharp库可以处理这些文件,但实际操作中却发现并非如此简单,可能是我的操作方法有误。

Error converting 'C:\Users\Pride\Desktop\2\DSC00001.ARW': The number of samples in the TIFF BitsPerSample entry is not supported.

这个错误表明ImageSharp库不支持15位的BitsPerSample值,意味着在将ARW文件转换为TIFF格式时,可能包含了ImageSharp不支持的位深度。

面对这一挑战,我转换了思路,决定先将文件转换为通用的TIFF格式,然后再转换为JPG格式。在这个过程中,我找到了一个非常有用的工具——Sdcb.LibRaw。使用这个库,操作变得非常简单。

作者博客:https://www.cnblogs.com/sdcb/p/20230801-sdcb-libraw-intro.html

安装

  • • Sdcb.LibRaw

  • • Sdcb.LibRaw.runtime.win64(或者适用于您系统的其他平台包)

功能

  • • RAW照片转Bitmap

  • • RAW照片转tiff

  • • 从RAW照片中读取缩略图

  • • 将RAW照片转换并保存为本地tiff文件

  • • 获取照片元数据信息

  • • 图片的后期处理

处理

未处理的ARW格式

提取的缩略图

风景






代码示例

// 获取所有ARW文件
string[] arwFiles = Directory.GetFiles(outputFolderPath + "\\", "*.ARW");
foreach (string file in arwFiles)
{
    string fileName = Path.GetFileNameWithoutExtension(file);  
    try
    {
        //https://www.cnblogs.com/sdcb/p/20230801-sdcb-libraw-intro.htmls
        // 打开RAW文件
        using RawContext r = RawContext.OpenFile(file);
        //读取文件信息
        LibRawImageParams imageParams = r.ImageParams;
        LibRawImageOtherParams otherParams = r.ImageOtherParams;
        LibRawLensInfo lensInfo = r.LensInfo; 
        Console.WriteLine($"相机: {imageParams.Model}");
        Console.WriteLine($"版本号: {imageParams.Software}");
        Console.WriteLine($"ISO: {otherParams.IsoSpeed}");
        Console.WriteLine($"快门速度: 1/{1 / otherParams.Shutter:F0}s");
        Console.WriteLine($"焦距: {otherParams.FocalLength}mm");
        Console.WriteLine($"艺术家标签: {otherParams.Artist}");
        Console.WriteLine($"拍摄日期: {new DateTime(1970, 1, 1, 8, 0, 0).AddSeconds(otherParams.Timestamp)}");
        Console.WriteLine($"镜头名称: {lensInfo.Lens}"); 
        r.Unpack();
        r.DcrawProcess();

        //从RAW照片中读取缩略图 
        using ProcessedImage image1 = r.ExportThumbnail(thumbnailIndex: 0);
        using Bitmap bmp1 = (Bitmap)Bitmap.FromStream(new MemoryStream(image1.AsSpan<byte>().ToArray()));
        bmp1.Save(Path.Combine(outputFolderPath, $"{fileName}-缩略图.JPG"), System.Drawing.Imaging.ImageFormat.Jpeg);

        //保存JPG
        using ProcessedImage image = r.MakeDcrawMemoryImage();
        using Bitmap bmp = ProcessedImageToBitmap(image);
        Bitmap ProcessedImageToBitmap(ProcessedImage rgbImage)
        {
           
            rgbImage.SwapRGB(); //这里 将RGB24转换成了BGR24
            using Bitmap bmp = new Bitmap(rgbImage.Width, rgbImage.Height, rgbImage.Width * 3, System.Drawing.Imaging.PixelFormat.Format24bppRgb, rgbImage.DataPointer);
            return new Bitmap(bmp);
        }

        bmp.Save(Path.Combine(outputFolderPath, $"{fileName}-保存JPG.JPG"), System.Drawing.Imaging.ImageFormat.Jpeg);

        //RAW照片转tiff
        r.WriteDcrawPpmTiff(Path.Combine(outputFolderPath, $"{fileName}.tiff"));

        //后期处理
        r.DcrawProcess(c =>
        {
            c.HalfSize = false; // 图片只保留1/4大小
            c.UseCameraWb = true; // 使用机内白平衡,false则会由UserMultipliers控制白平衡
            c.Gamma[0] = 0.35; // 调整Gamma曲线指数
            c.Gamma[1] = 3.5;  // 调整Gamma曲线斜率
            c.Brightness = 2.2f; // 亮度
            c.Interpolation = true; // 是否执行反马赛克(demosaic)操作
            c.OutputBps = 8; // 输出位数8位
            c.OutputTiff = false; // 输出为tiff文件?false表示输出Bitmap
            // c.Cropbox = new Rectangle(4000, 2000, 1500, 700); // 裁切
            // 还有许多其它设置可以自行探索 
        });
        bmp.Save(Path.Combine(outputFolderPath, $"{fileName}-后期处理.JPG"), System.Drawing.Imaging.ImageFormat.Jpeg);
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error converting '{file}': {ex.Message}");
    }
    finally
    { 
    } 
}

示例基于.ARW照片,但实际上几乎所有RAW格式照片都是支持的,包括.CR2或者.DNG,可以通过RawContext.SupportedCameras获取支持的相机列表,截止当前版本它支持了1182款相机型号:

Console.WriteLine("Sdcb.LibRaw supported cameras:");
foreach (string model in RawContext.SupportedCameras)
{
 Console.WriteLine(model);
}


推荐阅读

-看看这样的Dotnet后台管理,那真是叫一个清新优雅高颜值!!!

• 体验地址:https://malus.dotnetshare.com

-超级漂亮干净的Dotnet学习网站

  • • 体验地址:https://www.dotnetshare.com

如果你觉得这篇内容对你挺有启发和帮助,点个「在看」,让更多的人也能看到这篇内容,欢迎关注公众号「Net分享」,持续为你推送精选好文。 


点一下,代码无 Bug

WPF开发者
「WPF开发者」现役微软MVP,专注 WPF 和 Avalonia 技术分享与传播。
 最新文章