00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kis_png_converter.h"
00022
00023 #include <stdio.h>
00024
00025 #include <qfile.h>
00026
00027 #include <kapplication.h>
00028 #include <kmessagebox.h>
00029 #include <klocale.h>
00030
00031 #include <KoDocumentInfo.h>
00032
00033 #include <kio/netaccess.h>
00034
00035 #include <kis_abstract_colorspace.h>
00036 #include <kis_colorspace_factory_registry.h>
00037 #include <kis_doc.h>
00038 #include <kis_image.h>
00039 #include <kis_iterators_pixel.h>
00040 #include <kis_layer.h>
00041 #include <kis_meta_registry.h>
00042 #include <kis_profile.h>
00043 #include <kis_paint_layer.h>
00044 #include <kis_group_layer.h>
00045
00046 namespace {
00047
00048 const Q_UINT8 PIXEL_BLUE = 0;
00049 const Q_UINT8 PIXEL_GREEN = 1;
00050 const Q_UINT8 PIXEL_RED = 2;
00051 const Q_UINT8 PIXEL_ALPHA = 3;
00052
00053
00054 int getColorTypeforColorSpace( KisColorSpace * cs , bool alpha)
00055 {
00056 if ( cs->id() == KisID("GRAYA") || cs->id() == KisID("GRAYA16") )
00057 {
00058 return alpha ? PNG_COLOR_TYPE_GRAY_ALPHA : PNG_COLOR_TYPE_GRAY;
00059 }
00060 if ( cs->id() == KisID("RGBA") || cs->id() == KisID("RGBA16") )
00061 {
00062 return alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB;
00063 }
00064
00065 KMessageBox::error(0, i18n("The selected image format does not support the colorspace of the image (%1)\nPlease choose another format or convert to a different colorspace").arg(cs->id().name()) ) ;
00066 return -1;
00067
00068 }
00069
00070
00071 QString getColorSpaceForColorType(int color_type,int color_nb_bits) {
00072 if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
00073 {
00074 switch(color_nb_bits)
00075 {
00076 case 8:
00077 return "GRAYA";
00078 case 16:
00079 return "GRAYA16";
00080 }
00081 } else if(color_type == PNG_COLOR_TYPE_RGB_ALPHA || color_type == PNG_COLOR_TYPE_RGB) {
00082 switch(color_nb_bits)
00083 {
00084 case 8:
00085 return "RGBA";
00086 case 16:
00087 return "RGBA16";
00088 }
00089 } else if(color_type == PNG_COLOR_TYPE_PALETTE) {
00090 return "RGBA";
00091 }
00092 return "";
00093 }
00094
00095
00096 void fillText(png_text* p_text, char* key, QString& text)
00097 {
00098 p_text->compression = PNG_TEXT_COMPRESSION_zTXt;
00099 p_text->key = key;
00100 char* textc = new char[text.length()+1];
00101 strcpy(textc, text.ascii());
00102 p_text->text = textc;
00103 p_text->text_length = text.length()+1;
00104 }
00105
00106 }
00107
00108 KisPNGConverter::KisPNGConverter(KisDoc *doc, KisUndoAdapter *adapter)
00109 {
00110 Q_ASSERT(doc);
00111 Q_ASSERT(adapter);
00112
00113 m_doc = doc;
00114 m_adapter = adapter;
00115 m_stop = false;
00116 m_max_row = 0;
00117 m_img = 0;
00118 }
00119
00120 KisPNGConverter::~KisPNGConverter()
00121 {
00122 }
00123
00124 KisImageBuilder_Result KisPNGConverter::decode(const KURL& uri)
00125 {
00126 kdDebug(41008) << "Start decoding PNG File" << endl;
00127
00128 kdDebug(41008) << QFile::encodeName(uri.path()) << " " << uri.path() << " " << uri << endl;
00129 FILE *fp = fopen(QFile::encodeName(uri.path()), "rb");
00130 if (!fp)
00131 {
00132 return (KisImageBuilder_RESULT_NOT_EXIST);
00133 }
00134 png_byte signature[8];
00135 fread(signature, 1, 8, fp);
00136 if (!png_check_sig(signature, 8))
00137 {
00138 return (KisImageBuilder_RESULT_BAD_FETCH);
00139 }
00140
00141
00142 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL);
00143 if (!KisImageBuilder_RESULT_FAILURE)
00144 return (KisImageBuilder_RESULT_FAILURE);
00145
00146 png_infop info_ptr = png_create_info_struct(png_ptr);
00147 if (!info_ptr)
00148 {
00149 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
00150 return (KisImageBuilder_RESULT_FAILURE);
00151 }
00152
00153 png_infop end_info = png_create_info_struct(png_ptr);
00154 if (!end_info)
00155 {
00156 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
00157 return (KisImageBuilder_RESULT_FAILURE);
00158 }
00159
00160
00161 if (setjmp(png_jmpbuf(png_ptr)))
00162 {
00163 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00164 fclose(fp);
00165 return (KisImageBuilder_RESULT_FAILURE);
00166 }
00167
00168 png_init_io(png_ptr, fp);
00169 png_set_sig_bytes(png_ptr, 8);
00170
00171
00172 png_read_info(png_ptr, info_ptr);
00173
00174
00175 png_uint_32 width, height;
00176 int color_nb_bits, color_type;
00177 png_get_IHDR(png_ptr, info_ptr, &width, &height, &color_nb_bits, &color_type, NULL, NULL, NULL);
00178
00179
00180 #ifndef WORDS_BIGENDIAN
00181 if (color_nb_bits > 8 )
00182 png_set_swap(png_ptr);
00183 #endif
00184
00185
00186 QString csName = getColorSpaceForColorType(color_type, color_nb_bits);
00187 if(csName.isEmpty()) {
00188 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00189 return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE;
00190 }
00191 bool hasalpha = (color_type == PNG_COLOR_TYPE_RGB_ALPHA || color_type == PNG_COLOR_TYPE_GRAY_ALPHA);
00192
00193
00194 png_charp profile_name, profile_data;
00195 int compression_type;
00196 png_uint_32 proflen;
00197
00198 KisProfile* profile = 0;
00199 if(png_get_iCCP(png_ptr, info_ptr, &profile_name, &compression_type, &profile_data, &proflen))
00200 {
00201 QByteArray profile_rawdata;
00202
00203 if (QString::compare(profile_name, "icc") == 0) {
00204 profile_rawdata.resize(proflen);
00205 memcpy(profile_rawdata.data(), profile_data, proflen);
00206 profile = new KisProfile(profile_rawdata);
00207 Q_CHECK_PTR(profile);
00208 if (profile) {
00209 kdDebug(41008) << "profile name: " << profile->productName() << " profile description: " << profile->productDescription() << " information sur le produit: " << profile->productInfo() << endl;
00210 if(!profile->isSuitableForOutput())
00211 {
00212 kdDebug(41008) << "the profile is not suitable for output and therefore cannot be used in krita, we need to convert the image to a standard profile" << endl;
00213 }
00214 }
00215 }
00216 }
00217
00218
00219 KisColorSpace* cs;
00220 if (profile && profile->isSuitableForOutput())
00221 {
00222 kdDebug(41008) << "image has embedded profile: " << profile -> productName() << "\n";
00223 cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(csName, profile);
00224 }
00225 else
00226 cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID(csName,""),"");
00227
00228 if(cs == 0)
00229 {
00230 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00231 return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE;
00232 }
00233
00234
00235 cmsHTRANSFORM transform = 0;
00236 if(profile && !profile->isSuitableForOutput())
00237 {
00238 transform = cmsCreateTransform(profile->profile(), cs->colorSpaceType(),
00239 cs->getProfile()->profile() , cs->colorSpaceType(),
00240 INTENT_PERCEPTUAL, 0);
00241 }
00242
00243
00244 png_text* text_ptr;
00245 int num_comments;
00246 png_get_text(png_ptr, info_ptr, &text_ptr, &num_comments);
00247 KoDocumentInfo * info = m_doc->documentInfo();
00248 KoDocumentInfoAbout * aboutPage = static_cast<KoDocumentInfoAbout *>(info->page( "about" ));
00249 KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor *>(info->page( "author"));
00250 kdDebug(41008) << "There are " << num_comments << " comments in the text" << endl;
00251 for(int i = 0; i < num_comments; i++)
00252 {
00253 kdDebug(41008) << "key is " << text_ptr[i].key << " containing " << text_ptr[i].text << endl;
00254 if(QString::compare(text_ptr[i].key, "title") == 0)
00255 {
00256 aboutPage->setTitle(text_ptr[i].text);
00257 } else if(QString::compare(text_ptr[i].key, "abstract") == 0)
00258 {
00259 aboutPage->setAbstract(text_ptr[i].text);
00260 } else if(QString::compare(text_ptr[i].key, "author") == 0)
00261 {
00262 authorPage->setFullName(text_ptr[i].text);
00263 }
00264 }
00265
00266
00267 png_bytepp row_pointers = new png_bytep[height];
00268 png_uint_32 row_index = 0;
00269 try
00270 {
00271 png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
00272 for(; row_index < height; row_index++)
00273 {
00274 row_pointers[row_index] = new png_byte[rowbytes];
00275 }
00276 }
00277 catch(std::bad_alloc& e)
00278 {
00279
00280
00281 kdDebug(41008) << "bad alloc: " << e.what() << endl;
00282
00283 for (png_uint_32 y = 0; y < row_index; y++) {
00284 delete[] row_pointers[y];
00285 }
00286 delete [] row_pointers;
00287 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00288 return (KisImageBuilder_RESULT_FAILURE);
00289 }
00290
00291
00292 png_colorp palette ;
00293 int num_palette;
00294 if(color_type == PNG_COLOR_TYPE_PALETTE) {
00295 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
00296 }
00297
00298
00299 png_read_image(png_ptr, row_pointers);
00300
00301
00302 png_read_end(png_ptr, end_info);
00303 fclose(fp);
00304
00305
00306 if( ! m_img) {
00307 m_img = new KisImage(m_doc->undoAdapter(), width, height, cs, "built image");
00308 m_img->blockSignals(true);
00309 Q_CHECK_PTR(m_img);
00310 if(profile && !profile->isSuitableForOutput())
00311 {
00312 m_img -> addAnnotation( profile->annotation() );
00313 }
00314 }
00315
00316 KisPaintLayer* layer = new KisPaintLayer(m_img, m_img -> nextLayerName(), Q_UINT8_MAX);
00317 for (png_uint_32 y = 0; y < height; y++) {
00318 KisHLineIterator it = layer -> paintDevice() -> createHLineIterator(0, y, width, true);
00319 switch(color_type)
00320 {
00321 case PNG_COLOR_TYPE_GRAY:
00322 case PNG_COLOR_TYPE_GRAY_ALPHA:
00323 if(color_nb_bits == 16)
00324 {
00325 Q_UINT16 *src = reinterpret_cast<Q_UINT16 *>(row_pointers[y]);
00326 while (!it.isDone()) {
00327 Q_UINT16 *d = reinterpret_cast<Q_UINT16 *>(it.rawData());
00328 d[0] = *(src++);
00329 if(transform) cmsDoTransform(transform, d, d, 1);
00330 if(hasalpha) d[1] = *(src++);
00331 else d[1] = Q_UINT16_MAX;
00332 ++it;
00333 }
00334 } else {
00335 Q_UINT8 *src = row_pointers[y];
00336 while (!it.isDone()) {
00337 Q_UINT8 *d = it.rawData();
00338 d[0] = *(src++);
00339 if(transform) cmsDoTransform(transform, d, d, 1);
00340 if(hasalpha) d[1] = *(src++);
00341 else d[1] = Q_UINT8_MAX;
00342 ++it;
00343 }
00344 }
00345
00346 break;
00347 case PNG_COLOR_TYPE_RGB:
00348 case PNG_COLOR_TYPE_RGB_ALPHA:
00349 if(color_nb_bits == 16)
00350 {
00351 Q_UINT16 *src = reinterpret_cast<Q_UINT16 *>(row_pointers[y]);
00352 while (!it.isDone()) {
00353 Q_UINT16 *d = reinterpret_cast<Q_UINT16 *>(it.rawData());
00354 d[2] = *(src++);
00355 d[1] = *(src++);
00356 d[0] = *(src++);
00357 if(transform) cmsDoTransform(transform, d, d, 1);
00358 if(hasalpha) d[3] = *(src++);
00359 else d[3] = Q_UINT16_MAX;
00360 ++it;
00361 }
00362 } else {
00363 Q_UINT8 *src = row_pointers[y];
00364 while (!it.isDone()) {
00365 Q_UINT8 *d = it.rawData();
00366 d[2] = *(src++);
00367 d[1] = *(src++);
00368 d[0] = *(src++);
00369 if(transform) cmsDoTransform(transform, d, d, 1);
00370 if(hasalpha) d[3] = *(src++);
00371 else d[3] = Q_UINT8_MAX;
00372 ++it;
00373 }
00374 }
00375 break;
00376 case PNG_COLOR_TYPE_PALETTE:
00377 switch(color_nb_bits)
00378 {
00379 case 8:
00380 {
00381 Q_UINT8 *src = row_pointers[y];
00382 while (!it.isDone()) {
00383 Q_UINT8 *d = it.rawData();
00384 png_color c = palette[*(src++)];
00385 d[2] = c.red;
00386 d[1] = c.green;
00387 d[0] = c.blue;
00388 d[3] = Q_UINT8_MAX;
00389 ++it;
00390 }
00391 break;
00392 }
00393 default:
00394 return KisImageBuilder_RESULT_UNSUPPORTED;
00395 }
00396
00397 break;
00398 default:
00399 return KisImageBuilder_RESULT_UNSUPPORTED;
00400 }
00401 }
00402 m_img->addLayer(layer, m_img->rootLayer(), 0);
00403
00404
00405 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00406
00407 for (png_uint_32 y = 0; y < height; y++) {
00408 delete[] row_pointers[y];
00409 }
00410 delete [] row_pointers;
00411
00412 return KisImageBuilder_RESULT_OK;
00413
00414 }
00415
00416 KisImageBuilder_Result KisPNGConverter::buildImage(const KURL& uri)
00417 {
00418 kdDebug(41008) << QFile::encodeName(uri.path()) << " " << uri.path() << " " << uri << endl;
00419 if (uri.isEmpty())
00420 return KisImageBuilder_RESULT_NO_URI;
00421
00422 if (!KIO::NetAccess::exists(uri, false, qApp -> mainWidget())) {
00423 return KisImageBuilder_RESULT_NOT_EXIST;
00424 }
00425
00426
00427 KisImageBuilder_Result result = KisImageBuilder_RESULT_FAILURE;
00428 QString tmpFile;
00429
00430 if (KIO::NetAccess::download(uri, tmpFile, qApp -> mainWidget())) {
00431 KURL uriTF;
00432 uriTF.setPath( tmpFile );
00433 result = decode(uriTF);
00434 KIO::NetAccess::removeTempFile(tmpFile);
00435 }
00436
00437 return result;
00438 }
00439
00440
00441 KisImageSP KisPNGConverter::image()
00442 {
00443 return m_img;
00444 }
00445
00446
00447 KisImageBuilder_Result KisPNGConverter::buildFile(const KURL& uri, KisPaintLayerSP layer, vKisAnnotationSP_it annotationsStart, vKisAnnotationSP_it annotationsEnd, int compression, bool interlace, bool alpha)
00448 {
00449 kdDebug(41008) << "Start writing PNG File" << endl;
00450 if (!layer)
00451 return KisImageBuilder_RESULT_INVALID_ARG;
00452
00453 KisImageSP img = layer -> image();
00454 if (!img)
00455 return KisImageBuilder_RESULT_EMPTY;
00456
00457 if (uri.isEmpty())
00458 return KisImageBuilder_RESULT_NO_URI;
00459
00460 if (!uri.isLocalFile())
00461 return KisImageBuilder_RESULT_NOT_LOCAL;
00462
00463 FILE *fp = fopen(QFile::encodeName(uri.path()), "wb");
00464 if (!fp)
00465 {
00466 return (KisImageBuilder_RESULT_FAILURE);
00467 }
00468 int height = img->height();
00469 int width = img->width();
00470
00471 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL);
00472 if (!png_ptr)
00473 {
00474 KIO::del(uri);
00475 return (KisImageBuilder_RESULT_FAILURE);
00476 }
00477
00478 png_infop info_ptr = png_create_info_struct(png_ptr);
00479 if (!info_ptr)
00480 {
00481 KIO::del(uri);
00482 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
00483 return (KisImageBuilder_RESULT_FAILURE);
00484 }
00485
00486
00487 if (setjmp(png_jmpbuf(png_ptr)))
00488 {
00489 KIO::del(uri);
00490 png_destroy_write_struct(&png_ptr, &info_ptr);
00491 fclose(fp);
00492 return (KisImageBuilder_RESULT_FAILURE);
00493 }
00494
00495 png_init_io(png_ptr, fp);
00496
00497
00498
00499
00500
00501
00502 png_set_compression_level(png_ptr, compression);
00503
00504
00505 png_set_compression_mem_level(png_ptr, 8);
00506 png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
00507 png_set_compression_window_bits(png_ptr, 15);
00508 png_set_compression_method(png_ptr, 8);
00509 png_set_compression_buffer_size(png_ptr, 8192);
00510
00511 int color_nb_bits = 8 * layer->paintDevice()->pixelSize() / layer->paintDevice()->nChannels();
00512 int color_type = getColorTypeforColorSpace(img->colorSpace(), alpha);
00513
00514 if(color_type == -1)
00515 {
00516 return KisImageBuilder_RESULT_UNSUPPORTED;
00517 }
00518
00519 int interlacetype = interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE;
00520
00521 png_set_IHDR(png_ptr, info_ptr,
00522 width,
00523 height,
00524 color_nb_bits,
00525 color_type, interlacetype,
00526 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
00527
00528 png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_ABSOLUTE);
00529
00530
00531 vKisAnnotationSP_it it = annotationsStart;
00532 while(it != annotationsEnd) {
00533 if (!(*it) || (*it) -> type() == QString()) {
00534 kdDebug(41008) << "Warning: empty annotation" << endl;
00535 ++it;
00536 continue;
00537 }
00538
00539 kdDebug(41008) << "Trying to store annotation of type " << (*it) -> type() << " of size " << (*it) -> annotation() . size() << endl;
00540
00541 if ((*it) -> type().startsWith("krita_attribute:")) {
00542
00543 kdDebug(41008) << "can't save this annotation : " << (*it) -> type() << endl;
00544 } else {
00545 char* name = new char[(*it)->type().length()+1];
00546 strcpy(name, (*it)->type().ascii());
00547 png_set_iCCP(png_ptr, info_ptr, name, PNG_COMPRESSION_TYPE_BASE, (char*)(*it)->annotation().data(), (*it) -> annotation() . size());
00548 }
00549 ++it;
00550 }
00551
00552
00553 png_text texts[3];
00554 int nbtexts = 0;
00555 KoDocumentInfo * info = m_doc->documentInfo();
00556 KoDocumentInfoAbout * aboutPage = static_cast<KoDocumentInfoAbout *>(info->page( "about" ));
00557 QString title = aboutPage->title();
00558 if(!title.isEmpty())
00559 {
00560 fillText(texts+nbtexts, "title", title);
00561 nbtexts++;
00562 }
00563 QString abstract = aboutPage->abstract();
00564 if(!abstract.isEmpty())
00565 {
00566 fillText(texts+nbtexts, "abstract", abstract);
00567 nbtexts++;
00568 }
00569 KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor *>(info->page( "author" ));
00570 QString author = authorPage->fullName();
00571 if(!author.isEmpty())
00572 {
00573 fillText(texts+nbtexts, "author", author);
00574 nbtexts++;
00575 }
00576
00577 png_set_text(png_ptr, info_ptr, texts, nbtexts);
00578
00579
00580 png_write_info(png_ptr, info_ptr);
00581 png_write_flush(png_ptr);
00582
00583
00584 #ifndef WORDS_BIGENDIAN
00585 if (color_nb_bits > 8 )
00586 png_set_swap(png_ptr);
00587 #endif
00588
00589
00590
00591
00592
00593 png_byte** row_pointers= new png_byte*[height];
00594
00595 for (int y = 0; y < height; y++) {
00596 KisHLineIterator it = layer->paintDevice()->createHLineIterator(0, y, width, false);
00597 row_pointers[y] = new png_byte[width*layer->paintDevice()->pixelSize()];
00598 switch(color_type)
00599 {
00600 case PNG_COLOR_TYPE_GRAY:
00601 case PNG_COLOR_TYPE_GRAY_ALPHA:
00602 if(color_nb_bits == 16)
00603 {
00604 Q_UINT16 *dst = reinterpret_cast<Q_UINT16 *>(row_pointers[y]);
00605 while (!it.isDone()) {
00606 const Q_UINT16 *d = reinterpret_cast<const Q_UINT16 *>(it.rawData());
00607 *(dst++) = d[0];
00608 if(alpha) *(dst++) = d[1];
00609 ++it;
00610 }
00611 } else {
00612 Q_UINT8 *dst = row_pointers[y];
00613 while (!it.isDone()) {
00614 const Q_UINT8 *d = it.rawData();
00615 *(dst++) = d[0];
00616 if(alpha) *(dst++) = d[1];
00617 ++it;
00618 }
00619 }
00620 break;
00621 case PNG_COLOR_TYPE_RGB:
00622 case PNG_COLOR_TYPE_RGB_ALPHA:
00623 if(color_nb_bits == 16)
00624 {
00625 Q_UINT16 *dst = reinterpret_cast<Q_UINT16 *>(row_pointers[y]);
00626 while (!it.isDone()) {
00627 const Q_UINT16 *d = reinterpret_cast<const Q_UINT16 *>(it.rawData());
00628 *(dst++) = d[2];
00629 *(dst++) = d[1];
00630 *(dst++) = d[0];
00631 if(alpha) *(dst++) = d[3];
00632 ++it;
00633 }
00634 } else {
00635 Q_UINT8 *dst = row_pointers[y];
00636 while (!it.isDone()) {
00637 const Q_UINT8 *d = it.rawData();
00638 *(dst++) = d[2];
00639 *(dst++) = d[1];
00640 *(dst++) = d[0];
00641 if(alpha) *(dst++) = d[3];
00642 ++it;
00643 }
00644 }
00645 break;
00646 default:
00647 KIO::del(uri);
00648 return KisImageBuilder_RESULT_UNSUPPORTED;
00649 }
00650 }
00651
00652 png_write_image(png_ptr, row_pointers);
00653
00654
00655 png_write_end(png_ptr, info_ptr);
00656
00657
00658 png_destroy_write_struct(&png_ptr, &info_ptr);
00659 for (int y = 0; y < height; y++) {
00660 delete[] row_pointers[y];
00661 }
00662 delete[] row_pointers;
00663
00664 fclose(fp);
00665
00666 return KisImageBuilder_RESULT_OK;
00667 }
00668
00669
00670 void KisPNGConverter::cancel()
00671 {
00672 m_stop = true;
00673 }
00674
00675 void KisPNGConverter::progress(png_structp png_ptr, png_uint_32 row_number, int pass)
00676 {
00677 if(png_ptr == NULL || row_number > PNG_MAX_UINT || pass > 7) return;
00678
00679 }
00680
00681
00682 #include "kis_png_converter.moc"
00683