#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 imagePaths) { QVector 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 }