unit MergeFileUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ImageFile;

type
  TMergeFilesFrm = class(TForm)
    GroupBox1: TGroupBox;
    edFirstFileName: TEdit;
    bFirstFileName: TButton;
    edLastFileName: TEdit;
    bLastFileName: TButton;
    bMergeFiles: TButton;
    bCancel: TButton;
    ImageFile: TImageFile;
    MergeFile: TImageFile;
    OpenDialog: TOpenDialog;
    Label1: TLabel;
    Label2: TLabel;
    procedure bMergeFilesClick(Sender: TObject);
    procedure bFirstFileNameClick(Sender: TObject);
    procedure bLastFileNameClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
    procedure FindIndexNumber(
          FileName : String ;             // File name with index number
          var StartAt : Integer ;         // Start character of number
          var EndAt : Integer ;           // End character of number
          var sNum : string               // Number string
          ) ;

  public
    { Public declarations }
  end;

var
  MergeFilesFrm: TMergeFilesFrm;

implementation

uses PicViewMain;

{$R *.dfm}

procedure TMergeFilesFrm.bMergeFilesClick(Sender: TObject);
// --------------------------------------------
// Merge list of selected file into single file
// --------------------------------------------
// 25.06.09

var
   FileNum : Integer ;
   ImportFileName : String ;
   OutFileName : String ;
   iFrame : Integer ;           // Frame counter
   NumFramesImported : Integer ; // No. of frames imported
   PFrameBuf : Pointer ;        // Image frame buffer pointer
   i,iIncrement : Integer ;
   StartAt,EndAt : Integer ;
   sStartNum,sEndNum,sNum : String ;
   Done,FirstFile : Boolean ;
begin

    if not FileExists( edFirstFileName.text ) then begin
       ShowMessage('Start: '+ edFirstFileName.text + ' does not exist!') ;
       Exit ;
       end ;

    if not FileExists( edLastFileName.text ) then begin
       ShowMessage('End: ' + edLastFileName.text + ' does not exist!') ;
       Exit ;
       end ;

    PFrameBuf := Nil ;

    // Import frames from all files in list
    NumFramesImported := 0 ;

    // Create output file to hold images
    FindIndexNumber( edLastFileName.text, StartAt,EndAt,sEndNum ) ;
    FindIndexNumber( edFirstFileName.text, StartAt,EndAt,sStartNum ) ;
    OutFileName := edFirstFileName.text ;
    Delete( OutFileName, StartAt, Length(sStartNum) ) ;
    Insert( '[Merged ' + sStartNum + '-' + sEndNum + ']', OutFileName, StartAt ) ;
    // Create PIC file if source is gray scale, TIF if RGB
    if ImageFile.ComponentsPerPixel > 1 then OutFileName := ChangeFileExt(OutFileName,'.tif')
                                        else OutFileName := ChangeFileExt(OutFileName,'.pic') ;


    // Copy sourcefiles into output file
    // ---------------------------------

    ImportFileName := edFirstFileName.text ;
    Done := False ;
    FirstFile := True ;
    repeat

        // Skip if file does not exist
        if FileExists( ImportFileName ) then begin ;

          // Terminate if unable to open file
          if not ImageFile.OpenFile( ImportFileName ) then begin
             MainFrm.StatusBar.SimpleText := 'MERGE FILES: Unable to open : ' + ImportFileName ;
             Break ;
            end ;

          if FirstFile then begin
             // Create output file
             MergeFile.CreateFile( OutFileName,
                                   ImageFile.FrameWidth,
                                   ImageFile.FrameHeight,
                                   ImageFile.PixelDepth,
                                   ImageFile.ComponentsPerPixel,
                                   False ) ;

             // Get file calibration factors
             MergeFile.XResolution := ImageFile.XResolution ;
             MergeFile.YResolution := ImageFile.YResolution ;
             MergeFile.ZResolution := ImageFile.ZResolution ;
             MergeFile.TResolution := ImageFile.TResolution ;

             // Allocate frame buffer
             GetMem( PFrameBuf,MergeFile.NumBytesPerFrame ) ;

             FirstFile := False ;
             end
          else begin
             // Terminate merge if image properties change
             if (MergeFile.FrameWidth <> ImageFile.FrameWidth) or
                (MergeFile.FrameHeight <> ImageFile.FrameHeight) or
                (MergeFile.PixelDepth <> ImageFile.PixelDepth) or
                (MergeFile.ComponentsPerPixel <> ImageFile.ComponentsPerPixel) then begin
                MainFrm.StatusBar.SimpleText := 'MERGE FILES: Aborted at ' + ImportFileName ;
                ImageFile.CloseFile ;
                Break ;
                end ;
             end ;

          // Import frames from this file
          for iFrame := 1 to ImageFile.NumFrames do begin
              if ImageFile.LoadFrame( iFrame, PFrameBuf ) then begin
                 Inc(NumFramesImported) ;
                 MergeFile.SaveFrame( NumFramesImported, PFrameBuf ) ;
                 MainFrm.StatusBar.SimpleText := format(
                 'MERGE FILES: Copying %.3d/%.3d frames from %s to %s',
                 [iFrame,
                  ImageFile.NumFrames,
                  ExtractFileName(ImportFileName),
                  ExtractFileName(OutFileName)
                  ]) ;
                 end ;
               end ;

             // Close this import file
             ImageFile.CloseFile ;

             end ;

        if ImportFileName = edLastFileName.text then Done := True ;

        // Increment file index number by one
        FindIndexNumber( ImportFilename, StartAt, EndAt, sNum ) ;
        iIncrement := Length(sNum) ;
        for i := Length(sNum) downto 1 do begin
            if i = iIncrement then begin
               sNum[i] := chr( Ord(sNum[i]) + 1 ) ;
               if Ord(sNum[i]) = (Ord('9') + 1) then begin
                  Dec(iIncrement) ;
                  sNum[i] := '0' ;
                  end ;
               end ;
            end ;
        if iIncrement = 0 then sNum := '1' + sNum ;

        Delete(ImportFilename, StartAt, EndAt - StartAt + 1 ) ;
        Insert(sNum, ImportFilename, StartAt ) ;

        until Done ;

    // Close output file
    MergeFile.CloseFile ;

    if PFrameBuf <> Nil then FreeMem( PFrameBuf ) ;

    // Display file
    if NumFramesImported > 0 then begin
       Mainfrm.CreateNewViewFrm( OutFileName ) ;
       MainFrm.StatusBar.SimpleText := 'MERGE FILES: ' + OutFileName + ' created.' ;
       end ;

    end ;

procedure TMergeFilesFrm.FindIndexNumber(
          FileName : String ;             // File name with index number
          var StartAt : Integer ;         // Start character of number
          var EndAt : Integer ;           // End character of number
          var sNum : string               // Number string
          ) ;
var
    i : Integer ;
    Done : Boolean ;
begin

    i := Length(FileName) ;
    StartAt := 1 ;
    EndAt := 0 ;
    Done := False ;
    Repeat
       if FileName[i] in ['0'..'9'] then begin
          if EndAt = 0 then  EndAt := i ;
          StartAt := i ;
          end
       else if Endat <> 0 then Done := True ;
       Dec(i) ;
       until (i<=0) or Done ;

    sNum := '' ;
    for i := StartAt to EndAt do sNum := sNum + FileName[i] ;

    end ;


procedure TMergeFilesFrm.bFirstFileNameClick(Sender: TObject);
// --------------------------
// Select first file in range
// --------------------------
begin

    // Setup Open Files dialog box
    OpenDialog.options := [ofPathMustExist] ;
    if MainFrm.DataDirectory <> '' then OpenDialog.InitialDir := MainFrm.DataDirectory ;
    OpenDialog.Title := 'First File ' ;

    // Exit if no file name available
    if (not OpenDialog.Execute) or (OpenDialog.Files.Count <= 0) then Exit ;

    edFirstFileName.Text := OpenDialog.FileName ;

    end ;

procedure TMergeFilesFrm.bLastFileNameClick(Sender: TObject);
// --------------------------
// Select last file in range
// --------------------------
begin

    // Setup Open Files dialog box
    OpenDialog.options := [ofPathMustExist] ;
    if MainFrm.DataDirectory <> '' then OpenDialog.InitialDir := MainFrm.DataDirectory ;
    OpenDialog.Title := 'First File ' ;

    // Exit if no file name available
    if (not OpenDialog.Execute) or (OpenDialog.Files.Count <= 0) then Exit ;

    edLastFileName.Text := OpenDialog.FileName ;

    end ;

procedure TMergeFilesFrm.FormShow(Sender: TObject);
// -----------------------------------
// Initialisations when form displayed
// -----------------------------------
begin
     OpenDialog.Filter :=
     'BIORad PIC Files (*.PIC)|*.PIC|' +
     'TIFF Files (*.TIF)|*.TIF|' +
     'STK Files (*.STK)|*.STK' ;

      end;

end.
