/*!\brief Prüfen, ob es sich um ein PFP-File handelt * * \desc * Diese Funktion prüft, ob es sich bei der geöffneten Datei \p ff um eine Datei * im \ref PFPFileVersion3 PFP-Format Version 3 handelt. Ist dies der Fall, wird deren * ID und Version eingelesen. * * @param ff Referenz auf eine geöffnete Datei * @return Gibt \c true zurück, wenn es sich um eine Datei im PFP-Format handelt. Deren * ID kann anschließend mit PFPFile::getID ausgelesen werden, Version mit PFPFile::getVersion bzw. * PFPFile::getMainVersion und PFPFile::getSubVersion. Handelt es sich nicht um eine Datei * im PFP-Format, gibt die Funktion \c false zurück. Es wird keine Exception geworfen. */ bool PFPFile::ident(FileObject &ff) { try { const char *p; p=ff.map(0,24); if (strncmp(p,"PFP-File",8)!=0) return false; if (Peek8(p+8)!=3) return false; id.set(p+10,4); mainversion=Peek8(p+15); subversion=Peek8(p+14); comp=(Compression::Algorithm)Peek8(p+16); return true; } catch (...) { return false; } return false; }
int ImageFilter_PNG::ident(FileObject &file, IMAGE &img) { #ifdef HAVE_PNG try { const char *address=file.map(0,256); file.seek(0); if (address==NULL) return 0; if (png_sig_cmp((png_byte*)address, 0, 8)!=0) { // Ist es ein PNG-File? return 0; } png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL ,NULL, NULL); if (!png_ptr) return 0; png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr,(png_infopp)NULL, (png_infopp)NULL); return 0; } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return 0; } png_set_read_fn(png_ptr,&file, (png_rw_ptr) user_read_data); //png_set_write_fn(png_structp write_ptr, voidp write_io_ptr, png_rw_ptr write_data_fn, // png_flush_ptr output_flush_fn); png_read_info(png_ptr, info_ptr); img.width=png_get_image_width(png_ptr, info_ptr); img.height=png_get_image_height(png_ptr, info_ptr); img.bitdepth=png_get_bit_depth(png_ptr, info_ptr); img.colors=0; img.pitch=png_get_rowbytes(png_ptr, info_ptr); //img->pfp.header_version=0; bool supported=true; img.format=RGBFormat::unknown; if (img.bitdepth!=8) supported=false; // Nur 8-Bit/Farbwert wird unterstützt switch (png_get_color_type(png_ptr, info_ptr)) { case PNG_COLOR_TYPE_GRAY: img.bitdepth=8; img.colors=256; img.format=RGBFormat::GREY8; break; case PNG_COLOR_TYPE_PALETTE: img.bitdepth=8; img.colors=256; img.format=RGBFormat::Palette; //supported=false; break; case PNG_COLOR_TYPE_RGB: img.colors=0xffffff; img.bitdepth=24; img.format=RGBFormat::X8R8G8B8; break; case PNG_COLOR_TYPE_RGB_ALPHA: img.colors=0xffffff; img.bitdepth=32; img.format=RGBFormat::A8R8G8B8; break; case PNG_COLOR_TYPE_GRAY_ALPHA: img.colors=256; img.bitdepth=32; img.format=RGBFormat::GREYALPHA32; break; }; if (png_get_interlace_type(png_ptr,info_ptr)!=PNG_INTERLACE_NONE) { // Interlaced wird nicht unterstützt supported=false; } png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); if (!supported) { return 0; } return 1; } catch (...) { return 0; } return 0; #else return 0; #endif }
void PFPFile::load(FileObject &ff) /*!\brief PFP-File laden * * Mit dieser Funktion wird ein PFP-File in die Klasse geladen. Dabei wird zuerst der Header geladen * und überprüft, ob es sich um ein gültiges PFP-File handelt. Dann wird die virtuelle Funktion * PFPFile::LoadRequest mit ID, Haupt- und Unterversion als Parameter aufgerufen. Liefert diese * nicht true (1) zurück, wird der Ladevorgang abgebrochen. Andernfalls wird fortgeführt * und geprüft, ob der * Datenbereich komprimiert ist und gegebenenfalls dekomprimiert. Erst danach werden die * einzelnen Chunks eingelesen. Kommt es dabei zu Fehlern durch ungültige Chunks, werden diese * ignoriert und die Funktion gibt den Fehlercode 434 zurück. * * \param ff Pointer auf eine CFile-Klasse, mit der die einzulesende Datei geöffnet wurde. * \returns Konnte die Datei fehlerfrei eingelesen werden, gibt die Funktion true (1) zurück, * im Fehlerfall false (0). Ein entsprechender Fehlercode wird gesetzt. * * \remarks * Vor dem Laden der Datei wird die Funktion PFPFile::Clear aufgerufen, so dass eventuell vorher * vorhandene Daten verloren gehen. * * \since Version 6.1.0 */ { const char *p; try { p=ff.map(0,24); } catch (OverflowException &) { throw InvalidFormatException(); } if (strncmp(p,"PFP-File",8)!=0) throw InvalidFormatException(); if (Peek8(p+8)!=3) throw InvalidFormatException(); size_t z,fsize; // Wir haben ein gültiges PFP-File, aber dürfen wir es auch laden? char tmpid[5]; tmpid[4]=0; strncpy(tmpid,p+10,4); int t1,t2; t1=Peek8(p+15); t2=Peek8(p+14); if (!loadRequest(tmpid,t1,t2)) { throw AccessDeniedByInstanceException(); } clear(); id.set(p+10,4); mainversion=Peek8(p+15); subversion=Peek8(p+14); comp=(Compression::Algorithm)Peek8(p+16); size_t hsize=Peek8(p+9); char *u=NULL; if (comp) { p=(char*)ff.map(hsize,8); if (!p) throw ReadException(); size_t sizeunk=Peek32(p); size_t sizecomp=Peek32(p+4); p=ff.map(hsize+8,sizecomp); if (!p) throw ReadException(); u=(char*)malloc(sizeunk+1); if (!u) throw OutOfMemoryException(); size_t dstlen=sizeunk; Compression c; try { c.init(comp); c.uncompress(u,&dstlen,p,sizecomp); } catch (...) { free(u); clear(); throw; } if (dstlen!=sizeunk) { free(u); clear(); throw DecompressionFailedException(); } u[dstlen]=0; p=u; fsize=dstlen; } else { p=ff.map(); p+=hsize; fsize=ff.size()-hsize; } // Wir haben nun den ersten Chunk ab Pointer p z=0; String Chunkname; try { size_t size=0; while ((z+=size)<fsize) { size=Peek32(p+z+4); if (strncmp(p+z,"ENDF",4)==0) break; if (!size) break; // Falls z+size über das Ende der Datei geht, stimmt mit diesem Chunk was nicht if (z+size>fsize) break; PFPChunk *chunk=new PFPChunk; if (!chunk) throw OutOfMemoryException(); Chunkname.set(p+z,4); chunk->setName(Chunkname); chunk->setData(p+z+8,size-8); addChunk(chunk); } } catch (...) { if (u) free(u); clear(); throw; } if (u) free(u); }