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