fpwritepnm.pp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. {*****************************************************************************}
  2. {
  3. This file is part of the Free Pascal's "Free Components Library".
  4. Copyright (c) 2003 by Mazen NEIFER of the Free Pascal development team
  5. PNM writer implementation.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. }
  12. {*****************************************************************************}
  13. {Support for writing PNM (Portable aNyMap) formats added :
  14. * PBM (P1,P4) : Portable BitMap format : 1 bit per pixel
  15. * PGM (P2,P5) : Portable GrayMap format : 8 bits per pixel
  16. * PPM (P5,P6) : Portable PixelMap foramt : 24 bits per pixel}
  17. {$mode objfpc}{$h+}
  18. unit FPWritePNM;
  19. interface
  20. uses FPImage, classes, sysutils;
  21. type
  22. TFPWriterPNM = class(TFPCustomImageWriter)
  23. private
  24. BitMapType:Integer;
  25. protected
  26. procedure InternalWrite(Stream:TStream;Img:TFPCustomImage);override;
  27. public
  28. constructor Create(aBitMapType:Integer);
  29. end;
  30. implementation
  31. constructor TFPWriterPNM.Create(aBitMapType:Integer);
  32. begin
  33. inherited Create;
  34. BitMapType:=aBitMapType;
  35. end;
  36. procedure TFPWriterPNM.InternalWrite(Stream:TStream;Img:TFPCustomImage);
  37. function SaveHeader(stream:TStream):boolean;
  38. const
  39. MagicWords:Array[1..6]OF String[2]=('P1','P2','P3','P4','P5','P6');
  40. var
  41. PNMInfo:String;
  42. strWidth,StrHeight:String[15];
  43. begin
  44. SaveHeader:=false;
  45. with Img do
  46. begin
  47. Str(Img.Width,StrWidth);
  48. Str(Img.Height,StrHeight);
  49. end;
  50. PNMInfo:=Concat(MagicWords[BitMapType],#10,StrWidth,#32,StrHeight,#10);
  51. if BitMapType in [2,3,5,6]
  52. then
  53. PNMInfo:=Concat(PNMInfo,'255'#10);
  54. stream.seek(0,soFromBeginning);
  55. stream.Write(PNMInfo[1],Length(PNMInfo));
  56. SaveHeader := true;
  57. end;
  58. var
  59. Row,Coulumn,nBpLine,i:Integer;
  60. aColor:TFPColor;
  61. aLine:PByte;
  62. strCol:String[3];
  63. begin
  64. SaveHeader(Stream);
  65. case BitMapType of
  66. 1:nBpLine:=Img.Width*2;{p p p}
  67. 2:nBpLine:=Img.Width*4;{lll lll lll}
  68. 3:nBpLine:=Img.Width*3*4;{rrr ggg bbb rrr ggg bbb}
  69. 4:begin
  70. nBpLine:=Img.Width SHR 3;
  71. if(Img.Width AND $0F)<>0
  72. then
  73. Inc(nBpLine);
  74. end;
  75. 5:nBpLine:=Img.Width;
  76. 6:nBpLine:=Img.Width*3;
  77. end;
  78. GetMem(aLine,nBpLine);//3 extra byte for BMP 4Bytes alignement.
  79. for Row:=0 to img.Height-1 do
  80. begin
  81. FillChar(aLine^,nBpLine,0);
  82. for Coulumn:=0 to img.Width-1 do
  83. begin
  84. aColor:=img.Colors[Coulumn,Row];
  85. with aColor do
  86. case BitMapType of
  87. 1:begin
  88. if(Red<=$2F00)or(Green<=$2F00)or(Blue<=$2F00)
  89. then
  90. aLine[2*Coulumn]:=Ord('1')
  91. else
  92. aLine[2*Coulumn]:=Ord('0');
  93. aLine[2*Coulumn+1]:=32;
  94. end;
  95. 2:begin
  96. Str(Hi(Word(Round(Red*0.299+Green*0.587+Blue*0.114))),strCol);
  97. for i:=0 to Length(StrCol)-1 do
  98. aLine[4*Coulumn+i]:=Ord(StrCol[i+1]);
  99. for i:=Length(StrCol) to 4 do
  100. aLine[4*Coulumn+i]:=32;
  101. end;
  102. 3:begin
  103. Str(Hi(Red),strCol);
  104. for i:=0 to Length(StrCol)-1 do
  105. aLine[4*(3*Coulumn)+i]:=Ord(StrCol[i+1]);
  106. for i:=Length(StrCol) to 4 do
  107. aLine[4*(3*Coulumn)+i]:=32;
  108. Str(Hi(Green),strCol);
  109. for i:=0 to Length(StrCol)-1 do
  110. aLine[4*(3*Coulumn+1)+i]:=Ord(StrCol[i+1]);
  111. for i:=Length(StrCol) to 4 do
  112. aLine[4*(3*Coulumn+1)+i]:=32;
  113. Str(Hi(Blue),strCol);
  114. for i:=0 to Length(StrCol)-1 do
  115. aLine[4*(3*Coulumn+2)+i]:=Ord(StrCol[i+1]);
  116. for i:=Length(StrCol) to 4 do
  117. aLine[4*(3*Coulumn+2)+i]:=32;
  118. end;
  119. 4:if(Red<=$2F00)or(Green<=$2F00)or(Blue<=$2F00)
  120. then
  121. aLine[Coulumn shr 3]:=aLine[Coulumn shr 3] or ($80 shr (Coulumn and $07));
  122. 5:aLine[Coulumn]:=Hi(Word(Round(Red*0.299+Green*0.587+Blue*0.114)));
  123. 6:begin
  124. aLine[3*Coulumn]:=Hi(Red);
  125. aLine[3*Coulumn+1]:=Hi(Green);
  126. aLine[3*Coulumn+2]:=Hi(Blue);
  127. end;
  128. end;
  129. end;
  130. Stream.Write(aLine^,nBpLine);
  131. end;
  132. FreeMem(aLine,nBpLine);
  133. end;
  134. initialization
  135. ImageHandlers.RegisterImageWriter ('PBM Format', 'pbm', TFPWriterPNM);
  136. end.