⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rm_e_tiff.pas

📁 这是一个功能强大
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit RM_e_Tiff;

interface

{$I RM.INC}

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, RM_Class, RM_E_Graphic
  {$IFDEF USE_IMAGEEN}
  , imageenio, TIFLZW
  {$ENDIF};

type

  { TRMTiffExport }
  TRMTiffExport = class(TRMGraphicExport)
  private
    FMonochrome: Boolean;
    FPixelFormat: TPixelFormat;
    {$IFDEF USE_IMAGEEN}
    FImageEnIO: TImageEnIO;
    {$ENDIF}
  protected
    procedure InternalOnePage(aPage: TRMEndPage); override;
    procedure OnExportPage(const aPage: TRMEndPage); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    function ShowModal: Word; override;
  published
    property Monochrome: Boolean read FMonochrome write FMonochrome default False;
    property PixelFormat: TPixelFormat read FPixelFormat write FPixelFormat default pf24bit;
  end;

  { TRMBMPExportForm }
  TRMTiffExportForm = class(TForm)
    gbBMP: TGroupBox;
    chkMonochrome: TCheckBox;
    btnOK: TButton;
    btnCancel: TButton;
    Label1: TLabel;
    Label2: TLabel;
    edScaleX: TEdit;
    Label3: TLabel;
    edScaleY: TEdit;
    Label4: TLabel;
    cmbPixelFormat: TComboBox;
    procedure FormCreate(Sender: TObject);
  private
  protected
    procedure Localize;
  public
  end;

implementation

{$R *.DFM}

uses RM_Common, RM_Const, RM_Utils;

type
  PDirEntry = ^TDirEntry;
  TDirEntry = record
    _Tag: Word;
    _Type: Word;
    _Count: LongInt;
    _Value: LongInt;
  end;

const
  TifHeader: array[0..7] of Byte = (
    $49, $49, { Intel byte order }
    $2A, $00, { TIFF version (42) }
    $08, $00, $00, $00); { Pointer to the first directory }

  NoOfDirs: array[0..1] of Byte = ($0F, $00); { Number of tags within the directory }

  DirectoryBW: array[0..13] of TDirEntry = (
    (_Tag: $00FE; _Type: $0004; _Count: $00000001; _Value: $00000000), { NewSubFile: Image with full solution (0) }
    (_Tag: $0100; _Type: $0003; _Count: $00000001; _Value: $00000000), { ImageWidth:      Value will be set later }
    (_Tag: $0101; _Type: $0003; _Count: $00000001; _Value: $00000000), { ImageLength:     Value will be set later }
    (_Tag: $0102; _Type: $0003; _Count: $00000001; _Value: $00000001), { BitsPerSample:   1                       }
    (_Tag: $0103; _Type: $0003; _Count: $00000001; _Value: $00000001), { Compression:     No compression          }
    (_Tag: $0106; _Type: $0003; _Count: $00000001; _Value: $00000001), { PhotometricInterpretation:   0, 1        }
    (_Tag: $0111; _Type: $0004; _Count: $00000001; _Value: $00000000), { StripOffsets: Ptr to the adress of the image data }
    (_Tag: $0115; _Type: $0003; _Count: $00000001; _Value: $00000001), { SamplesPerPixels: 1                      }
    (_Tag: $0116; _Type: $0004; _Count: $00000001; _Value: $00000000), { RowsPerStrip: Value will be set later    }
    (_Tag: $0117; _Type: $0004; _Count: $00000001; _Value: $00000000), { StripByteCounts: xs*ys bytes pro strip   }
    (_Tag: $011A; _Type: $0005; _Count: $00000001; _Value: $00000000), { X-Resolution: Adresse                    }
    (_Tag: $011B; _Type: $0005; _Count: $00000001; _Value: $00000000), { Y-Resolution: (Adresse)                  }
    (_Tag: $0128; _Type: $0003; _Count: $00000001; _Value: $00000002), { Resolution Unit: (2)= Unit ZOLL          }
    (_Tag: $0131; _Type: $0002; _Count: $0000000A; _Value: $00000000)); { Software:                                }

  DirectoryCOL: array[0..14] of TDirEntry = (
    (_Tag: $00FE; _Type: $0004; _Count: $00000001; _Value: $00000000), { NewSubFile: Image with full solution (0) }
    (_Tag: $0100; _Type: $0003; _Count: $00000001; _Value: $00000000), { ImageWidth:      Value will be set later }
    (_Tag: $0101; _Type: $0003; _Count: $00000001; _Value: $00000000), { ImageLength:     Value will be set later }
    (_Tag: $0102; _Type: $0003; _Count: $00000001; _Value: $00000008), { BitsPerSample:   4 or 8                  }
    (_Tag: $0103; _Type: $0003; _Count: $00000001; _Value: $00000001), { Compression:     No compression          }
    (_Tag: $0106; _Type: $0003; _Count: $00000001; _Value: $00000003), { PhotometricInterpretation:   3           }
    (_Tag: $0111; _Type: $0004; _Count: $00000001; _Value: $00000000), { StripOffsets: Ptr to the adress of the image data }
    (_Tag: $0115; _Type: $0003; _Count: $00000001; _Value: $00000001), { SamplesPerPixels: 1                      }
    (_Tag: $0116; _Type: $0004; _Count: $00000001; _Value: $00000000), { RowsPerStrip: Value will be set later    }
    (_Tag: $0117; _Type: $0004; _Count: $00000001; _Value: $00000000), { StripByteCounts: xs*ys bytes pro strip   }
    (_Tag: $011A; _Type: $0005; _Count: $00000001; _Value: $00000000), { X-Resolution: Adresse                    }
    (_Tag: $011B; _Type: $0005; _Count: $00000001; _Value: $00000000), { Y-Resolution: (Adresse)                  }
    (_Tag: $0128; _Type: $0003; _Count: $00000001; _Value: $00000002), { Resolution Unit: (2)= Unit ZOLL          }
    (_Tag: $0131; _Type: $0002; _Count: $0000000A; _Value: $00000000), { Software:                                }
    (_Tag: $0140; _Type: $0003; _Count: $00000300; _Value: $00000008)); { ColorMap: Color table startadress        }

  DirectoryRGB: array[0..14] of TDirEntry = (
    (_Tag: $00FE; _Type: $0004; _Count: $00000001; _Value: $00000000), { NewSubFile:      Image with full solution (0) }
    (_Tag: $0100; _Type: $0003; _Count: $00000001; _Value: $00000000), { ImageWidth:      Value will be set later      }
    (_Tag: $0101; _Type: $0003; _Count: $00000001; _Value: $00000000), { ImageLength:     Value will be set later      }
    (_Tag: $0102; _Type: $0003; _Count: $00000003; _Value: $00000008), { BitsPerSample:   8                            }
    (_Tag: $0103; _Type: $0003; _Count: $00000001; _Value: $00000001), { Compression:     No compression               }
    (_Tag: $0106; _Type: $0003; _Count: $00000001; _Value: $00000002), { PhotometricInterpretation:
    0=black, 2 power BitsPerSample -1 =white }
    (_Tag: $0111; _Type: $0004; _Count: $00000001; _Value: $00000000), { StripOffsets: Ptr to the adress of the image data }
    (_Tag: $0115; _Type: $0003; _Count: $00000001; _Value: $00000003), { SamplesPerPixels: 3                         }
    (_Tag: $0116; _Type: $0004; _Count: $00000001; _Value: $00000000), { RowsPerStrip: Value will be set later         }
    (_Tag: $0117; _Type: $0004; _Count: $00000001; _Value: $00000000), { StripByteCounts: xs*ys bytes pro strip        }
    (_Tag: $011A; _Type: $0005; _Count: $00000001; _Value: $00000000), { X-Resolution: Adresse                         }
    (_Tag: $011B; _Type: $0005; _Count: $00000001; _Value: $00000000), { Y-Resolution: (Adresse)                       }
    (_Tag: $011C; _Type: $0003; _Count: $00000001; _Value: $00000001), { PlanarConfiguration:
    Pixel data will be stored continous         }
    (_Tag: $0128; _Type: $0003; _Count: $00000001; _Value: $00000002), { Resolution Unit: (2)= Unit ZOLL               }
    (_Tag: $0131; _Type: $0002; _Count: $0000000A; _Value: $00000000)); { Software:                                   }

  NullString: array[0..3] of Byte = ($00, $00, $00, $00);
  X_Res_Value: array[0..7] of Byte = ($6D, $03, $00, $00, $0A, $00, $00, $00); { Value for X-Resolution:
  87,7 Pixel/Zoll (SONY SCREEN) }
  Y_Res_Value: array[0..7] of Byte = ($6D, $03, $00, $00, $0A, $00, $00, $00); { Value for Y-Resolution: 87,7 Pixel/Zoll }
  Software: array[0..9] of Char = ('K', 'r', 'u', 'w', 'o', ' ', 's', 'o', 'f', 't');
  BitsPerSample: array[0..2] of Word = ($0008, $0008, $0008);

procedure WriteTiffToStream(Stream: TStream; Bitmap: TBitmap);
var
  BM: HBitmap;
  Header, Bits: PChar;
  BitsPtr: PChar;
  TmpBitsPtr: PChar;
  HeaderSize: {$IFDEF WINDOWS}INTEGER{$ELSE}DWORD{$ENDIF};
  BitsSize: {$IFDEF WINDOWS}LongInt{$ELSE}DWORD{$ENDIF};
  Width, Height: {$IFDEF WINDOWS}LongInt{$ELSE}Integer{$ENDIF};
  DataWidth: {$IFDEF WINDOWS}LongInt{$ELSE}Integer{$ENDIF};
  BitCount: {$IFDEF WINDOWS}LongInt{$ELSE}Integer{$ENDIF};
  ColorMapRed: array[0..255, 0..1] of Byte;
  ColorMapGreen: array[0..255, 0..1] of Byte;
  ColorMapBlue: array[0..255, 0..1] of Byte;
  ColTabSize: Integer;
  I, K: {$IFDEF WINDOWS}LongInt{$ELSE}Integer{$ENDIF};
  Red, Blue: Char;
  {$IFDEF WINDOWS}
  RGBArr: packed array[0..2] of CHAR;
  {$ENDIF}
  BmpWidth: {$IFDEF WINDOWS}LongInt{$ELSE}Integer{$ENDIF};
  OffsetXRes: LongInt;
  OffsetYRes: LongInt;
  OffsetSoftware: LongInt;
  OffsetStrip: LongInt;
  OffsetDir: LongInt;
  OffsetBitsPerSample: LongInt;
  {$IFDEF WINDOWS}
  MemHandle: THandle;
  MemStream: TMemoryStream;
  ActPos, TmpPos: LongInt;
  {$ENDIF}
begin
  BM := Bitmap.Handle;
  if BM = 0 then exit;

  GetDIBSizes(BM, HeaderSize, BitsSize);
  {$IFDEF WINDOWS}
  MemHandle := GlobalAlloc(HeapAllocFlags, HeaderSize + BitsSize);
  Header := GlobalLock(MemHandle);
  MemStream := TMemoryStream.Create;
  {$ELSE}
  GetMem(Header, HeaderSize + BitsSize);
  {$ENDIF}
  try
    Bits := Header + HeaderSize;
    if GetDIB(BM, Bitmap.Palette, Header^, Bits^) then
    begin
      { Read Image description }
      Width := PBITMAPINFO(Header)^.bmiHeader.biWidth;
      Height := PBITMAPINFO(Header)^.bmiHeader.biHeight;
      BitCount := PBITMAPINFO(Header)^.bmiHeader.biBitCount;

      {$IFDEF WINDOWS}
      { Read Bits into MemoryStream for 16 - Bit - Version }
      MemStream.Write(Bits^, BitsSize);
      {$ENDIF}

      { Count max No of Colors }
      ColTabSize := (1 shl BitCount);
      BmpWidth := Trunc(BitsSize / Height);

      { ========================================================================== }
      { 1 Bit - Bilevel-Image }
      { ========================================================================== }
      if BitCount = 1 then // Monochrome Images
      begin
        DataWidth := ((Width + 7) div 8);

        DirectoryBW[1]._Value := LongInt(Width); { Image Width    }
        DirectoryBW[2]._Value := LongInt(abs(Height)); { Image Height   }
        DirectoryBW[8]._Value := LongInt(abs(Height)); { Rows per Strip }
        DirectoryBW[9]._Value := LongInt(DataWidth * abs(Height)); { Strip Byte Counts }

        { Write TIFF - File for Bilevel-Image }
          {-------------------------------------}
          { Write Header }
        Stream.Write(TifHeader, sizeof(TifHeader));

        OffsetStrip := Stream.Position;
        { Write Image Data }

        if Height < 0 then
        begin
          for I := 0 to Height - 1 do
          begin
            {$IFNDEF WINDOWS}
            BitsPtr := Bits + I * BmpWidth;
            Stream.Write(BitsPtr^, DataWidth);
            {$ELSE}
            MemStream.Position := I * BmpWidth;
            Stream.CopyFrom(MemStream, DataWidth);
            {$ENDIF}
          end;
        end
        else
        begin
          { Flip Image }
          for I := 1 to Height do
          begin
            {$IFNDEF WINDOWS}
            BitsPtr := Bits + (Height - I) * BmpWidth;
            Stream.Write(BitsPtr^, DataWidth);
            {$ELSE}
            MemStream.Position := (Height - I) * BmpWidth;
            Stream.CopyFrom(MemStream, DataWidth);
            {$ENDIF}
          end;
        end;

        OffsetXRes := Stream.Position;
        Stream.Write(X_Res_Value, sizeof(X_Res_Value));

        OffsetYRes := Stream.Position;
        Stream.Write(Y_Res_Value, sizeof(Y_Res_Value));

        OffsetSoftware := Stream.Position;
        Stream.Write(Software, sizeof(Software));

        { Set Adresses into Directory }
        DirectoryBW[6]._Value := OffsetStrip; { StripOffset  }
        DirectoryBW[10]._Value := OffsetXRes; { X-Resolution }
        DirectoryBW[11]._Value := OffsetYRes; { Y-Resolution }
        DirectoryBW[13]._Value := OffsetSoftware; { Software     }

        { Write Directory }
        OffsetDir := Stream.Position;
        Stream.Write(NoOfDirs, sizeof(NoOfDirs));
        Stream.Write(DirectoryBW, sizeof(DirectoryBW));
        Stream.Write(NullString, sizeof(NullString));

        { Update Start of Directory }
        Stream.Seek(4, soFromBeginning);
        Stream.Write(OffsetDir, sizeof(OffsetDir));
      end;

      { ========================================================================== }
      { 4, 8, 16 Bit - Image with Color Table }
      { ========================================================================== }
      if BitCount in [4, 8, 16] then
      begin
        DataWidth := Width;
        if BitCount = 4 then
        begin
          { If we have only 4 bit per pixel, we have to
             truncate the size of the image to a byte boundary }
          Width := (Width div BitCount) * BitCount;
          if BitCount = 4 then DataWidth := Width div 2;
        end;

        DirectoryCOL[1]._Value := LongInt(Width); { Image Width   }
        DirectoryCOL[2]._Value := LongInt(abs(Height)); { Image Height  }
        DirectoryCOL[3]._Value := LongInt(BitCount); { BitsPerSample }
        DirectoryCOL[8]._Value := LongInt(Height); { Image Height  }
        DirectoryCOL[9]._Value := LongInt(DataWidth * abs(Height)); { Strip Byte Counts }

        for I := 0 to ColTabSize - 1 do
        begin
          ColorMapRed[I][1] := PBITMAPINFO(Header)^.bmiColors[I].rgbRed;
          ColorMapRed[I][0] := 0;
          ColorMapGreen[I][1] := PBITMAPINFO(Header)^.bmiColors[I].rgbGreen;
          ColorMapGreen[I][0] := 0;
          ColorMapBlue[I][1] := PBITMAPINFO(Header)^.bmiColors[I].rgbBlue;
          ColorMapBlue[I][0] := 0;
        end;

        DirectoryCOL[14]._Count := LongInt(ColTabSize * 3);

        { Write TIFF - File for Image with Color Table }
         {----------------------------------------------}
         { Write Header }
        Stream.Write(TifHeader, sizeof(TifHeader));
        Stream.Write(ColorMapRed, ColTabSize * 2);
        Stream.Write(ColorMapGreen, ColTabSize * 2);
        Stream.Write(ColorMapBlue, ColTabSize * 2);

        OffsetXRes := Stream.Position;
        Stream.Write(X_Res_Value, sizeof(X_Res_Value));

        OffsetYRes := Stream.Position;
        Stream.Write(Y_Res_Value, sizeof(Y_Res_Value));

        OffsetSoftware := Stream.Position;
        Stream.Write(Software, sizeof(Software));

        OffsetStrip := Stream.Position;
        { Write Image Data }
        if Height < 0 then
        begin
          for I := 0 to Height - 1 do
          begin
            {$IFNDEF WINDOWS}
            BitsPtr := Bits + I * BmpWidth;
            Stream.Write(BitsPtr^, DataWidth);
            {$ELSE}
            MemStream.Position := I * BmpWidth;
            Stream.CopyFrom(MemStream, DataWidth);
            {$ENDIF}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -