소스 검색

support for raw images

Johann 6 년 전
부모
커밋
fe076d425a

+ 8 - 3
lazpaint/dialog/ubrowseimages.pas

@@ -160,7 +160,7 @@ uses BGRAThumbnail, BGRAPaintNet, BGRAOpenRaster, BGRAReadLzp,
     Types, UResourceStrings,
     UConfig, bgrareadjpeg, FPReadJPEG,
     UFileExtensions, BGRAUTF8, LazFileUtils,
-    UGraph;
+    UGraph, URaw;
 
 var
   IconCache: TStringList;
@@ -498,7 +498,8 @@ begin
   if AType = 'Folder' then AType := rsFolder else
   begin
     format := SuggestImageFormat(AType);
-    if format = ifPng then AType := 'PNG' //too long to write explicitely
+    if IsRawFilename('noname'+AType) then AType := 'Raw'
+    else if format = ifPng then AType := 'PNG' //too long to write explicitely
     else if format = ifGIF then AType := 'GIF' //do not know if animated or not
     else if format = ifIco then AType := 'Icon'
     else if format = ifCur then AType := 'Cursor'
@@ -541,7 +542,11 @@ var i: integer;
           try
             s := FileManager.CreateFileStream(itemPath, fmOpenRead or fmShareDenyWrite);
             try
-              found := GetStreamThumbnail(s,ShellListView1.LargeIconSize,ShellListView1.LargeIconSize, BGRAPixelTransparent, True, ExtractFileExt(itemPath), FBmpIcon) <> nil;
+              if IsRawFilename(itemPath) then
+              begin
+                found := GetRawStreamThumbnail(s,ShellListView1.LargeIconSize,ShellListView1.LargeIconSize, BGRAPixelTransparent, True, FBmpIcon) <> nil;
+              end else
+                found := GetStreamThumbnail(s,ShellListView1.LargeIconSize,ShellListView1.LargeIconSize, BGRAPixelTransparent, True, ExtractFileExt(itemPath), FBmpIcon) <> nil;
             finally
               s.Free;
             end;

+ 1 - 1
lazpaint/lazpaint.lpr

@@ -39,7 +39,7 @@ uses
   UMainFormLayout, USaveOption, UBrushType, ugeometricbrush,
   URainType, UFormRain, UPaletteToolbar, uselectionhighlight,
   UImagePreview, UPreviewDialog, UQuestion, UTiff, UImageView,
-  UDarkTheme;
+  UDarkTheme, URaw;
 
 //sometimes LResources disappear in the uses clause
 

+ 12 - 1
lazpaint/lazpaintmainform.pas

@@ -863,7 +863,7 @@ implementation
 uses LCLIntf, BGRAUTF8, ugraph, math, umac, uclipboard, ucursors,
    ufilters, ULoadImage, ULoading, UFileExtensions, UBrushType,
    ugeometricbrush, UPreviewDialog, UQuestion, BGRALayerOriginal,
-   BGRATransform, LCVectorPolyShapes;
+   BGRATransform, LCVectorPolyShapes, URaw;
 
 const PenWidthFactor = 10;
 
@@ -3588,7 +3588,12 @@ var
       StartImport;
       with ComputeAcceptableImageSize(newPicture.bmp.Width,newPicture.bmp.Height) do
         if (cx < newPicture.bmp.Width) or (cy < newPicture.bmp.Height) then
+        begin
+          MessagePopupForever(rsResamplingImage);
+          LazPaintInstance.UpdateWindows;
           BGRAReplace(newPicture.bmp, newPicture.bmp.Resample(cx,cy,rmFineResample));
+          MessagePopupHide
+        end;
       image.Assign(newPicture.bmp,True, false);
       newPicture.bmp := nil;
       EndImport(newPicture.bpp, newPicture.frameIndex);
@@ -3628,6 +3633,12 @@ begin
       ImportNewPicture;
     end
     else
+    if IsRawFilename(filenameUTF8) then
+    begin
+      newPicture.bmp := GetRawFileImage(filenameUTF8);
+      newPicture.bpp := 0;
+      ImportNewPicture;
+    end else
     if format in[ifIco,ifCur] then
     begin
       newPicture := ShowPreviewDialog(LazPaintInstance, FilenameUTF8, rsIconOrCursor, ASkipDialogIfSingleImage);

+ 2 - 1
lazpaint/ufileextensions.pas

@@ -41,7 +41,7 @@ implementation
 
 uses Masks, LazUTF8, UResourceStrings, BGRASVG,
      BGRALayerOriginal, BGRASVGOriginal, BGRAGradientOriginal,
-     LCVectorOriginal, LCVectorShapes;
+     LCVectorOriginal, LCVectorShapes, URaw;
 
 function GetSelectedFilterExtensions(const Filter: string;
   FilterIndex: integer; ARemoveLeadingDot: boolean): TStringList;
@@ -321,6 +321,7 @@ initialization
   RegisterPicExt('Tiff','tif;tiff', [eoReadable,eoWritable]);
   RegisterPicExt('X PixMap','xpm', [eoReadable,eoWritable]);
   RegisterPicExt('X Window','xwd', [eoReadable]);
+  RegisterPicExt('Raw',AllRawExtensions, [eoReadable]);
 
 end.
 

+ 14 - 1
lazpaint/uimagepreview.pas

@@ -100,7 +100,7 @@ type
 implementation
 
 uses FPimage, BGRAReadJpeg, BGRAOpenRaster, BGRAPaintNet, BGRAReadLzp, Dialogs, UNewimage,
-  LCLType, BGRAPhoxo, BGRASVG, math;
+  LCLType, BGRAPhoxo, BGRASVG, math, URaw;
 
 { TImagePreview }
 
@@ -844,6 +844,19 @@ begin
     try
       source := FileManager.CreateFileStream(FFilename, fmOpenRead or fmShareDenyWrite);
       FImageFormat := DetectFileFormat(source,ExtractFileExt(FFilename));
+      if IsRawFilename(FFilename) then
+      begin
+        try
+          FSingleImage := GetRawStreamImage(source);
+          FImageNbLayers := 1;
+        except
+          on ex: Exception do
+          begin
+            FLoadError:= ex.Message;
+            FreeAndNil(FSingleImage);
+          end;
+        end;
+      end else
       case FImageFormat of
       ifGif:
         begin

+ 7 - 1
lazpaint/uloadimage.pas

@@ -18,7 +18,7 @@ implementation
 uses FileUtil, BGRAAnimatedGif, Graphics, UMultiImage,
   BGRAReadLzp, LCLProc, BGRABitmapTypes, BGRAReadPng,
   UFileSystem, BGRAIconCursor, BGRAReadTiff,
-  Dialogs, math;
+  Dialogs, math, URaw;
 
 function LoadIcoMultiImageFromStream(AStream: TStream): ArrayOfImageEntry;
 var ico: TBGRAIconCursor; i: integer;
@@ -120,6 +120,7 @@ function AbleToLoadUTF8(AFilename: string): boolean;
 var
   s: TStream;
 begin
+  if IsRawFilename(AFilename) then exit(true);
   s := FileManager.CreateFileStream(AFilename, fmOpenRead or fmShareDenyWrite);
   try
     result := DefaultBGRAImageReader[DetectFileFormat(s, ExtractFileExt(AFilename))] <> nil;
@@ -187,6 +188,11 @@ begin
   s := FileManager.CreateFileStream(AFilename, fmOpenRead or fmShareDenyWrite);
   try
     format := DetectFileFormat(s, ExtractFileExt(AFilename));
+    if IsRawFilename(AFilename) then
+    begin
+      result.bmp := GetRawStreamImage(s);
+      result.bpp:= 0;
+    end else
     if format in[ifIco,ifCur] then
     begin
       multi := LoadIcoMultiImageFromStream(s);

+ 216 - 0
lazpaint/uraw.pas

@@ -0,0 +1,216 @@
+unit URaw;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, FPimage, BGRABitmap, BGRABitmapTypes, Controls;
+
+type
+  TRawExtension = record
+    ext: string;
+    brand: string;
+  end;
+
+const
+  RawFileExtensions: array[0..28] of TRawExtension =
+    ((ext:'3fr'; brand:'Hasselblad'),
+     (ext:'ari'; brand:'Arri_Alexa'),
+     (ext:'arw;srf;sr2'; brand:'Sony'),
+     (ext:'bay'; brand:'Casio'),
+     (ext:'braw'; brand:'Blackmagic Design'),
+     (ext:'cri'; brand:'Cintel'),
+     (ext:'crw;cr2;cr3'; brand:'Canon'),
+     (ext:'cap;iiq;eip'; brand:'Phase_One'),
+     (ext:'dcs;dcr;drf;k25;kdc'; brand:'Kodak'),
+     (ext:'dng'; brand:'Adobe'),
+     (ext:'erf'; brand:'Epson'),
+     (ext:'fff'; brand:'Imacon/Hasselblad raw'),
+     (ext:'gpr'; brand:'GoPro'),
+     (ext:'mef'; brand:'Mamiya'),
+     (ext:'mdc'; brand:'Minolta, Agfa'),
+     (ext:'mos'; brand:'Leaf'),
+     (ext:'mrw'; brand:'Minolta, Konica Minolta'),
+     (ext:'nef;nrw'; brand:'Nikon'),
+     (ext:'orf'; brand:'Olympus'),
+     (ext:'pef;ptx'; brand:'Pentax'),
+     (ext:'pxn'; brand:'Logitech'),
+     (ext:'R3D'; brand:'RED Digital Cinema'),
+     (ext:'raf'; brand:'Fuji'),
+     (ext:'raw'; brand:'Panasonic/Leica'),
+     (ext:'rw2'; brand:'Panasonic'),
+     (ext:'rwl;dng'; brand:'Leica'),
+     (ext:'rwz'; brand:'Rawzor'),
+     (ext:'srw'; brand:'Samsung'),
+     (ext:'x3f'; brand:'Sigma'));
+
+var
+  AllRawExtensions: string;
+
+function GetRawStreamThumbnail(AStream: TStream; AWidth,AHeight: integer;
+  ABackColor: TBGRAPixel; ACheckers: boolean; ADest: TBGRABitmap= nil): TBGRABitmap;
+function GetRawStreamImage(AStream: TStream): TBGRABitmap;
+function IsRawFilename(AFilename: string): boolean;
+function GetRawFileImage(AFilename: string): TBGRABitmap;
+
+implementation
+
+uses process, BGRAThumbnail, UResourceStrings, UFileSystem, Forms;
+
+function GetAllRawExtensions: string;
+var
+  i: Integer;
+begin
+  result := '';
+  for i := low(RawFileExtensions) to high(RawFileExtensions) do
+  begin
+    if result <> '' then result += ';';
+    result += RawFileExtensions[i].ext;
+  end;
+end;
+
+procedure RunDCRaw(AOptions: array of string;
+  AInputStream, AOutputStream: TStream);
+var
+  tempName,tempOutName: String;
+  s: TFileStream;
+  p: TProcess;
+  available: DWord;
+  i: Integer;
+  consoleOut, tiffOut: boolean;
+begin
+  tempName := '';
+  p := nil;
+  try
+    tempName := GetTempFileName;
+    s := TFileStream.Create(tempName, fmCreate);
+    try
+      s.CopyFrom(AInputStream, AInputStream.Size);
+    finally
+      s.Free;
+    end;
+
+    p := TProcess.Create(nil);
+    try
+      p.Options:= p.Options+[poStderrToOutPut];
+      p.Executable:= 'dcraw';
+
+      consoleOut := false;
+      tiffOut := false;
+      for i := 0 to High(AOptions) do
+      begin
+        p.Parameters.Add(AOptions[i]);
+        if AOptions[i] = '-c' then consoleOut := true;
+        if AOptions[i] = '-T' then tiffOut := true;
+      end;
+      p.Parameters.Add(tempName);
+
+      if consoleOut then
+      begin
+        p.Options:= p.Options+[poUsePipes];
+        p.PipeBufferSize:= 524288;
+        p.Execute;
+        while p.Running do
+        begin
+          available:=P.Output.NumBytesAvailable;
+          if available > 0 then
+            AOutputStream.CopyFrom(P.Output, available)
+          else
+            sleep(30);
+        end;
+        available:=P.Output.NumBytesAvailable;
+        if available > 0 then
+          AOutputStream.CopyFrom(P.Output, available);
+      end else
+      begin
+        if tiffOut then
+          tempOutName := ChangeFileExt(tempName, '.tiff')
+        else
+          tempOutName := ChangeFileExt(tempName, '.ppm');
+        p.Execute;
+        try
+          p.WaitOnExit;
+          if not FileExists(tempOutName) then
+            raise exception.Create(rsErrorDecodingRaw);
+          s := TFileStream.Create(tempOutName, fmOpenRead);
+          try
+            AOutputStream.CopyFrom(s, s.Size);
+          finally
+            s.Free;
+          end;
+        finally
+          if FileExists(tempOutName) then DeleteFile(tempOutName);
+        end;
+      end;
+    finally
+      FreeAndNil(p);
+    end;
+  finally
+    if FileExists(tempName) then DeleteFile(tempName);
+  end;
+end;
+
+function GetRawStreamThumbnail(AStream: TStream; AWidth, AHeight: integer;
+  ABackColor: TBGRAPixel; ACheckers: boolean; ADest: TBGRABitmap): TBGRABitmap;
+var
+  thumbData: TMemoryStream;
+begin
+  result := nil;
+  thumbData := TMemoryStream.Create;
+  try
+    RunDCRaw(['-c','-e'],AStream,thumbData);
+    thumbData.Position:= 0;
+    result := GetStreamThumbnail(thumbData, AWidth,AHeight, ABackColor,ACheckers,'',ADest);
+  finally
+    thumbData.Free;
+  end;
+end;
+
+function GetRawStreamImage(AStream: TStream): TBGRABitmap;
+var
+  imageData: TMemoryStream;
+  prevCursor: TCursor;
+begin
+  prevCursor := Screen.Cursor;
+  Screen.Cursor:= crHourGlass;
+  result := nil;
+  imageData := TMemoryStream.Create;
+  try
+    RunDCRaw(['-T'],AStream,imageData);
+    imageData.Position:= 0;
+    result := TBGRABitmap.Create(imageData);
+  finally
+    imageData.Free;
+    Screen.Cursor:= prevCursor;
+  end;
+end;
+
+function IsRawFilename(AFilename: string): boolean;
+var
+  ext: String;
+begin
+  ext := LowerCase(ExtractFileExt(AFilename));
+  delete(ext,1,1);
+  result := Pos(';'+ext+';',';'+AllRawExtensions+';') <> 0;
+end;
+
+function GetRawFileImage(AFilename: string): TBGRABitmap;
+var
+  s: TStream;
+begin
+  s := FileManager.CreateFileStream(AFilename, fmOpenRead);
+  result := nil;
+  try
+    result := GetRawStreamImage(s);
+  finally
+    s.Free;
+  end;
+end;
+
+initialization
+
+  AllRawExtensions := GetAllRawExtensions;
+
+end.
+

+ 2 - 0
lazpaint/uresourcestrings.pas

@@ -30,6 +30,7 @@ resourcestring
   rsEnterLayerName='Enter layer name:';
   rsFileExtensionNotSupported='This file extension is not supported.';
   rsFileFormatNotRecognized='The file format has not been recognized.';
+  rsErrorDecodingRaw='Error decoding raw image.';
   rsErrorLoadingOriginal='Error while loading original however layer can be rasterized.';
   rsRasterLayer = 'Raster layer';
   rsTransformedRasterLayer = 'Transformed raster layer';
@@ -95,6 +96,7 @@ resourcestring
 
   rsRepeatImage='Repeat image';
   rsCanvasSize='Canvas size';
+  rsResamplingImage='Resampling image...';
 
   rsRed='Red';
   rsGreen='Green';