Skip to content

Commit

Permalink
From Eric Sokolowsky, "Attached is an updated PNM plugin for inclusio…
Browse files Browse the repository at this point in the history
…n in both the trunk and for release version 2.8.5. The attached file fixes numerous bugs in reading 8-bit and 16-bit images, including loading the images upside-down. This file also incorporates trunk patch r12220 which updated the plugin for reading and writing images through streams instead of C-style FILE I/O."

Note from Robert Osfield, previous revision was in error due to an incomplete merge, this revision completes the job.
  • Loading branch information
robertosfield committed May 27, 2011
1 parent fcd3150 commit 0820be9
Showing 1 changed file with 84 additions and 0 deletions.
84 changes: 84 additions & 0 deletions src/osgPlugins/pnm/ReaderWriterPNM.cpp
Expand Up @@ -22,53 +22,101 @@ template <class T>
unsigned char* read_bitmap_ascii(std::istream& fin, int width, int height)
{
T* data = new T[width*height];
T* end = data + width*height;

int x = 0;
T* dst = end - width;
int value = 0;

while(dst >= data)
{
fin >> value;
if (!fin.good())
{
delete [] data;
return NULL;
}

// place value in the image. 0 is white and anything else is black.
*(dst++) = value ? 0 : 255;

// At end of each row, jump back two rows
++x;
if (x == width)
{
x = 0;
dst -= 2*width;
}
}

return reinterpret_cast<unsigned char*>(data);
}

template <class T>
unsigned char* read_grayscale_ascii(std::istream& fin, int width, int height, int max_value)
{
T* data = new T[width*height];
T* end = data + width*height;

int x = 0;
T* dst = end - width;
int value = 0;
float max = (sizeof(T) == 1) ? 255.0 : 65535.0;

while(dst >= data)
{
fin >> value;
if (!fin.good())
{
delete [] data;
return NULL;
}

// place value in the image
*(dst++) = T(float(value)/float(max_value)*max);

// At end of each row, jump back two rows
++x;
if (x == width)
{
x = 0;
dst -= 2*width;
}
}

return reinterpret_cast<unsigned char*>(data);
}

template <class T>
unsigned char* read_color_ascii(std::istream& fin, int width, int height, int max_value)
{
T* data = new T[3*width*height];
T* end = data + 3*width*height;

int x = 0;
T* dst = end - 3*width;
int value = 0;
float max = (sizeof(T) == 1) ? 255.0 : 65535.0;

while(dst >= data)
{
fin >> value;
if (!fin.good())
{
delete [] data;
return NULL;
}

// place value in the image
*(dst++) = T(float(value)/float(max_value)*max);

// At end of the row, jump back two rows
++x;
if (x == width*3)
{
x = 0;
dst -= 6*width;
}
}

return reinterpret_cast<unsigned char*>(data);
Expand All @@ -79,6 +127,7 @@ template <class T>
{
T* data = new T[width*height];

for(int y = height-1; y >= 0; --y)
{
T* dst = data + (y+0)*width;
T* end = data + (y+1)*width;
Expand Down Expand Up @@ -107,30 +156,55 @@ template <class T>
template <class T>
unsigned char* read_grayscale_binary(std::istream& fin, int width, int height)
{
T* data = new T[width*height];

for(int y = height-1; y >= 0; --y)
{
T* dst = data + y*width;
fin.read((char*)dst, sizeof(T)*width);
if (!fin.good())
{
delete [] data;
return NULL;
}
}

// if the machine is little endian swap the bytes around
if (sizeof(T) == 2 && getCpuByteOrder() == osg::LittleEndian)
{
unsigned char *bs = reinterpret_cast<unsigned char *>(data);
unsigned char *end = bs + sizeof(T)*width*height;
for (; bs < end; bs += 2)
{
std::swap(bs[0], bs[1]);
}
}

return reinterpret_cast<unsigned char *>(data);
}

template <class T>
unsigned char* read_color_binary(std::istream& fin, int width, int height)
{
T* data = new T[3*width*height];

for(int y = height-1; y >= 0; --y)
{
T* dst = data + y*3*width;
fin.read((char*)dst, sizeof(T)*3*width);
if (!fin.good())
{
delete [] data;
return NULL;
}
}

// if the machine is little endian swap the bytes around
if (sizeof(T) == 2 && getCpuByteOrder() == osg::LittleEndian)
{
unsigned char *bs = reinterpret_cast<unsigned char *>(data);
unsigned char *end = bs + sizeof(T)*3*width*height;
for (; bs < end; bs+=2)
{
std::swap(bs[0], bs[1]);
}
Expand Down Expand Up @@ -225,9 +299,11 @@ class ReaderWriterPNM : public osgDB::ReaderWriter
{
case 2: // grayscale ascii
pixelFormat = GL_LUMINANCE;
data = read_grayscale_ascii<unsigned short>(fin, width, height, max_value);
break;
case 3: // color ascii
pixelFormat = GL_RGB;
data = read_color_ascii<unsigned short>(fin, width, height, max_value);
break;
case 5: // grayscale binary
pixelFormat = GL_LUMINANCE;
Expand All @@ -237,6 +313,9 @@ class ReaderWriterPNM : public osgDB::ReaderWriter
pixelFormat = GL_RGB;
data = read_color_binary<unsigned short>(fin, width, height);
break;
default:
return ReadResult::ERROR_IN_READING_FILE;
break;
}
}
else
Expand All @@ -250,9 +329,11 @@ class ReaderWriterPNM : public osgDB::ReaderWriter
break;
case 2: // grayscale ascii
pixelFormat = GL_LUMINANCE;
data = read_grayscale_ascii<unsigned char>(fin, width, height, max_value);
break;
case 3: // color ascii
pixelFormat = GL_RGB;
data = read_color_ascii<unsigned char>(fin, width, height, max_value);
break;
case 4: // bitmap binary
pixelFormat = GL_LUMINANCE;
Expand All @@ -266,6 +347,9 @@ class ReaderWriterPNM : public osgDB::ReaderWriter
pixelFormat = GL_RGB;
data = read_color_binary<unsigned char>(fin, width, height);
break;
default:
return ReadResult::ERROR_IN_READING_FILE;
break;
}
}

Expand Down

0 comments on commit 0820be9

Please sign in to comment.