Recode and rescale texture file data before uploading

A recodeImage() method is added to the JavaScript ArrayBuffer object.
This commit is contained in:
David Rowe 2014-07-29 17:26:42 -07:00
parent 287e3d6800
commit f39aed37b6
3 changed files with 46 additions and 4 deletions

View file

@ -64,6 +64,12 @@ if (typeof String.prototype.fileName !== "function") {
};
}
if (typeof String.prototype.fileType !== "function") {
String.prototype.fileType = function () {
return this.slice(this.lastIndexOf(".") + 1);
};
}
if (typeof String.prototype.path !== "function") {
String.prototype.path = function () {
return this.replace(/[\\\/][^\\\/]*$/, "");
@ -284,6 +290,7 @@ var modelUploader = (function () {
PITCH_FIELD = "pitch",
YAW_FIELD = "yaw",
ROLL_FIELD = "roll",
MAX_TEXTURE_SIZE = 1024,
geometry;
function error(message) {
@ -578,6 +585,8 @@ var modelUploader = (function () {
lodFile,
lodBuffer,
textureBuffer,
textureSourceFormat,
textureTargetFormat,
i;
print("Preparing to send model");
@ -638,6 +647,12 @@ var modelUploader = (function () {
textureBuffer = readFile(modelFile.path() + "\/"
+ (mapping[TEXDIR_FIELD] !== "." ? mapping[TEXDIR_FIELD] + "\/" : "")
+ geometry.textures[i]);
textureSourceFormat = geometry.textures[i].fileType().toLowerCase();
textureTargetFormat = (textureSourceFormat === "jpg" ? "jpg" : "png");
textureBuffer.buffer = textureBuffer.buffer.recodeImage(textureSourceFormat, textureTargetFormat, MAX_TEXTURE_SIZE);
textureBuffer.filename = textureBuffer.filename.slice(0, -textureSourceFormat.length) + textureTargetFormat;
httpMultiPart.add({
name: "texture" + i,
buffer: textureBuffer

View file

@ -11,6 +11,9 @@
#include <glm/glm.hpp>
#include <QBuffer>
#include <QImage>
#include "ArrayBufferClass.h"
#include "ArrayBufferPrototype.h"
@ -47,17 +50,40 @@ QByteArray ArrayBufferPrototype::slice(qint32 begin) const {
}
QByteArray ArrayBufferPrototype::compress() const {
// Compresses the ArrayBuffer data in Zlib format.
QByteArray* ba = thisArrayBuffer();
QByteArray buffer = qCompress(*ba);
// Qt's qCompress() default compression level (-1) is the standard zLib compression.
// Here remove Qt's custom header that prevents the data server from uncompressing the files with zLib.
buffer.remove(QCOMPRESS_HEADER_POSITION, QCOMPRESS_HEADER_SIZE);
buffer.remove(QCOMPRESS_HEADER_POSITION, QCOMPRESS_HEADER_SIZE); // Remove Qt's custom header to make it proper Zlib.
return buffer;
}
QByteArray ArrayBufferPrototype::recodeImage(const QString& sourceFormat, const QString& targetFormat, qint32 maxSize) const {
// Recodes image data if sourceFormat and targetFormat are different.
// Rescales image data if either dimension is greater than the specified maximum.
QByteArray* ba = thisArrayBuffer();
bool mustRecode = sourceFormat.toLower() != targetFormat.toLower();
QImage image = QImage::fromData(*ba);
if (image.width() > maxSize || image.height() > maxSize) {
image = image.scaled(maxSize, maxSize, Qt::KeepAspectRatio);
mustRecode = true;
}
if (mustRecode) {
QBuffer buffer;
buffer.open(QIODevice::WriteOnly);
std::string str = targetFormat.toUpper().toStdString();
const char* format = str.c_str();
image.save(&buffer, format);
return buffer.data();
}
return *ba;
}
QByteArray* ArrayBufferPrototype::thisArrayBuffer() const {
return qscriptvalue_cast<QByteArray*>(thisObject().data());
}

View file

@ -24,6 +24,7 @@ public slots:
QByteArray slice(qint32 begin, qint32 end) const;
QByteArray slice(qint32 begin) const;
QByteArray compress() const;
QByteArray recodeImage(const QString& sourceFormat, const QString& targetFormat, qint32 maxSize) const;
private:
QByteArray* thisArrayBuffer() const;