Summary: | kfaxview lowres scaling issue/no LZW compression | ||
---|---|---|---|
Product: | [Applications] kviewshell | Reporter: | Hans-Peter Jansen <hpj> |
Component: | general | Assignee: | Matthias Hoelzer-Kluepfel <hoelzer> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | deller, hpj, kebekus |
Priority: | NOR | ||
Version: | unspecified | ||
Target Milestone: | --- | ||
Platform: | Unlisted Binaries | ||
OS: | Linux | ||
Latest Commit: | Version Fixed In: |
Description
Hans-Peter Jansen
2006-07-23 23:36:29 UTC
SVN commit 578144 by whuss: Support LZW compressed fax files. This adds a dependency to libtiff. BUG: 131263 M +5 -1 Makefile.am A configure.in.bot M +2 -2 fax/Makefile.am A fax/configure.in.in M +82 -37 fax/faxrenderer.cpp M +6 -5 fax/faxrenderer.h --- branches/work/kviewshell-0.7/kviewshell/plugins/Makefile.am #578143:578144 @@ -2,4 +2,8 @@ KVS_PDF_SUBDIR=pdf endif -SUBDIRS = djvu dvi fax $(KVS_PDF_SUBDIR) ps +if include_TIFF +KVS_FAX_SUBDIR=fax +endif + +SUBDIRS = djvu dvi $(KVS_FAX_SUBDIR) $(KVS_PDF_SUBDIR) ps --- branches/work/kviewshell-0.7/kviewshell/plugins/fax/Makefile.am #578143:578144 @@ -17,11 +17,11 @@ kde_module_LTLIBRARIES = kfaxviewpart.la kfaxviewpart_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module kfaxviewpart_la_LIBADD = -lkdeprint -lkparts $(top_builddir)/kviewshell/shell/libkmultipage.la \ - libkfaximage/libkfaximage.la + libkfaximage/libkfaximage.la $(LIBTIFF) kfaxviewpart_la_SOURCES = faxmultipage.cpp faxrenderer.cpp faxprintsettings.cpp pluginsdir = $(kde_datadir) -#plugins_DATA = +#plugins_DATA = partdesktopdir = $(kde_servicesdir) partdesktop_DATA = kvs_fax_part.desktop --- branches/work/kviewshell-0.7/kviewshell/plugins/fax/faxrenderer.cpp #578143:578144 @@ -33,7 +33,7 @@ //#define KF_DEBUG FaxRenderer::FaxRenderer(KMultiPage* _multiPage) - : DocumentRenderer(_multiPage) + : DocumentRenderer(_multiPage), fax(0) { #ifdef KF_DEBUG kdError(kvs::fax) << "FaxRenderer( parent=" << par << " )" << endl; @@ -79,7 +79,9 @@ double resolution = id.resolution; - QImage img = fax.page(id.pageNumber - 1); + QImage img = getRawImage(id.pageNumber); + if (img.isNull()) + return 0; SimplePageSize psize = pageSizes[id.pageNumber - 1]; if (psize.isValid()) @@ -123,11 +125,17 @@ QMutexLocker locker(&mutex); // If fname is the empty string, then this means: "close". - if (fname.isEmpty()) { + if (fname.isEmpty()) + { + if (fax) + { + TIFFClose(fax); + fax = 0; + } kdDebug(kvs::fax) << "FaxRenderer::setFile( ... ) called with empty filename. Closing the file." << endl; return true; } - + // Paranoid saftey checks: make sure the file actually exists, and // that it is a file, not a directory. Otherwise, show an error // message and exit.. @@ -143,51 +151,44 @@ // Now we assume that the file is fine and load the file into the // fax member. We abort on error and give an error message. - bool ok = fax.loadImage(filename); + fax = TIFFOpen(QFile::encodeName( filename ), "r"); + if (!fax) + { + KMessageBox::error(parentWidget, + i18n("<qt><strong>File error.</strong> The specified file '%1' could not be loaded.</qt>").arg(filename), + i18n("File Error")); - // It can happen that fax.loadImage() returns with 'ok == true', but - // still the file could NOT be loaded. This happens, e.g. for TIFF - // file that do NOT contain FAX, but other image formats. We handle - // that case here also. - if ( (!ok) || (fax.numPages() == 0)) { - // Unfortunately, it can happen that fax.loadImage() fails WITHOUT - // leaving an error message in fax.errorString(). We try to handle - // this case gracefully. - if (fax.errorString().isEmpty()) - KMessageBox::error( parentWidget, - i18n("<qt><strong>File error.</strong> The specified file '%1' could not be loaded.</qt>").arg(filename), - i18n("File Error")); - else - KMessageBox::detailedError( parentWidget, - i18n("<qt><strong>File error.</strong> The specified file '%1' could not be loaded.</qt>").arg(filename), - fax.errorString(), - i18n("File Error")); clear(); return false; } // Set the number of pages page sizes - numPages = fax.numPages(); + tdir_t dirs = TIFFNumberOfDirectories(fax); + numPages = dirs; // Set the page size for the first page in the pageSizes array. // The rest of the page sizes will be calculated on demand by the drawPage function. pageSizes.resize(numPages); Length w,h; - if (numPages != 0) { - for(Q_UINT16 pg=0; pg < numPages; pg++) { - QSize pageSize = fax.page_size(pg); - QPoint dpi = fax.page_dpi(pg); - double dpix = dpi.x(); - double dpiy = dpi.y(); + if (numPages != 0) + { + for(tdir_t pg = 0; pg < dirs; pg++) + { + if (!TIFFSetDirectory(fax, pg)) + continue; - if (dpix*dpiy < 1.0) { - kdError(kvs::fax) << "File invalid resolutions, dpi x = " << dpix << ", dpi y = " << dpiy << ". This information will be ignored and 75 DPI assumed." << endl; - dpix = dpiy = 75.0; - } + QPoint dpi = getDPI(pg + 1); - w.setLength_in_inch(pageSize.width() / dpix); - h.setLength_in_inch(pageSize.height() / dpiy); + Q_UINT32 width = 0; + Q_UINT32 height = 0; + + if (TIFFGetField(fax, TIFFTAG_IMAGEWIDTH, &width) != 1 || + TIFFGetField(fax, TIFFTAG_IMAGELENGTH, &height) != 1 ) + continue; + + w.setLength_in_inch(width / (double)dpi.x()); + h.setLength_in_inch(height / (double)dpi.y()); pageSizes[pg].setPageSize(w, h); } } @@ -199,13 +200,57 @@ QImage FaxRenderer::getRawImage(PageNumber page) { - return fax.page(page - 1); + if (!TIFFSetDirectory(fax, page - 1)) + return QImage(); + + Q_UINT32 width = 0; + Q_UINT32 height = 0; + + if (TIFFGetField(fax, TIFFTAG_IMAGEWIDTH, &width) != 1 || + TIFFGetField(fax, TIFFTAG_IMAGELENGTH, &height) != 1 ) + return QImage(); + + QImage img(width, height, 32); + Q_UINT32* data = (Q_UINT32*)img.bits(); + + if (TIFFReadRGBAImageOriented(fax, width, height, data, ORIENTATION_TOPLEFT) != 0) + { + Q_UINT32 size = width * height; + for (Q_UINT32 i = 0; i < size; ++i) + { + Q_UINT32 red = (data[i] & 0x00FF0000) >> 16; + Q_UINT32 blue = (data[i] & 0x000000FF) << 16; + data[i] = (data[i] & 0xFF00FF00) + red + blue; + } + } + else + { + return QImage(); + } + + return img; } QPoint FaxRenderer::getDPI(PageNumber page) { - return fax.page_dpi(page - 1); + if (!TIFFSetDirectory(fax, page-1)) + return QPoint(0, 0); + + float dpix = 0.0; + float dpiy = 0.0; + if (TIFFGetField(fax, TIFFTAG_XRESOLUTION, &dpix) != 1 || + TIFFGetField(fax, TIFFTAG_YRESOLUTION, &dpiy) != 1) + return QPoint(0, 0); + + kdDebug(kvs::fax) << "resolutions, dpi x = " << dpix << ", dpi y = " << dpiy << "." << endl; + + if (dpix <= 1 || dpiy <= 1) { + kdError(kvs::fax) << "File invalid resolutions, dpi x = " << dpix << ", dpi y = " << dpiy << ". This information will be ignored and 75 DPI assumed." << endl; + dpix = dpiy = 75; + } + + return QPoint((int)dpix, (int)dpiy); } #include "faxrenderer.moc" --- branches/work/kviewshell-0.7/kviewshell/plugins/fax/faxrenderer.h #578143:578144 @@ -23,12 +23,13 @@ #include "documentRenderer.h" -#include "kfaximage.h" +#include <tiffio.h> + class documentPage; /*! \brief Well-documented minimal implementation of a documentRenderer for reading FAX files - + This class provides a well-documented reference implementation of a documentRenderer, suitable as a starting point for a real-world implementation. This class is responsible for document loading and @@ -65,7 +66,7 @@ is contained in the class "KFaxImage", to keep this reference implementation short. - @param fname the name of the file that should be opened. + @param fname the name of the file that should be opened. */ virtual bool setFile(const QString& fname, const KURL &); @@ -84,8 +85,8 @@ QPoint getDPI(PageNumber page); private: - /** This class holds the fax file */ - KFaxImage fax; + /** This pointer holds the fax file */ + TIFF* fax; }; #endif SVN commit 599807 by whuss: port of commit 578144: Support LZW compressed fax files. This adds a dependency to libtiff. CCBUG: 131263 M +7 -1 CMakeLists.txt M +2 -4 fax/CMakeLists.txt M +91 -46 fax/faxrenderer.cpp M +6 -5 fax/faxrenderer.h --- trunk/KDE/kdegraphics/kviewshell/plugins/CMakeLists.txt #599806:599807 @@ -9,8 +9,14 @@ if(FreeType2_FOUND) add_subdirectory( dvi ) endif(FreeType2_FOUND) -add_subdirectory( fax ) +macro_optional_find_package(TIFF) +if(TIFF_FOUND) + add_subdirectory( fax ) +else(TIFF_FOUND) + message(STATUS "libtiff was not found. The KViewShell FAX-plugin will not be build.") +endif(TIFF_FOUND) + macro_optional_find_package(PopplerQt4) if (POPPLER_QT4_FOUND) add_subdirectory( pdf ) --- trunk/KDE/kdegraphics/kviewshell/plugins/fax/CMakeLists.txt #599806:599807 @@ -1,9 +1,7 @@ -add_subdirectory( libkfaximage ) +include_directories( ${CMAKE_SOURCE_DIR}/kviewshell/shell ) -include_directories( ${CMAKE_SOURCE_DIR}/kviewshell/shell ${CMAKE_CURRENT_SOURCE_DIR}/libkfaximage ) - ########### next target ############### set(kfaxviewpart_PART_SRCS faxmultipage.cpp faxrenderer.cpp faxprintsettings.cpp ) @@ -14,7 +12,7 @@ kde4_install_libtool_file( ${PLUGIN_INSTALL_DIR} kfaxviewpart ) -target_link_libraries(kfaxviewpart ${KDE4_KDEPRINT_LIBS} ${KDE4_KPARTS_LIBS} kmultipage kfaximage ) +target_link_libraries(kfaxviewpart ${KDE4_KDEPRINT_LIBS} ${KDE4_KPARTS_LIBS} ${TIFF_LIBRARIES} kmultipage ) install(TARGETS kfaxviewpart DESTINATION ${PLUGIN_INSTALL_DIR} ) --- trunk/KDE/kdegraphics/kviewshell/plugins/fax/faxrenderer.cpp #599806:599807 @@ -33,7 +33,7 @@ //#define KF_DEBUG FaxRenderer::FaxRenderer(KMultiPage* _multiPage) - : DocumentRenderer(_multiPage) + : DocumentRenderer(_multiPage), fax(0) { #ifdef KF_DEBUG kError(kvs::fax) << "FaxRenderer( parent=" << par << " )" << endl; @@ -79,7 +79,9 @@ double resolution = id.resolution; - QImage img = fax.page(id.pageNumber - 1); + QImage img = getRawImage(id.pageNumber); + if (img.isNull()) + return 0; SimplePageSize psize = pageSizes[id.pageNumber - 1]; if (psize.isValid()) @@ -113,17 +115,6 @@ } -QImage FaxRenderer::getRawImage(PageNumber page) -{ - return fax.page(page - 1); -} - -QPoint FaxRenderer::getDPI(PageNumber page) -{ - return fax.page_dpi(page - 1); -} - - bool FaxRenderer::setFile(const QString &fname, const KUrl &) { #ifdef KF_DEBUG @@ -134,11 +125,17 @@ QMutexLocker locker(&mutex); // If fname is the empty string, then this means: "close". - if (fname.isEmpty()) { + if (fname.isEmpty()) + { + if (fax) + { + TIFFClose(fax); + fax = 0; + } kDebug(kvs::fax) << "FaxRenderer::setFile( ... ) called with empty filename. Closing the file." << endl; return true; } - + // Paranoid saftey checks: make sure the file actually exists, and // that it is a file, not a directory. Otherwise, show an error // message and exit.. @@ -154,51 +151,44 @@ // Now we assume that the file is fine and load the file into the // fax member. We abort on error and give an error message. - bool ok = fax.loadImage(filename); + fax = TIFFOpen(QFile::encodeName( filename ), "r"); + if (!fax) + { + KMessageBox::error(parentWidget, + i18n("<qt><strong>File error.</strong> The specified file '%1' could not be loaded.</qt>").arg(filename), + i18n("File Error")); - // It can happen that fax.loadImage() returns with 'ok == true', but - // still the file could NOT be loaded. This happens, e.g. for TIFF - // file that do NOT contain FAX, but other image formats. We handle - // that case here also. - if ( (!ok) || (fax.numPages() == 0)) { - // Unfortunately, it can happen that fax.loadImage() fails WITHOUT - // leaving an error message in fax.errorString(). We try to handle - // this case gracefully. - if (fax.errorString().isEmpty()) - KMessageBox::error( parentWidget, - i18n("<qt><strong>File error.</strong> The specified file '%1' could not be loaded.</qt>", filename), - i18n("File Error")); - else - KMessageBox::detailedError( parentWidget, - i18n("<qt><strong>File error.</strong> The specified file '%1' could not be loaded.</qt>", filename), - fax.errorString(), - i18n("File Error")); clear(); return false; } // Set the number of pages page sizes - numPages = fax.numPages(); + tdir_t dirs = TIFFNumberOfDirectories(fax); + numPages = dirs; // Set the page size for the first page in the pageSizes array. // The rest of the page sizes will be calculated on demand by the drawPage function. pageSizes.resize(numPages); Length w,h; - if (numPages != 0) { - for(quint16 pg=0; pg < numPages; pg++) { - QSize pageSize = fax.page_size(pg); - QPoint dpi = fax.page_dpi(pg); - double dpix = dpi.x(); - double dpiy = dpi.y(); + if (numPages != 0) + { + for(tdir_t pg = 0; pg < dirs; pg++) + { + if (!TIFFSetDirectory(fax, pg)) + continue; - if (dpix*dpiy < 1.0) { - kError(kvs::fax) << "File invalid resolutions, dpi x = " << dpix << ", dpi y = " << dpiy << ". This information will be ignored and 75 DPI assumed." << endl; - dpix = dpiy = 75.0; - } + QPoint dpi = getDPI(pg + 1); - w.setLength_in_inch(pageSize.width() / dpix); - h.setLength_in_inch(pageSize.height() / dpiy); + quint32 width = 0; + quint32 height = 0; + + if (TIFFGetField(fax, TIFFTAG_IMAGEWIDTH, &width) != 1 || + TIFFGetField(fax, TIFFTAG_IMAGELENGTH, &height) != 1 ) + continue; + + w.setLength_in_inch(width / (double)dpi.x()); + h.setLength_in_inch(height / (double)dpi.y()); pageSizes[pg].setPageSize(w, h); } } @@ -208,4 +198,59 @@ } +QImage FaxRenderer::getRawImage(PageNumber page) +{ + if (!TIFFSetDirectory(fax, page - 1)) + return QImage(); + + quint32 width = 0; + quint32 height = 0; + + if (TIFFGetField(fax, TIFFTAG_IMAGEWIDTH, &width) != 1 || + TIFFGetField(fax, TIFFTAG_IMAGELENGTH, &height) != 1 ) + return QImage(); + + QImage img(width, height, 32); + quint32* data = (quint32*)img.bits(); + + if (TIFFReadRGBAImageOriented(fax, width, height, data, ORIENTATION_TOPLEFT) != 0) + { + quint32 size = width * height; + for (quint32 i = 0; i < size; ++i) + { + Q_UINT32 red = (data[i] & 0x00FF0000) >> 16; + Q_UINT32 blue = (data[i] & 0x000000FF) << 16; + data[i] = (data[i] & 0xFF00FF00) + red + blue; + } + } + else + { + return QImage(); + } + + return img; +} + + +QPoint FaxRenderer::getDPI(PageNumber page) +{ + if (!TIFFSetDirectory(fax, page-1)) + return QPoint(0, 0); + + float dpix = 0.0; + float dpiy = 0.0; + if (TIFFGetField(fax, TIFFTAG_XRESOLUTION, &dpix) != 1 || + TIFFGetField(fax, TIFFTAG_YRESOLUTION, &dpiy) != 1) + return QPoint(0, 0); + + kDebug(kvs::fax) << "resolutions, dpi x = " << dpix << ", dpi y = " << dpiy << "." << endl; + + if (dpix <= 1 || dpiy <= 1) { + kError(kvs::fax) << "File invalid resolutions, dpi x = " << dpix << ", dpi y = " << dpiy << ". This information will be ignored and 75 DPI assumed." << endl; + dpix = dpiy = 75; + } + + return QPoint((int)dpix, (int)dpiy); +} + #include "faxrenderer.moc" --- trunk/KDE/kdegraphics/kviewshell/plugins/fax/faxrenderer.h #599806:599807 @@ -24,12 +24,13 @@ #include <qimage.h> #include "documentRenderer.h" -#include "kfaximage.h" +#include <tiffio.h> + class documentPage; /*! \brief Well-documented minimal implementation of a documentRenderer for reading FAX files - + This class provides a well-documented reference implementation of a documentRenderer, suitable as a starting point for a real-world implementation. This class is responsible for document loading and @@ -66,7 +67,7 @@ is contained in the class "KFaxImage", to keep this reference implementation short. - @param fname the name of the file that should be opened. + @param fname the name of the file that should be opened. */ virtual bool setFile(const QString& fname, const KUrl &); @@ -85,8 +86,8 @@ QPoint getDPI(PageNumber page); private: - /** This class holds the fax file */ - KFaxImage fax; + /** This pointer holds the fax file */ + TIFF* fax; }; #endif |