00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043
00044 #include "OSGConfig.h"
00045
00046 #include <iostream>
00047
00048 #include <OSGLog.h>
00049
00050 #include "OSGPNMImageFileType.h"
00051
00052 #ifdef OSG_SGI_STL
00053
00054
00055 #ifndef INT_MAX
00056 #define INT_MAX numeric_limits<int>::max()
00057 #endif
00058 #else
00059 #include <limits.h>
00060 #endif
00061 OSG_USING_NAMESPACE
00062
00063
00076
00077
00078
00079
00080 static const Char8 *suffixArray[] =
00081 {
00082 "pnm", "pbm", "pgm", "ppm"
00083 };
00084
00085
00086 PNMImageFileType PNMImageFileType::_the("image/x-portable-bitmap",
00087 suffixArray, sizeof(suffixArray),
00088 OSG_READ_SUPPORTED |
00089 OSG_WRITE_SUPPORTED);
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00103 PNMImageFileType& PNMImageFileType::the (void)
00104 {
00105 return _the;
00106 }
00107
00108
00109
00110
00111
00112
00117 bool PNMImageFileType::read(ImagePtr &image, std::istream &in, const std::string &mimetype)
00118 {
00119 bool isBinary = true;
00120 Int16 type = 0, width, height, lineSize, maxValue=0, value, x, y;
00121 UInt32 i, n;
00122 UChar8 *imageData = 0;
00123 UInt8 id, commentKey = '#';
00124
00125 in >> id >> type;
00126 in.ignore(INT_MAX, '\n');
00127 while(in.peek() == commentKey)
00128 in.ignore(INT_MAX, '\n');
00129 in >> width >> height;
00130 isBinary = ((type > 3) && (type < 7)) ? true : false;
00131
00132 switch(type)
00133 {
00134 case 1:
00135 case 4:
00136 maxValue = 1;
00137 image->set(Image::OSG_L_PF, width, height);
00138 break;
00139 case 2:
00140 case 5:
00141 maxValue = 0;
00142 image->set(Image::OSG_L_PF, width, height);
00143 break;
00144 case 3:
00145 case 6:
00146 maxValue = 0;
00147 image->set(Image::OSG_RGB_PF, width, height);
00148 break;
00149 case 7:
00150 FWARNING (("Read PNM type %d: LA-ascii extention\n",type ));
00151 maxValue = 0;
00152 image->set(Image::OSG_LA_PF, width, height);
00153 break;
00154 case 8:
00155 FWARNING (("Read PNM type %d: RGBA-ascii extention\n",type ));
00156 maxValue = 0;
00157 image->set(Image::OSG_RGBA_PF, width, height);
00158 break;
00159 default:
00160 SWARNING << "unknown image format type " << type << std::endl;
00161 break;
00162 }
00163
00164 if(!maxValue)
00165 {
00166 in >> maxValue;
00167 if(maxValue != 255)
00168 {
00169 SWARNING <<
00170 "unknown max value " <<
00171 maxValue <<
00172 ", can't read the image" <<
00173 std::endl;
00174 maxValue = 0;
00175 }
00176 }
00177
00178
00179 in.ignore(INT_MAX, '\n');
00180
00181 if(maxValue && (imageData = image->getData()))
00182 {
00183 SINFO <<
00184 "Read pnm file of type " <<
00185 type <<
00186 ", " <<
00187 width <<
00188 "x" <<
00189 height <<
00190 std::endl;
00191
00192 lineSize = width * image->getBpp();
00193 if(isBinary)
00194 {
00195 for(y = height - 1; y >= 0; y--)
00196 {
00197 in.read((Char8 *) &(imageData[y * lineSize]), lineSize);
00198 }
00199 }
00200 else
00201 {
00202 for(y = height - 1; y >= 0; y--)
00203 {
00204 for(x = 0; x < lineSize; x++)
00205 {
00206 in >> value;
00207 imageData[y * lineSize + x] = UChar8(value);
00208 }
00209 }
00210 }
00211
00212 if(maxValue == 1)
00213 {
00214 n = image->getSize();
00215 for(i = 0; i < n; i++)
00216 imageData[0] *= 255;
00217 }
00218 }
00219
00220 return true;
00221 }
00222
00223
00228 bool PNMImageFileType::write(const ImagePtr &image, std::ostream &out, const std::string &mimetype)
00229 {
00230 Int16 p, y, x, lineSize;
00231 UInt16 bpp = image->getBpp();
00232 UInt8 *data = 0;
00233
00234 switch(bpp)
00235 {
00236 case 1:
00237 case 2:
00238 out << "P5" << std::endl;
00239 break;
00240 case 3:
00241 case 4:
00242 out << "P6" << std::endl;
00243 break;
00244 }
00245
00246 out << "# PNMImageFileType write" << std::endl;
00247 out << image->getWidth() << " " << image->getHeight() << std::endl;
00248 out << "255" << std::endl;
00249
00250 if(bpp & 1)
00251 {
00252
00253 lineSize = image->getBpp() * image->getWidth();
00254 for(y = image->getHeight() - 1; y >= 0; y--)
00255 {
00256 out.write((char *) (image->getData() + (lineSize * y)),
00257 lineSize);
00258 }
00259 }
00260 else
00261 {
00262
00263 lineSize = image->getBpp() * image->getWidth();
00264 for(y = image->getHeight() - 1; y >= 0; y--)
00265 {
00266 data = (UInt8 *) (image->getData() + (lineSize * y));
00267 for(x = 0; x < image->getWidth(); x++)
00268 {
00269 for(p = bpp - 1; p--;)
00270 out << *data++;
00271 data++;
00272 }
00273 }
00274 }
00275
00276 return data ? true : false;
00277 }
00278
00279
00285 std::string PNMImageFileType::determineMimetypeFromStream(std::istream &is)
00286 {
00287 char filecode[2];
00288 is.read(filecode, 2);
00289 is.seekg(-2, std::ios::cur);
00290 if (strncmp(filecode, "P1", 2) == 0)
00291 return std::string(getMimeType());
00292 if (strncmp(filecode, "P2", 2) == 0)
00293 return std::string(getMimeType());
00294 if (strncmp(filecode, "P3", 2) == 0)
00295 return std::string(getMimeType());
00296 if (strncmp(filecode, "P4", 2) == 0)
00297 return std::string(getMimeType());
00298 if (strncmp(filecode, "P5", 2) == 0)
00299 return std::string(getMimeType());
00300 if (strncmp(filecode, "P6", 2) == 0)
00301 return std::string(getMimeType());
00302 return std::string();
00303 }
00304
00305
00309 PNMImageFileType::PNMImageFileType(const Char8 *mimeType,
00310 const Char8 *suffixArray[],
00311 UInt16 suffixByteCount,
00312 UInt32 flags) :
00313 ImageFileType(mimeType, suffixArray, suffixByteCount, flags)
00314 {}
00315
00316
00320 PNMImageFileType::~PNMImageFileType(void) {}