mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-22 13:16:23 +00:00
First Commit
For Azeroth!
This commit is contained in:
217
dep/g3dlite/source/GImage_ppm.cpp
Normal file
217
dep/g3dlite/source/GImage_ppm.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
/**
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user