server/dep/src/g3dlite/GImage_ppm.cpp
Lynx3d ae3ad10bcf [10097] Update G3D up to v8.0b4
+ Got rid of zip lib requirement in G3D...
  Still can re-enable code by defining _HAVE_ZIP...

+ Remove silly X11 lib dependency from G3D
  Code doesn't seem to do anything yet anyway, and even if, we don't want it :p

+ Fix another weird G3D build problem...

+ Remove some __asm usage in g3d, which is not available on Win64
  My editor also decided to remove a ton of trailing white spaces...tss...

+ Reapply G3D fixes for 64bit VC

+ not use SSE specific header when SSE not enabled in *nix

+ Updated project files

+ New vmap_assembler VC90/VC80 Project

+ vmap assembler binaries updates

NOTE: Old vmap fikes expected work (as tests show) with new library version.
      But better use new generated versions. Its different in small parts to bad or good...

(based on Lynx3d's repo commit 44798d3)

Signed-off-by: VladimirMangos <vladimir@getmangos.com>
2010-06-23 06:45:25 +04:00

217 lines
6.1 KiB
C++

/**
@file GImage_ppm.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu
@created 2002-05-27
@edited 2006-05-10
*/
#include "G3D/platform.h"
#include "G3D/GImage.h"
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
#include "G3D/TextInput.h"
#include "G3D/TextOutput.h"
#include "G3D/Log.h"
namespace G3D {
void GImage::encodePPMASCII(
BinaryOutput& out) const {
TextOutput::Settings ppmOptions;
ppmOptions.convertNewlines = false;
ppmOptions.numColumns = 70;
ppmOptions.wordWrap = TextOutput::Settings::WRAP_WITHOUT_BREAKING;
TextOutput ppm(ppmOptions);
switch (m_channels) {
case 1:
{
ppm.printf("P2\n%d %d\n255\n", m_width, m_height);
const Color1uint8* c = this->pixel1();
// Insert newlines every 70 characters max
for (uint32 i = 0; i < (uint32)(m_width * m_height); ++i) {
ppm.printf("%d%c", c[i].value, (i % (70/4) == 0) ? '\n' : ' ');
}
}
break;
case 3:
{
ppm.printf("P3\n%d %d\n255\n", m_width, m_height);
const Color3uint8* c = this->pixel3();
// Insert newlines every 70 characters max
for (uint32 i = 0; i < (uint32)(m_width * m_height); ++i) {
ppm.printf("%d %d %d%c", c[i].r, c[i].g, c[i].b,
(i % (70/12) == 0) ?
'\n' : ' ');
}
}
break;
default:
alwaysAssertM(false, "PPM requires either 1 or 3 channels exactly.");
}
const std::string& s = ppm.commitString();
out.writeBytes(s.c_str(), s.length());
}
void GImage::encodePPM(
BinaryOutput& out) const {
// http://netpbm.sourceforge.net/doc/ppm.html
if (m_channels == 3) {
std::string header = format("P6 %d %d 255 ", m_width, m_height);
out.writeBytes(header.c_str(), header.size());
out.writeBytes(this->pixel3(), m_width * m_height * 3);
} else if (m_channels == 1) {
std::string header = format("P5 %d %d 255 ", m_width, m_height);
out.writeBytes(header.c_str(), header.size());
out.writeBytes(this->pixel1(), m_width * m_height);
} else {
alwaysAssertM(false, "PPM requires either 1 or 3 channels exactly.");
}
}
void GImage::decodePPMASCII(
BinaryInput& input) {
int ppmWidth;
int ppmHeight;
double maxColor;
// Create a TextInput object to parse ascii format
// Mixed binary/ascii formats will require more
const std::string inputStr = input.readString();
TextInput::Settings ppmOptions;
ppmOptions.cppLineComments = false;
ppmOptions.otherCommentCharacter = '#';
ppmOptions.signedNumbers = true;
ppmOptions.singleQuotedStrings = false;
TextInput ppmInput(TextInput::FROM_STRING, inputStr, ppmOptions);
//Skip first line in header P#
std::string ppmType = ppmInput.readSymbol();
ppmWidth = (int)ppmInput.readNumber();
ppmHeight = (int)ppmInput.readNumber();
// Everything but a PBM will have a max color value
if (ppmType != "P2") {
maxColor = ppmInput.readNumber();
} else {
maxColor = 255;
}
if ((ppmWidth < 0) ||
(ppmHeight < 0) ||
(maxColor <= 0)) {
throw GImage::Error("Invalid PPM Header.", input.getFilename());
}
// I don't think it's proper to scale values less than 255
if (maxColor <= 255.0) {
maxColor = 255.0;
}
m_width = ppmWidth;
m_height = ppmHeight;
m_channels = 3;
// always scale down to 1 byte per channel
m_byte = (uint8*)m_memMan->alloc(m_width * m_height * 3);
// Read in the image data. I am not validating if the values match the maxColor
// requirements. I only scale if needed to fit within the byte available.
for (uint32 i = 0; i < (uint32)(m_width * m_height); ++i) {
// read in color and scale to max pixel defined in header
// A max color less than 255 might need to be left alone and not scaled.
Color3uint8& curPixel = *(pixel3() + i);
if (ppmType == "P3") {
curPixel.r = (uint8)(ppmInput.readNumber() * (255.0 / maxColor));
curPixel.g = (uint8)(ppmInput.readNumber() * (255.0 / maxColor));
curPixel.b = (uint8)(ppmInput.readNumber() * (255.0 / maxColor));
} else if (ppmType == "P2") {
uint8 pixel = (uint8)(ppmInput.readNumber() * (255.0 / maxColor));
curPixel.r = pixel;
curPixel.g = pixel;
curPixel.b = pixel;
} else if (ppmType == "P1") {
int pixel = (uint8)(ppmInput.readNumber() * maxColor);
curPixel.r = pixel;
curPixel.g = pixel;
curPixel.b = pixel;
}
}
}
/** Consumes whitespace up to and including a number, but not the following character */
static int scanUInt(BinaryInput& input) {
char c = input.readUInt8();
while (isWhiteSpace(c)) {
c = input.readUInt8();
}
std::string s;
s += c;
c = input.readUInt8();
while (!isWhiteSpace(c)) {
s += c;
c = input.readUInt8();
}
// Back up one to avoid consuming the last character
input.setPosition(input.getPosition() - 1);
int x;
sscanf(s.c_str(), "%d", &x);
return x;
}
void GImage::decodePPM(
BinaryInput& input) {
char head[2];
int w, h;
input.readBytes(head, 2);
if (head[0] != 'P' || (head[1] != '6') && (head[1] != '5')) {
throw GImage::Error("Invalid PPM Header.", input.getFilename());
}
w = scanUInt(input);
h = scanUInt(input);
// Skip the max color specifier
scanUInt(input);
if ((w < 0) ||
(h < 0) ||
(w > 100000) ||
(h > 100000)) {
throw GImage::Error("Invalid PPM size in header.", input.getFilename());
}
// Trailing whitespace
input.readUInt8();
if (head[1] == '6') {
// 3 channel
resize(w, h, 3);
input.readBytes(m_byte, m_width * m_height * 3);
} else if (head[1] == '5') {
// 1 channel
resize(w, h, 1);
input.readBytes(m_byte, m_width * m_height);
}
}
}