bool KIPIWriteImage::write2PNG(const QString& destPath) { /* check this out for b/w support: http://lxr.kde.org/source/playground/graphics/krita-exp/kis_png_converter.cpp#607 */ QFile file(destPath); if (!file.open(QIODevice::ReadWrite)) { qDebug() << "Failed to open PNG file for writing" ; return false; } uchar* data = 0; int bitsDepth = d->sixteenBit ? 16 : 8; png_color_8 sig_bit; png_bytep row_ptr; png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_infop info_ptr = png_create_info_struct(png_ptr); png_set_write_fn(png_ptr, (void*)&file, kipi_png_write_fn, kipi_png_flush_fn); if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) // Intel png_set_bgr(png_ptr); else // PPC png_set_swap_alpha(png_ptr); if (d->hasAlpha) { png_set_IHDR(png_ptr, info_ptr, d->width, d->height, bitsDepth, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); if (d->sixteenBit) data = new uchar[d->width * 8 * sizeof(uchar)]; else data = new uchar[d->width * 4 * sizeof(uchar)]; } else { png_set_IHDR(png_ptr, info_ptr, d->width, d->height, bitsDepth, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); if (d->sixteenBit) data = new uchar[d->width * 6 * sizeof(uchar)]; else data = new uchar[d->width * 3 * sizeof(uchar)]; } sig_bit.red = bitsDepth; sig_bit.green = bitsDepth; sig_bit.blue = bitsDepth; sig_bit.alpha = bitsDepth; png_set_sBIT(png_ptr, info_ptr, &sig_bit); png_set_compression_level(png_ptr, 9); // Write Software info. QString libpngver(QLatin1String(PNG_HEADER_VERSION_STRING)); libpngver.replace(QLatin1Char('\n'), QLatin1Char(' ')); QByteArray softAscii = libpngver.toLatin1(); png_text text; text.key = (png_charp)"Software"; text.text = softAscii.data(); text.compression = PNG_TEXT_COMPRESSION_zTXt; png_set_text(png_ptr, info_ptr, &(text), 1); png_write_info(png_ptr, info_ptr); png_set_shift(png_ptr, &sig_bit); png_set_packing(png_ptr); uchar* ptr = (uchar*)d->data.data(); uint x, y, j; for (y = 0; y < d->height; ++y) { if (cancel()) { delete [] data; file.close(); png_destroy_write_struct(&png_ptr, (png_infopp) & info_ptr); png_destroy_info_struct(png_ptr, (png_infopp) & info_ptr); return false; } j = 0; for (x = 0; x < d->width*bytesDepth(); x+=bytesDepth()) { if (d->sixteenBit) { if (d->hasAlpha) { data[j++] = ptr[x+1]; // Blue data[j++] = ptr[ x ]; data[j++] = ptr[x+3]; // Green data[j++] = ptr[x+2]; data[j++] = ptr[x+5]; // Red data[j++] = ptr[x+4]; data[j++] = ptr[x+7]; // Alpha data[j++] = ptr[x+6]; } else { data[j++] = ptr[x+1]; // Blue data[j++] = ptr[ x ]; data[j++] = ptr[x+3]; // Green data[j++] = ptr[x+2]; data[j++] = ptr[x+5]; // Red data[j++] = ptr[x+4]; } } else { if (d->hasAlpha) { data[j++] = ptr[ x ]; // Blue data[j++] = ptr[x+1]; // Green data[j++] = ptr[x+2]; // Red data[j++] = ptr[x+3]; // Alpha } else { data[j++] = ptr[ x ]; // Blue data[j++] = ptr[x+1]; // Green data[j++] = ptr[x+2]; // Red } } } row_ptr = (png_bytep) data; png_write_rows(png_ptr, &row_ptr, 1); ptr += (d->width * bytesDepth()); } delete [] data; png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, (png_infopp) & info_ptr); png_destroy_info_struct(png_ptr, (png_infopp) & info_ptr); file.close(); return true; }
bool KPWriteImage::write2PNG(const QString& destPath) { FILE* file = fopen(QFile::encodeName(destPath), "wb"); if (!file) { kDebug( 51000 ) << "Failed to open PNG file for writing" << endl; return false; } uchar *data = 0; int bitsDepth = d->sixteenBit ? 16 : 8; png_color_8 sig_bit; png_bytep row_ptr; png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_infop info_ptr = png_create_info_struct(png_ptr); png_init_io(png_ptr, file); if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) // Intel png_set_bgr(png_ptr); else // PPC png_set_swap_alpha(png_ptr); if (d->hasAlpha) { png_set_IHDR(png_ptr, info_ptr, d->width, d->height, bitsDepth, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); if (d->sixteenBit) data = new uchar[d->width * 8 * sizeof(uchar)]; else data = new uchar[d->width * 4 * sizeof(uchar)]; } else { png_set_IHDR(png_ptr, info_ptr, d->width, d->height, bitsDepth, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); if (d->sixteenBit) data = new uchar[d->width * 6 * sizeof(uchar)]; else data = new uchar[d->width * 3 * sizeof(uchar)]; } sig_bit.red = bitsDepth; sig_bit.green = bitsDepth; sig_bit.blue = bitsDepth; sig_bit.alpha = bitsDepth; png_set_sBIT(png_ptr, info_ptr, &sig_bit); png_set_compression_level(png_ptr, 9); // Write ICC profil. if (!d->iccProfile.isEmpty()) { png_set_iCCP(png_ptr, info_ptr, (png_charp)"icc", PNG_COMPRESSION_TYPE_BASE, d->iccProfile.data(), d->iccProfile.size()); } // Write Software info. QString libpngver(PNG_HEADER_VERSION_STRING); libpngver.replace('\n', ' '); QString soft = d->kipipluginsVer; soft.append(QString(" (%1)").arg(libpngver)); png_text text; text.key = (png_charp)"Software"; text.text = soft.toAscii().data(); text.compression = PNG_TEXT_COMPRESSION_zTXt; png_set_text(png_ptr, info_ptr, &(text), 1); // Store Exif data. QByteArray ba = d->metadata.getExif(true); writeRawProfile(png_ptr, info_ptr, (png_charp)"exif", ba.data(), (png_uint_32) ba.size()); // Store Iptc data. QByteArray ba2 = d->metadata.getIptc(); writeRawProfile(png_ptr, info_ptr, (png_charp)"iptc", ba2.data(), (png_uint_32) ba2.size()); // Store Xmp data. QByteArray ba3 = d->metadata.getXmp(); writeRawProfile(png_ptr, info_ptr, (png_charp)("xmp"), ba3.data(), (png_uint_32) ba3.size()); png_write_info(png_ptr, info_ptr); png_set_shift(png_ptr, &sig_bit); png_set_packing(png_ptr); uchar* ptr = (uchar*)d->data.data(); uint x, y, j; for (y = 0; y < d->height; y++) { if (cancel()) { delete [] data; fclose(file); png_destroy_write_struct(&png_ptr, (png_infopp) & info_ptr); png_destroy_info_struct(png_ptr, (png_infopp) & info_ptr); return false; } j = 0; for (x = 0; x < d->width*bytesDepth(); x+=bytesDepth()) { if (d->sixteenBit) { if (d->hasAlpha) { data[j++] = ptr[x+1]; // Blue data[j++] = ptr[ x ]; data[j++] = ptr[x+3]; // Green data[j++] = ptr[x+2]; data[j++] = ptr[x+5]; // Red data[j++] = ptr[x+4]; data[j++] = ptr[x+7]; // Alpha data[j++] = ptr[x+6]; } else { data[j++] = ptr[x+1]; // Blue data[j++] = ptr[ x ]; data[j++] = ptr[x+3]; // Green data[j++] = ptr[x+2]; data[j++] = ptr[x+5]; // Red data[j++] = ptr[x+4]; } } else { if (d->hasAlpha) { data[j++] = ptr[ x ]; // Blue data[j++] = ptr[x+1]; // Green data[j++] = ptr[x+2]; // Red data[j++] = ptr[x+3]; // Alpha } else { data[j++] = ptr[ x ]; // Blue data[j++] = ptr[x+1]; // Green data[j++] = ptr[x+2]; // Red } } } row_ptr = (png_bytep) data; png_write_rows(png_ptr, &row_ptr, 1); ptr += (d->width * bytesDepth()); } delete [] data; png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, (png_infopp) & info_ptr); png_destroy_info_struct(png_ptr, (png_infopp) & info_ptr); fclose(file); return true; }