1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/common/imagpnm.cpp
3 // Purpose:     wxImage PNM handler
4 // Author:      Sylvain Bougnoux
5 // Copyright:   (c) Sylvain Bougnoux
6 // Licence:     wxWindows licence
7 /////////////////////////////////////////////////////////////////////////////
8 
9 // For compilers that support precompilation, includes "wx.h".
10 #include "wx/wxprec.h"
11 
12 #ifdef __BORLANDC__
13     #pragma hdrstop
14 #endif
15 
16 #if wxUSE_IMAGE && wxUSE_PNM
17 
18 #include "wx/imagpnm.h"
19 
20 #ifndef WX_PRECOMP
21     #include "wx/intl.h"
22     #include "wx/log.h"
23 #endif
24 
25 #include "wx/txtstrm.h"
26 
27 //-----------------------------------------------------------------------------
28 // wxBMPHandler
29 //-----------------------------------------------------------------------------
30 
IMPLEMENT_DYNAMIC_CLASS(wxPNMHandler,wxImageHandler)31 IMPLEMENT_DYNAMIC_CLASS(wxPNMHandler,wxImageHandler)
32 
33 #if wxUSE_STREAMS
34 
35 void Skip_Comment(wxInputStream &stream)
36 {
37     wxTextInputStream text_stream(stream);
38 
39     if (stream.Peek()==wxT('#'))
40     {
41         text_stream.ReadLine();
42         Skip_Comment(stream);
43     }
44 }
45 
LoadFile(wxImage * image,wxInputStream & stream,bool verbose,int WXUNUSED (index))46 bool wxPNMHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int WXUNUSED(index) )
47 {
48     wxUint32  width, height;
49     wxUint16  maxval;
50     char      c(0);
51 
52     image->Destroy();
53 
54     /*
55      * Read the PNM header
56      */
57 
58     wxBufferedInputStream buf_stream(stream);
59     wxTextInputStream text_stream(buf_stream);
60 
61     Skip_Comment(buf_stream);
62     if (buf_stream.GetC()==wxT('P')) c=buf_stream.GetC();
63 
64     switch (c)
65     {
66         case wxT('2'): // ASCII Grey
67         case wxT('3'): // ASCII RGB
68         case wxT('5'): // RAW Grey
69         case wxT('6'): break;
70         default:
71             if (verbose)
72             {
73                 wxLogError(_("PNM: File format is not recognized."));
74             }
75             return false;
76     }
77 
78     text_stream.ReadLine(); // for the \n
79     Skip_Comment(buf_stream);
80     text_stream >> width >> height ;
81     Skip_Comment(buf_stream);
82     text_stream >> maxval;
83 
84     //cout << line << " " << width << " " << height << " " << maxval << endl;
85     image->Create( width, height );
86     unsigned char *ptr = image->GetData();
87     if (!ptr)
88     {
89         if (verbose)
90         {
91            wxLogError( _("PNM: Couldn't allocate memory.") );
92         }
93         return false;
94     }
95 
96 
97     if (c=='2') // Ascii GREY
98     {
99         wxUint32 value, size=width*height;
100         for (wxUint32 i=0; i<size; ++i)
101         {
102             value=text_stream.Read32();
103             if ( maxval != 255 )
104                 value = (255 * value)/maxval;
105             *ptr++=(unsigned char)value; // R
106             *ptr++=(unsigned char)value; // G
107             *ptr++=(unsigned char)value; // B
108             if ( !buf_stream )
109             {
110                 if (verbose)
111                 {
112                     wxLogError(_("PNM: File seems truncated."));
113                 }
114                 return false;
115             }
116         }
117     }
118     if (c=='3') // Ascii RBG
119     {
120         wxUint32 value, size=3*width*height;
121         for (wxUint32 i=0; i<size; ++i)
122           {
123             //this is very slow !!!
124             //I wonder how we can make any better ?
125             value=text_stream.Read32();
126             if ( maxval != 255 )
127                 value = (255 * value)/maxval;
128             *ptr++=(unsigned char)value;
129 
130             if ( !buf_stream )
131               {
132                 if (verbose)
133                 {
134                     wxLogError(_("PNM: File seems truncated."));
135                 }
136                 return false;
137               }
138           }
139     }
140     if (c=='5') // Raw GREY
141     {
142         wxUint32 size=width*height;
143         unsigned char value;
144         for (wxUint32 i=0; i<size; ++i)
145         {
146             buf_stream.Read(&value,1);
147             if ( maxval != 255 )
148                 value = (255 * value)/maxval;
149             *ptr++=value; // R
150             *ptr++=value; // G
151             *ptr++=value; // B
152             if ( !buf_stream )
153             {
154                 if (verbose)
155                 {
156                     wxLogError(_("PNM: File seems truncated."));
157                 }
158                 return false;
159             }
160         }
161     }
162 
163     if ( c=='6' ) // Raw RGB
164     {
165         buf_stream.Read(ptr, 3*width*height);
166         if ( maxval != 255 )
167         {
168             for ( unsigned i = 0; i < 3*width*height; i++ )
169                 ptr[i] = (255 * ptr[i])/maxval;
170         }
171     }
172 
173     image->SetMask( false );
174 
175     const wxStreamError err = buf_stream.GetLastError();
176     return err == wxSTREAM_NO_ERROR || err == wxSTREAM_EOF;
177 }
178 
SaveFile(wxImage * image,wxOutputStream & stream,bool WXUNUSED (verbose))179 bool wxPNMHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool WXUNUSED(verbose) )
180 {
181     wxTextOutputStream text_stream(stream);
182 
183     //text_stream << "P6" << endl
184     //<< image->GetWidth() << " " << image->GetHeight() << endl
185     //<< "255" << endl;
186     text_stream << wxT("P6\n") << image->GetWidth() << wxT(" ") << image->GetHeight() << wxT("\n255\n");
187     stream.Write(image->GetData(),3*image->GetWidth()*image->GetHeight());
188 
189     return stream.IsOk();
190 }
191 
DoCanRead(wxInputStream & stream)192 bool wxPNMHandler::DoCanRead( wxInputStream& stream )
193 {
194     Skip_Comment(stream);
195 
196     // it's ok to modify the stream position here
197     if ( stream.GetC() == 'P' )
198     {
199         switch ( stream.GetC() )
200         {
201             case '2': // ASCII Grey
202             case '3': // ASCII RGB
203             case '5': // RAW Grey
204             case '6': // RAW RGB
205                 return true;
206         }
207     }
208 
209     return false;
210 }
211 
212 
213 #endif // wxUSE_STREAMS
214 
215 #endif // wxUSE_IMAGE && wxUSE_PNM
216