122 lines
3.5 KiB
C++
122 lines
3.5 KiB
C++
#include "texturecrafter.h"
|
|
|
|
TextureCrafter::TextureCrafter(QObject *parent)
|
|
: QObject{parent}
|
|
{}
|
|
|
|
QString TextureCrafter::getOutFilename() {
|
|
QString outFileName;
|
|
if (outDir.isValid()) {
|
|
outFileName = outDir.path();
|
|
outFileName.append("/out.png");
|
|
} else {
|
|
return QString();
|
|
}
|
|
|
|
return outFileName;
|
|
}
|
|
|
|
QUrl TextureCrafter::packChannels(QVector<QUrl> imagePaths) {
|
|
|
|
QVector<QImage> sourceImages;
|
|
int width = 0, height = 0;
|
|
QImage::Format format = QImage::Format_RGB888;
|
|
|
|
for (int i = 0; i < imagePaths.length(); i++) {
|
|
// if the ui layer did its job this will always be a file:// url
|
|
QString rawPath = imagePaths[i].toLocalFile();
|
|
QImage newImage(rawPath); // would this cause a use after free idk
|
|
|
|
// we just use the first image's dimensions and force the others to conform hehe
|
|
if (width == 0) {
|
|
width = newImage.width();
|
|
}
|
|
if (height == 0) {
|
|
height = newImage.height();
|
|
}
|
|
|
|
sourceImages.append(newImage);
|
|
}
|
|
|
|
png_structp outPng;
|
|
png_infop outInfo;
|
|
FILE *outFile;
|
|
QString outFilename = getOutFilename();
|
|
unsigned char *rowBuffer;
|
|
|
|
// maybe abstract this?
|
|
outFile = fopen(outFilename.toLatin1().data(), "wb");
|
|
|
|
if (!outFile) {
|
|
return QUrl();
|
|
}
|
|
|
|
outPng = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
outInfo = png_create_info_struct(outPng);
|
|
rowBuffer = (unsigned char*)malloc(sizeof(char) * 3 * width);
|
|
|
|
png_init_io(outPng, outFile);
|
|
|
|
png_set_IHDR (outPng,
|
|
outInfo,
|
|
width,
|
|
height,
|
|
8, // TODO: support other bit depths someday
|
|
PNG_COLOR_TYPE_RGB,
|
|
PNG_INTERLACE_NONE,
|
|
PNG_COMPRESSION_TYPE_DEFAULT,
|
|
PNG_FILTER_TYPE_DEFAULT);
|
|
|
|
png_write_info(outPng, outInfo);
|
|
|
|
// do the channel packing!!
|
|
// theres probably a faster way to do this but eh
|
|
for (int i = 0; i < height; i++) {
|
|
memset(rowBuffer, 0, sizeof(char) * 3 * width);
|
|
for (int j = 0; j < width; j++) {
|
|
unsigned char r, g, b;
|
|
|
|
// too eepy for dry
|
|
r = sourceImages.at(0).pixelColor(j, i).red();
|
|
g = sourceImages.at(1).pixelColor(j, i).green();
|
|
b = sourceImages.at(2).pixelColor(j, i).blue();
|
|
|
|
rowBuffer[j*3+0] = r;
|
|
rowBuffer[j*3+1] = g;
|
|
rowBuffer[j*3+2] = b;
|
|
}
|
|
|
|
png_write_row(outPng, rowBuffer);
|
|
}
|
|
|
|
png_write_end(outPng, NULL);
|
|
|
|
// good soldiers free their memory
|
|
free(rowBuffer);
|
|
png_destroy_write_struct(&outPng, &outInfo);
|
|
fclose(outFile);
|
|
return QUrl::fromLocalFile(outFilename);
|
|
|
|
// // write it to a temp file
|
|
// if (outDir.isValid()) {
|
|
// QString outFileName = outDir.path();
|
|
// outFileName.append("/out.png");
|
|
|
|
// printf("wrote to %s\n", outFileName.toLatin1().data());
|
|
|
|
// //TODO: use libpng and do progressive write to update the progress bar
|
|
// if (outImage.save(outFileName)) {
|
|
// printf("cool ^-^\n");
|
|
// return QUrl::fromLocalFile(outFileName);
|
|
// } else {
|
|
// //TODO: return some error value to show the user
|
|
// printf("that dream is fucked it is fucking fucked\n");
|
|
// }
|
|
// } else {
|
|
// printf("chat its so over\n");
|
|
// }
|
|
|
|
return QUrl();
|
|
//do we need to close these??? idk lets hope qt handles it
|
|
}
|