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