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 
13 #if wxUSE_IMAGE && wxUSE_PNM
14 
15 #include "wx/imagpnm.h"
16 
17 #ifndef WX_PRECOMP
18     #include "wx/intl.h"
19     #include "wx/log.h"
20 #endif
21 
22 #include "wx/txtstrm.h"
23 
24 //-----------------------------------------------------------------------------
25 // wxBMPHandler
26 //-----------------------------------------------------------------------------
27 
28 wxIMPLEMENT_DYNAMIC_CLASS(wxPNMHandler,wxImageHandler);
29 
30 #if wxUSE_STREAMS
31 
32 static
Skip_Comment(wxInputStream & stream)33 void Skip_Comment(wxInputStream &stream)
34 {
35     wxTextInputStream text_stream(stream);
36 
37     if (stream.Peek()==wxT('#'))
38     {
39         text_stream.ReadLine();
40         Skip_Comment(stream);
41     }
42 }
43 
LoadFile(wxImage * image,wxInputStream & stream,bool verbose,int WXUNUSED (index))44 bool wxPNMHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int WXUNUSED(index) )
45 {
46     wxUint32  width, height;
47     wxUint16  maxval;
48     char      c(0);
49 
50     image->Destroy();
51 
52     /*
53      * Read the PNM header
54      */
55 
56     wxBufferedInputStream buf_stream(stream);
57     wxTextInputStream text_stream(buf_stream);
58 
59     Skip_Comment(buf_stream);
60     if (buf_stream.GetC()==wxT('P')) c=buf_stream.GetC();
61 
62     switch (c)
63     {
64         case wxT('2'): // ASCII Grey
65         case wxT('3'): // ASCII RGB
66         case wxT('5'): // RAW Grey
67         case wxT('6'): break;
68         default:
69             if (verbose)
70             {
71                 wxLogError(_("PNM: File format is not recognized."));
72             }
73             return false;
74     }
75 
76     text_stream.ReadLine(); // for the \n
77     Skip_Comment(buf_stream);
78     text_stream >> width >> height ;
79     Skip_Comment(buf_stream);
80     text_stream >> maxval;
81 
82     //cout << line << " " << width << " " << height << " " << maxval << endl;
83     image->Create( width, height );
84     unsigned char *ptr = image->GetData();
85     if (!ptr)
86     {
87         if (verbose)
88         {
89            wxLogError( _("PNM: Couldn't allocate memory.") );
90         }
91         return false;
92     }
93 
94 
95     if (c=='2') // Ascii GREY
96     {
97         wxUint32 size=width*height;
98         for (wxUint32 i=0; i<size; ++i)
99         {
100             wxUint32 value;
101             value=text_stream.Read32();
102             if ( maxval != 255 )
103                 value = (255 * value)/maxval;
104             *ptr++=(unsigned char)value; // R
105             *ptr++=(unsigned char)value; // G
106             *ptr++=(unsigned char)value; // B
107             if ( !buf_stream )
108             {
109                 if (verbose)
110                 {
111                     wxLogError(_("PNM: File seems truncated."));
112                 }
113                 return false;
114             }
115         }
116     }
117     if (c=='3') // Ascii RBG
118     {
119         wxUint32 size=3*width*height;
120         for (wxUint32 i=0; i<size; ++i)
121           {
122             //this is very slow !!!
123             //I wonder how we can make any better ?
124             wxUint32 value;
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         for (wxUint32 i=0; i<size; ++i)
144         {
145             unsigned char value;
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