The attach fixes two problems I found reading pnm files:
- RGB files were not being read correctly
- byte values of 255 were overflowing.
I have adjusted the colour scaling to be compatible with what happens for .BMP files. I have not been able to do much testing, as I am short of files to test, but it works for the file I originally had problems with at least.
Colin


diff -uNr trunk/fpcsrc/fcl/image/fpreadpnm.pp trunk.w/fpcsrc/fcl/image/fpreadpnm.pp
--- trunk/fpcsrc/fcl/image/fpreadpnm.pp	2005-06-11 09:58:32.000000000 +0100
+++ trunk.w/fpcsrc/fcl/image/fpreadpnm.pp	2005-06-11 13:44:41.000000000 +0100
@@ -35,7 +35,7 @@
       FWidth      : Integer;
       FHeight     : Integer;
     protected
-      FMaxVal     : Integer;
+      FMaxVal     : Cardinal;
       FBitPP        : Byte;
       FScanLineSize : Integer;
       FScanLine   : PByte;
@@ -131,9 +131,7 @@
 procedure TFPReaderPNM.InternalRead(Stream:TStream;Img:TFPCustomImage);
 
 var
-  Row,Coulumn,nBpLine,ReadSize:Integer;
-  aColor:TFPcolor;
-  aLine:PByte;
+  Row:Integer;
 
 begin
   ReadHeader(Stream);
@@ -199,7 +197,23 @@
 Var
   C : TFPColor;
   L : Cardinal;
-  FHalfMaxVal : Word;
+  Scale: Cardinal;
+
+  function ScaleByte(B: Byte):Word;
+  begin
+    if FMaxVal = 255 then
+      Result := (B shl 8) or B { As used for reading .BMP files }
+    else { Mimic the above with multiplications }
+      Result := (B*(FMaxVal+1) + B) * 65535 div Scale;
+  end;
+
+  function ScaleWord(W: Word):Word;
+  begin
+    if FMaxVal = 65535 then
+      Result := W
+    else { Mimic the above with multiplications }
+      Result := Int64(W*(FMaxVal+1) + W) * 65535 div Scale;
+  end;
 
   Procedure ByteBnWScanLine;
 
@@ -238,7 +252,7 @@
     P:=PWord(FScanLine);
     For I:=0 to FWidth-1 do
       begin
-      L:=(((P^ shl 16)+FHalfMaxVal) div FMaxVal) and $FFFF;
+      L:=ScaleWord(P^);
       C.Red:=L;
       C.Green:=L;
       C.Blue:=L;
@@ -257,14 +271,11 @@
     P:=PWord(FScanLine);
     For I:=0 to FWidth-1 do
       begin
-      L:=(((P^ shl 16)+FHalfMaxVal) div FMaxVal) and $FFFF;
-      C.Red:=L;
+      C.Red:=ScaleWord(P^);
       Inc(P);
-      L:=(((P^ shl 16)+FHalfMaxVal) div FMaxVal) and $FFFF;
-      C.Green:=L;
+      C.Green:=ScaleWord(P^);
       Inc(P);
-      L:=(((P^ shl 16)+FHalfMaxVal) div FMaxVal) and $FFFF;
-      C.Blue:=L;
+      C.Blue:=ScaleWord(P^);
       Img.Colors[I,Row]:=C;
       Inc(P);
       end;
@@ -280,7 +291,7 @@
     P:=PByte(FScanLine);
     For I:=0 to FWidth-1 do
       begin
-      L:=(((P^ shl 16)+FHalfMaxVal) div FMaxVal) and $FFFF;
+      L:=ScaleByte(P^);
       C.Red:=L;
       C.Green:=L;
       C.Blue:=L;
@@ -299,14 +310,11 @@
     P:=PByte(FScanLine);
     For I:=0 to FWidth-1 do
       begin
-      L:=(((P^ shl 16)+FHalfMaxVal) div FMaxVal) and $FFFF;
-      C.Red:=L;
+      C.Red:=ScaleByte(P^);
       Inc(P);
-      L:=(((P^ shl 16)+FHalfMaxVal) div FMaxVal) and $FFFF;
-      C.Green:=L;
+      C.Green:=ScaleByte(P^);
       Inc(P);
-      L:=(((P^ shl 16)+FHalfMaxVal) div FMaxVal) and $FFFF;
-      C.Blue:=L;
+      C.Blue:=ScaleByte(P^);
       Img.Colors[I,Row]:=C;
       Inc(P);
       end;
@@ -314,17 +322,17 @@
 
 begin
   C.Alpha:=AlphaOpaque;
-  FHalfMaxVal:=(FMaxVal div 2);
+  Scale := FMaxVal*(FMaxVal+1) + FMaxVal;
   Case FBitmapType of
     1 : ;
     2 : WordGrayScanline;
     3 : WordRGBScanline;
     4 : ByteBnWScanLine;
-    5 : If FBitPP=1 then
+    5 : If FBitPP=8 then
           ByteGrayScanLine
         else
           WordGrayScanLine;
-    6 : If FBitPP=3 then
+    6 : If FBitPP=24 then
           ByteRGBScanLine
         else
           WordRGBScanLine;
_______________________________________________
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply via email to