summaryrefslogtreecommitdiffstats
path: root/kfaxview
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit47d455dd55be855e4cc691c32f687f723d9247ee (patch)
tree52e236aaa2576bdb3840ebede26619692fed6d7d /kfaxview
downloadtdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.tar.gz
tdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegraphics@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kfaxview')
-rw-r--r--kfaxview/Makefile.am38
-rw-r--r--kfaxview/faxmultipage.cpp85
-rw-r--r--kfaxview/faxmultipage.h120
-rw-r--r--kfaxview/faxrenderer.cpp204
-rw-r--r--kfaxview/faxrenderer.h90
-rw-r--r--kfaxview/hi16-app-kfaxview.pngbin0 -> 787 bytes
-rw-r--r--kfaxview/hi22-app-kfaxview.pngbin0 -> 1241 bytes
-rw-r--r--kfaxview/hi32-app-kfaxview.pngbin0 -> 1928 bytes
-rw-r--r--kfaxview/hi48-app-kfaxview.pngbin0 -> 3352 bytes
-rw-r--r--kfaxview/hisc-app-kfaxview.svgzbin0 -> 11876 bytes
-rw-r--r--kfaxview/kfaxmultipage.desktop60
-rw-r--r--kfaxview/kfaxmultipage_tiff.desktop57
-rw-r--r--kfaxview/kfaxview.desktop82
-rw-r--r--kfaxview/libkfaximage/Makefile.am14
-rw-r--r--kfaxview/libkfaximage/faxexpand.cpp745
-rw-r--r--kfaxview/libkfaximage/faxexpand.h126
-rw-r--r--kfaxview/libkfaximage/faxinit.cpp345
-rw-r--r--kfaxview/libkfaximage/kfaximage.cpp667
-rw-r--r--kfaxview/libkfaximage/kfaximage.h162
-rw-r--r--kfaxview/main.cpp174
20 files changed, 2969 insertions, 0 deletions
diff --git a/kfaxview/Makefile.am b/kfaxview/Makefile.am
new file mode 100644
index 00000000..669fcd9b
--- /dev/null
+++ b/kfaxview/Makefile.am
@@ -0,0 +1,38 @@
+INCLUDES = -I$(top_srcdir)/kviewshell \
+ -I$(top_builddir)/kviewshell \
+ -I$(kde_includes)/kviewshell \
+ -I$(srcdir)/libkfaximage \
+ -I$(top_srcdir) $(all_includes)
+
+SUBDIRS = libkfaximage .
+
+KDE_ICON = kfaxview
+
+METASOURCES = AUTO
+
+bin_PROGRAMS = kfaxview
+kfaxview_SOURCES = main.cpp
+kfaxview_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+kfaxview_LDADD = ../kviewshell/libifaces.la ../kviewshell/libkviewshell.la -lkparts
+
+# this is where the desktop file will go
+kde_services_DATA = kfaxmultipage.desktop kfaxmultipage_tiff.desktop
+
+# this is where the shell's XML-GUI resource file goes
+shellrcdir = $(kde_datadir)/kfaxview
+
+kde_module_LTLIBRARIES = kfaxviewpart.la
+kfaxviewpart_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module
+kfaxviewpart_la_LIBADD = -lkdeprint -lkparts $(top_builddir)/kviewshell/libkmultipage.la libkfaximage/libkfaximage.la
+kfaxviewpart_la_SOURCES = faxmultipage.cpp faxrenderer.cpp
+
+partdir = $(kde_datadir)/kfaxview
+part_DATA = ../kviewshell/kviewshell.rc
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/kfaxview.pot
+
+xdg_apps_DATA = kfaxview.desktop
+
+# The next line switches the API documentation on
+include ../admin/Doxyfile.am
diff --git a/kfaxview/faxmultipage.cpp b/kfaxview/faxmultipage.cpp
new file mode 100644
index 00000000..bbf4e566
--- /dev/null
+++ b/kfaxview/faxmultipage.cpp
@@ -0,0 +1,85 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Stefan Kebekus *
+ * kebekus@kde.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <config.h>
+
+#include <kfiledialog.h>
+#include <kparts/genericfactory.h>
+
+#include "faxmultipage.h"
+
+
+
+typedef KParts::GenericFactory<FaxMultiPage> FaxMultiPageFactory;
+K_EXPORT_COMPONENT_FACTORY(kfaxviewpart, FaxMultiPageFactory)
+
+
+FaxMultiPage::FaxMultiPage(QWidget *parentWidget, const char *widgetName, QObject *parent,
+ const char *name, const QStringList&)
+ : KMultiPage(parentWidget, widgetName, parent, name), faxRenderer(parentWidget)
+{
+ /* This is kparts wizardry that cannot be understood by man. Simply
+ change the names to match your implementation. */
+ setInstance(FaxMultiPageFactory::instance());
+ faxRenderer.setName("Fax renderer");
+
+ setXMLFile("kfaxview.rc");
+
+ /* It is very important that this method is called in the
+ constructor. Otherwise kmultipage does not know how to render
+ files, and crashes may result. */
+ setRenderer(&faxRenderer);
+}
+
+
+FaxMultiPage::~FaxMultiPage()
+{
+ ;
+}
+
+
+KAboutData* FaxMultiPage::createAboutData()
+{
+ /* You obviously want to change this to match your setup */
+ KAboutData* about = new KAboutData("kfaxview", I18N_NOOP("KFaxView"), "0.1",
+ I18N_NOOP("KViewshell Fax Plugin."),
+ KAboutData::License_GPL,
+ "Stefan Kebekus",
+ I18N_NOOP("This program previews fax (g3) files."));
+
+ about->addAuthor ("Stefan Kebekus",
+ I18N_NOOP("Current Maintainer."),
+ "kebekus@kde.org",
+ "http://www.mi.uni-koeln.de/~kebekus");
+ return about;
+}
+
+
+QStringList FaxMultiPage::fileFormats() const
+{
+ /* This list is used in the file selection dialog when the file is
+ saved */
+ QStringList r;
+ r << i18n("*.g3|Fax (g3) file (*.g3)");
+ return r;
+}
+
+
+#include "faxmultipage.moc"
diff --git a/kfaxview/faxmultipage.h b/kfaxview/faxmultipage.h
new file mode 100644
index 00000000..1ea8b6c5
--- /dev/null
+++ b/kfaxview/faxmultipage.h
@@ -0,0 +1,120 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Stefan Kebekus *
+ * kebekus@kde.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef FAXMULTIPAGE_H
+#define FAXMULTIPAGE_H
+
+#include <qstringlist.h>
+
+#include "kmultipage.h"
+#include "faxrenderer.h"
+
+
+
+/*! \mainpage FaxMultiPage
+
+\section intro_sec Introduction
+
+FaxMultiPage is a minimal, but well-documented reference
+implementation of a kviewshell plugin that can serve as a starting
+point for implementations.
+
+\section install_sec Usage
+
+When FaxMultiPage and the associated files are installed, the
+kviewshell program can open TIFF-Fax anf G3 fax files, i.e. files of
+mime types image/fax-g3 or image/tiff.
+
+\section content Content
+
+Only the two classes that are absolutely necessary for a working
+plugin are implemented. The only other file that is installed are
+desktop file, which tells kviewshell to use the plugin.
+
+- FaxMultiPage, an implementation of a KMultiPage. In a larger
+application, this class would contain the GUI elements that the plugin
+adds to the GUI of the kviewshell. For viewing FAXes, no special GUI
+elements are required, and this plugin does only the minimal
+initialization required.
+
+- FaxRenderer, an implementation of a DocumentRenderer. This class is
+responsible for document loading and rendering.
+
+- kfaxmultipage.desktop and kfaxmultipage_tiff.desktop are desktop
+entry files that associate the plugin wit image/fax-g3 or image/tiff
+mime-types. Without these files installed, the file dialog in
+kviewshell would not show FAX files, and the command line "kvieshell
+test.g3" would fail with an error dialog "No plugin for image/fax-g3
+files installed".
+*/
+
+
+
+
+/*! \brief Well-documented minimal implementation of a KMultiPage
+
+This class provides a well-documented reference implementation of a
+KMultiPage, suitable as a starting point for a real-world
+implementation. In a larger application, this class would contain the
+GUI elements that the plugin adds to the GUI of the kviewshell. For
+viewing FAXes, no special GUI elements are required, and this plugin
+does only the minimal initialization required.
+*/
+
+class FaxMultiPage : public KMultiPage
+{
+ Q_OBJECT
+
+public:
+ /** Constructor
+
+ The constructor needs to initialize several members of the
+ kmultipage. Please have a look at the constructor's source code to
+ see how to adjust this for your implementation.
+ */
+ FaxMultiPage(QWidget *parentWidget, const char *widgetName, QObject *parent,
+ const char *name, const QStringList& args = QStringList());
+
+ /** Destructor
+
+ This destructor does nothing.
+ */
+ virtual ~FaxMultiPage();
+
+ /** List of file formats for file saving
+
+ This method returns the list of supported file formats for saving
+ the file.
+ */
+ virtual QStringList fileFormats() const;
+
+ /** Author information
+
+ This member returns a structure that contains information about the
+ authors of the implementation
+ */
+ static KAboutData* createAboutData();
+
+ private:
+ /** This member holds the renderer which is used by the demo implementation */
+ FaxRenderer faxRenderer;
+};
+
+#endif
diff --git a/kfaxview/faxrenderer.cpp b/kfaxview/faxrenderer.cpp
new file mode 100644
index 00000000..ec18d431
--- /dev/null
+++ b/kfaxview/faxrenderer.cpp
@@ -0,0 +1,204 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Stefan Kebekus *
+ * kebekus@kde.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <config.h>
+
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <qfileinfo.h>
+#include <qpainter.h>
+
+#include "documentWidget.h"
+#include "faxrenderer.h"
+#include "faxmultipage.h"
+
+//#define KF_DEBUG
+
+FaxRenderer::FaxRenderer(QWidget* par)
+ : DocumentRenderer(par)
+{
+#ifdef KF_DEBUG
+ kdError() << "FaxRenderer( parent=" << par << " )" << endl;
+#endif
+}
+
+
+
+FaxRenderer::~FaxRenderer()
+{
+#ifdef KF_DEBUG
+ kdDebug() << "~FaxRenderer" << endl;
+#endif
+
+ // Wait for all access to this documentRenderer to finish
+ mutex.lock();
+ mutex.unlock();
+}
+
+
+void FaxRenderer::drawPage(double resolution, RenderedDocumentPage* page)
+{
+#ifdef KF_DEBUG
+ kdDebug() << "FaxRenderer::drawPage(documentPage*) called, page number " << page->getPageNumber() << endl;
+#endif
+
+ // Paranoid safety checks
+ if (page == 0) {
+ kdError() << "FaxRenderer::drawPage(documentPage*) called with argument == 0" << endl;
+ return;
+ }
+ if (page->getPageNumber() == 0) {
+ kdError() << "FaxRenderer::drawPage(documentPage*) called for a documentPage with page number 0" << endl;
+ return;
+ }
+
+ // Wait for all access to this documentRenderer to finish
+ mutex.lock();
+
+ // more paranoid safety checks
+ if (page->getPageNumber() > numPages) {
+ kdError() << "FaxRenderer::drawPage(documentPage*) called for a documentPage with page number " << page->getPageNumber()
+ << " but the current fax file has only " << numPages << " pages." << endl;
+ mutex.unlock();
+ return;
+ }
+
+ QImage img = fax.page(page->getPageNumber() - 1);
+
+ SimplePageSize psize = pageSizes[page->getPageNumber() - 1];
+ if (psize.isValid()) {
+ QPainter *foreGroundPaint = page->getPainter();
+ if (foreGroundPaint != 0) {
+ // Compute an image for the page.
+
+ // WARNING: It may be tempting to compute the image size in
+ // pixel, using page->height() and page->width(). DON'T DO
+ // THAT. KViewShell uses transformations e.g. to rotate the
+ // page, and sets the argument 'resolution' accordingly. Similar
+ // problems occur if KViewShell required a shrunken version of
+ // the page, e.g. to print multiple pages on one sheet of paper.
+
+ int width_in_pixel = qRound(resolution * psize.width().getLength_in_inch());
+ int height_in_pixel = qRound(resolution * psize.height().getLength_in_inch());
+
+ img = img.smoothScale(width_in_pixel, height_in_pixel);
+ foreGroundPaint->drawImage(0, 0, img);
+ page->returnPainter(foreGroundPaint);
+ }
+ } else
+ kdError() << "FaxRenderer::drawPage() called, but page size for page " << page->getPageNumber() << " is invalid." << endl;
+
+ // To indicate that the page was drawn, we set the appropriate flas in the page structure
+ page->isEmpty = false;
+
+ mutex.unlock();
+}
+
+
+bool FaxRenderer::setFile(const QString &fname, const KURL &)
+{
+#ifdef KF_DEBUG
+ kdDebug() << "FaxRenderer::setFile(" << fname << ") called" << endl;
+#endif
+
+ // Wait for all access to this documentRenderer to finish
+ mutex.lock();
+
+ // If fname is the empty string, then this means: "close".
+ if (fname.isEmpty()) {
+ kdDebug() << "FaxRenderer::setFile( ... ) called with empty filename. Closing the file." << endl;
+ mutex.unlock();
+ 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..
+ QFileInfo fi(fname);
+ QString filename = fi.absFilePath();
+ if (!fi.exists() || fi.isDir()) {
+ KMessageBox::error( parentWidget,
+ i18n("<qt><strong>File error.</strong> The specified file '%1' does not exist.</qt>").arg(filename),
+ i18n("File Error"));
+ // the return value 'false' indicates that this operation was not successful.
+ mutex.unlock();
+ return false;
+ }
+
+ // 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);
+
+ // 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();
+ mutex.unlock();
+ return false;
+ }
+
+ // Set the number of pages page sizes
+ numPages = fax.numPages();
+
+ // 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 (dpix*dpiy < 1.0) {
+ kdError() << "File invalid resolutions, dpi x = " << dpix << ", dpi y = " << dpiy << ". This information will be ignored and 75 DPI assumed." << endl;
+ dpix = dpiy = 75.0;
+ }
+
+ w.setLength_in_inch(pageSize.width() / dpix);
+ h.setLength_in_inch(pageSize.height() / dpiy);
+ pageSizes[pg].setPageSize(w, h);
+ }
+ }
+
+ // the return value 'true' indicates that this operation was not successful.
+ mutex.unlock();
+ return true;
+}
+
+
+#include "faxrenderer.moc"
diff --git a/kfaxview/faxrenderer.h b/kfaxview/faxrenderer.h
new file mode 100644
index 00000000..d2b37657
--- /dev/null
+++ b/kfaxview/faxrenderer.h
@@ -0,0 +1,90 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Stefan Kebekus *
+ * kebekus@kde.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef _FAXRENDERER_H_
+#define _FAXRENDERER_H_
+
+
+#include "documentRenderer.h"
+#include "kfaximage.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
+rendering. Apart from the constructor and the descructor, it
+implements only the necessary methods setFile() and drawPage().
+*/
+
+class FaxRenderer : public DocumentRenderer
+{
+ Q_OBJECT
+
+public:
+ /** Default constructor
+
+ This constructor simply prints a message (if debugging is
+ enabled) and calls the default constructor.
+ */
+ FaxRenderer(QWidget* parent);
+
+ /** Destructor
+
+ The destructor simpley prints a message if debugging is
+ enabled. It uses the mutex to ensure that this class is not
+ destructed while another thread is currently using it.
+ */
+ ~FaxRenderer();
+
+ /** Opening a file
+
+ This implementation does the necessary consistency checks and
+ complains, e.g. if the file does not exist. It then uses the
+ member 'fax' to load the fax file and initializes the
+ appropriate data structures. The code for loading and rendering
+ is contained in the class "KFaxImage", to keep this reference
+ implementation short.
+
+ @param fname the name of the file that should be opened.
+ */
+ virtual bool setFile(const QString& fname, const KURL &);
+
+ /** Rendering a page
+
+ This implementation first checks if the arguments are in a
+ reasonable range, and error messages are printed if this is not
+ so. Secondly, the page is rendered by the KFaxImage class and
+ the drawn.
+
+ @param res resolution at which drawing should take place
+
+ @param page pointer to a page structur on which we should draw
+ */
+ void drawPage(double res, RenderedDocumentPage* page);
+
+private:
+ /** This class holds the fax file */
+ KFaxImage fax;
+};
+
+#endif
diff --git a/kfaxview/hi16-app-kfaxview.png b/kfaxview/hi16-app-kfaxview.png
new file mode 100644
index 00000000..bb676f8b
--- /dev/null
+++ b/kfaxview/hi16-app-kfaxview.png
Binary files differ
diff --git a/kfaxview/hi22-app-kfaxview.png b/kfaxview/hi22-app-kfaxview.png
new file mode 100644
index 00000000..90fc64b0
--- /dev/null
+++ b/kfaxview/hi22-app-kfaxview.png
Binary files differ
diff --git a/kfaxview/hi32-app-kfaxview.png b/kfaxview/hi32-app-kfaxview.png
new file mode 100644
index 00000000..7330eb41
--- /dev/null
+++ b/kfaxview/hi32-app-kfaxview.png
Binary files differ
diff --git a/kfaxview/hi48-app-kfaxview.png b/kfaxview/hi48-app-kfaxview.png
new file mode 100644
index 00000000..3f58c369
--- /dev/null
+++ b/kfaxview/hi48-app-kfaxview.png
Binary files differ
diff --git a/kfaxview/hisc-app-kfaxview.svgz b/kfaxview/hisc-app-kfaxview.svgz
new file mode 100644
index 00000000..f46fd440
--- /dev/null
+++ b/kfaxview/hisc-app-kfaxview.svgz
Binary files differ
diff --git a/kfaxview/kfaxmultipage.desktop b/kfaxview/kfaxmultipage.desktop
new file mode 100644
index 00000000..1bfc9acc
--- /dev/null
+++ b/kfaxview/kfaxmultipage.desktop
@@ -0,0 +1,60 @@
+[Desktop Entry]
+Name=kfaxview
+Name[hu]=KFaxView
+Name[ja]=KfaxView
+Name[nb]=Kfaxview
+Name[ne]=केडीई फ्याक्स दृश्य
+Name[ro]=KFaxiView
+Name[sv]=Kfaxview
+Name[zh_CN]=KFaxView
+Icon=kfaxview
+Type=Service
+Comment=KViewShell plugin for fax files
+Comment[bg]=Приставка за факс файлове
+Comment[br]=Lugent KViewShell evit ar restroù faks
+Comment[bs]=KViewShell dodatak za fax datoteke
+Comment[ca]=Connector pel KViewShell per a fitxers de fax
+Comment[cs]=KViewShell modul pro faxové soubory
+Comment[da]=Kviewshell-plugin for telefaxfiler
+Comment[de]=Ein Modul für KViewShell zum Betrachten von Faxdateien
+Comment[el]=Πρόσθετο του KViewShell για αρχεία φαξ
+Comment[eo]=KViewShell-kromaĵo for faksdosieroj
+Comment[es]=Extensión KViewShell para archivos de fax
+Comment[et]=KView faksifailide plugin
+Comment[eu]=Fax fitxategientzatko KViewShell-en plugina
+Comment[fa]=وصلۀ KViewShell برای پرونده‌های دورنگار
+Comment[fi]=KViewShell sovelma faksitiedostoille
+Comment[fr]=Module KViewShell pour les fichiers de fax
+Comment[gl]=Extensión de KViewShell para ficheiros de fax
+Comment[hu]=KViewShell-modul faxfájlokhoz
+Comment[is]=KViewShell íforrit fyrir faxskrár
+Comment[it]=Plugin KViewShell per file di fax
+Comment[ja]=ファクスファイル用の KViewShell プラグイン
+Comment[kk]=Факс файлдарын қарау плагин модулі
+Comment[km]=កម្មវិធី​ជំនួយ KViewShell សម្រាប់​ឯកសារ​ទូរសារ
+Comment[lt]=KViewShell priedas fakso byloms
+Comment[ms]=Plugin KViewShell untuk fail faks
+Comment[nb]=KViewShell programtillegg for faksfiler
+Comment[nds]="KViewShell"-Moduul för Faxdateien
+Comment[ne]=फ्याक्स फाइलका लागि केडीई दृश्य शेल प्लगइन
+Comment[nl]=KViewShell-plugin voor faxbestanden
+Comment[nn]=KViewShell-programtillegg for faksfiler
+Comment[pl]=Wtyczka KViewShell do plików faksów
+Comment[pt]='Plugin' do KViewShell para ficheiros de Fax
+Comment[pt_BR]=Plugin KViewShell para arquivos de fax
+Comment[ru]=Компонент просмотра факсов
+Comment[sk]=KViewShell modul pre faxové súbory
+Comment[sl]=Vstavek za KViewShell za fakse
+Comment[sr]=KViewShell-ов прикључак за факс фајлове
+Comment[sr@Latn]=KViewShell-ov priključak za faks fajlove
+Comment[sv]=Kviewshell-insticksprogram för telefaxfiler
+Comment[th]=ปลั๊กอินสำหรับแสดงแฟ้มโทรสารของ KViewShell
+Comment[tr]=Faks dosyaları için KViewShell eklentisi
+Comment[uk]=Втулок перегляду файлів факсів для KViewShell
+Comment[zh_CN]=传真文件的 KViewShell 插件
+Comment[zh_HK]=傳真檔的 KViewShell 插件
+Comment[zh_TW]=KViewShell 傳真檔外掛程式
+ServiceTypes=KViewShell/MultiPage
+X-KDE-MimeTypes=image/fax-g3
+X-KDE-Library=kfaxviewpart
+X-KDE-MultiPageVersion=2
diff --git a/kfaxview/kfaxmultipage_tiff.desktop b/kfaxview/kfaxmultipage_tiff.desktop
new file mode 100644
index 00000000..a1b33913
--- /dev/null
+++ b/kfaxview/kfaxmultipage_tiff.desktop
@@ -0,0 +1,57 @@
+[Desktop Entry]
+Name=kfaxview_tiff
+Name[da]=Kfaxview TIFF
+Name[ne]=केडीई फ्याक्स दृश्य टिफ
+Name[sv]=Kfaxview TIFF
+Name[zh_CN]=KFaxView_tiff
+Icon=kfaxview
+Type=Service
+Comment=KViewShell plugin for fax files
+Comment[bg]=Приставка за факс файлове
+Comment[br]=Lugent KViewShell evit ar restroù faks
+Comment[bs]=KViewShell dodatak za fax datoteke
+Comment[ca]=Connector pel KViewShell per a fitxers de fax
+Comment[cs]=KViewShell modul pro faxové soubory
+Comment[da]=Kviewshell-plugin for telefaxfiler
+Comment[de]=Ein Modul für KViewShell zum Betrachten von Faxdateien
+Comment[el]=Πρόσθετο του KViewShell για αρχεία φαξ
+Comment[eo]=KViewShell-kromaĵo for faksdosieroj
+Comment[es]=Extensión KViewShell para archivos de fax
+Comment[et]=KView faksifailide plugin
+Comment[eu]=Fax fitxategientzatko KViewShell-en plugina
+Comment[fa]=وصلۀ KViewShell برای پرونده‌های دورنگار
+Comment[fi]=KViewShell sovelma faksitiedostoille
+Comment[fr]=Module KViewShell pour les fichiers de fax
+Comment[gl]=Extensión de KViewShell para ficheiros de fax
+Comment[hu]=KViewShell-modul faxfájlokhoz
+Comment[is]=KViewShell íforrit fyrir faxskrár
+Comment[it]=Plugin KViewShell per file di fax
+Comment[ja]=ファクスファイル用の KViewShell プラグイン
+Comment[kk]=Факс файлдарын қарау плагин модулі
+Comment[km]=កម្មវិធី​ជំនួយ KViewShell សម្រាប់​ឯកសារ​ទូរសារ
+Comment[lt]=KViewShell priedas fakso byloms
+Comment[ms]=Plugin KViewShell untuk fail faks
+Comment[nb]=KViewShell programtillegg for faksfiler
+Comment[nds]="KViewShell"-Moduul för Faxdateien
+Comment[ne]=फ्याक्स फाइलका लागि केडीई दृश्य शेल प्लगइन
+Comment[nl]=KViewShell-plugin voor faxbestanden
+Comment[nn]=KViewShell-programtillegg for faksfiler
+Comment[pl]=Wtyczka KViewShell do plików faksów
+Comment[pt]='Plugin' do KViewShell para ficheiros de Fax
+Comment[pt_BR]=Plugin KViewShell para arquivos de fax
+Comment[ru]=Компонент просмотра факсов
+Comment[sk]=KViewShell modul pre faxové súbory
+Comment[sl]=Vstavek za KViewShell za fakse
+Comment[sr]=KViewShell-ов прикључак за факс фајлове
+Comment[sr@Latn]=KViewShell-ov priključak za faks fajlove
+Comment[sv]=Kviewshell-insticksprogram för telefaxfiler
+Comment[th]=ปลั๊กอินสำหรับแสดงแฟ้มโทรสารของ KViewShell
+Comment[tr]=Faks dosyaları için KViewShell eklentisi
+Comment[uk]=Втулок перегляду файлів факсів для KViewShell
+Comment[zh_CN]=传真文件的 KViewShell 插件
+Comment[zh_HK]=傳真檔的 KViewShell 插件
+Comment[zh_TW]=KViewShell 傳真檔外掛程式
+ServiceTypes=KViewShell/MultiPage
+X-KDE-MimeTypes=image/tiff
+X-KDE-Library=kfaxviewpart
+X-KDE-MultiPageVersion=2
diff --git a/kfaxview/kfaxview.desktop b/kfaxview/kfaxview.desktop
new file mode 100644
index 00000000..4dc74ff1
--- /dev/null
+++ b/kfaxview/kfaxview.desktop
@@ -0,0 +1,82 @@
+[Desktop Entry]
+GenericName=Fax Viewer
+GenericName[af]=Faks Aansig
+GenericName[ar]=عارض الفاكس
+GenericName[bg]=Преглед на факсове
+GenericName[br]=Gweler faks
+GenericName[bs]=Preglednik faxova
+GenericName[ca]=Visualitzador de fax
+GenericName[cs]=Prohlížeč faxů
+GenericName[cy]=Gwelydd Ffacs
+GenericName[da]=Fax-fremviser
+GenericName[de]=Faxbetrachter
+GenericName[el]=Προβολέας φαξ
+GenericName[eo]=Faksrigardilo
+GenericName[es]=Visor de faxes
+GenericName[et]=Fakside vaataja
+GenericName[eu]=Fax ikustailua
+GenericName[fa]=مشاهده‌گر دورنگار
+GenericName[fi]=Faksinäytin
+GenericName[fr]=Afficheur de fax
+GenericName[gl]=Visor de fax
+GenericName[he]=מציג פקסים
+GenericName[hi]=फ़ैक्स प्रदर्शक
+GenericName[hr]=Preglednik faksova
+GenericName[hu]=Faxnézegető
+GenericName[is]=Fax sjá
+GenericName[it]=Visore di fax
+GenericName[ja]=ファクスビューア
+GenericName[kk]=Факсты қарау
+GenericName[km]=កម្មវិធី​មើល​ទូរសារ
+GenericName[lt]=Faksų žiūriklis
+GenericName[lv]=Faksu Skatītājs
+GenericName[ms]=Pemapar Faks
+GenericName[nb]=Faksfremviser
+GenericName[nds]=Faxkieker
+GenericName[ne]=फ्याक्स द्रष्टा
+GenericName[nl]=Faxweergaveprogramma
+GenericName[nn]=Faksvisar
+GenericName[pa]=ਫੈਕਸ ਦਰਸ਼ਕ
+GenericName[pl]=Przeglądarka faksów
+GenericName[pt]=Visualizador de Faxes
+GenericName[pt_BR]=Visualizador de Faxes
+GenericName[ro]=Vizualizor FAX
+GenericName[ru]=Просмотр факсов
+GenericName[se]=Fáksačájeheaddji
+GenericName[sk]=Prehliadač faxov
+GenericName[sl]=Pregledovalnik faksov
+GenericName[sr]=Приказивач факсова
+GenericName[sr@Latn]=Prikazivač faksova
+GenericName[sv]=Faxvisare
+GenericName[ta]=ஃபாக்ஸ் காட்சி
+GenericName[tg]=Хондани факс
+GenericName[th]=เครื่องมือแสดงโทรสารของ KDE
+GenericName[tr]=Faks Görüntüleyici
+GenericName[uk]=Переглядач факсів
+GenericName[uz]=Faks koʻruvchi
+GenericName[uz@cyrillic]=Факс кўрувчи
+GenericName[ven]=Muvhoni wa Fekisi
+GenericName[wa]=Håyneu di facs
+GenericName[xh]=Umboniseli Wefax
+GenericName[zh_CN]=传真查看器
+GenericName[zh_HK]=傳真檢視器
+GenericName[zh_TW]=傳真檢視器
+GenericName[zu]=Umbonisi wefax
+Name=KFaxView
+Name[nb]=Kfaxview
+Name[ne]=केडीई फ्याक्स दृश्य
+Name[sv]=Kfaxview
+Name[zh_TW]=KFaxView 傳真檢視
+MimeType=image/fax-g3;
+InitialPreference=6
+Exec=kfaxview %f
+Icon=kfaxview
+Path=
+Type=Application
+Terminal=false
+ServiceTypes=Browser/View
+X-KDE-Library=kviewerpart
+X-KDE-BrowserView-Args=fax
+DocPath=kfaxview/index.html
+X-KDE-StartupNotify=true
+Categories=Qt;KDE;Graphics;
diff --git a/kfaxview/libkfaximage/Makefile.am b/kfaxview/libkfaximage/Makefile.am
new file mode 100644
index 00000000..616afb3c
--- /dev/null
+++ b/kfaxview/libkfaximage/Makefile.am
@@ -0,0 +1,14 @@
+INCLUDES = -I$(top_srcdir) $(all_includes)
+
+lib_LTLIBRARIES = libkfaximage.la
+libkfaximage_la_LDFLAGS = $(all_libraries) -no-undefined -avoid-version
+libkfaximage_la_LIBADD = $(LIB_KDECORE)
+libkfaximage_la_SOURCES = kfaximage.cpp faxexpand.cpp faxinit.cpp
+
+include_HEADERS = kfaximage.h
+noinst_HEADERS = faxexpand.h
+
+METASOURCES = AUTO
+
+messages: rc.cpp
+ $(XGETTEXT) $(libkfaximage_la_SOURCES) -o $(podir)/libkfaximgage.pot
diff --git a/kfaxview/libkfaximage/faxexpand.cpp b/kfaxview/libkfaximage/faxexpand.cpp
new file mode 100644
index 00000000..9c4b4082
--- /dev/null
+++ b/kfaxview/libkfaximage/faxexpand.cpp
@@ -0,0 +1,745 @@
+/* Expand one page of fax data
+ Copyright (C) 1990, 1995 Frank D. Cringle.
+
+This file is part of viewfax - g3/g4 fax processing software.
+
+viewfax is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include <kdebug.h>
+
+#include "faxexpand.h"
+
+//Uncomment this for verbose debug output
+//#define DEBUG_FAX
+#define verbose false
+
+pagenode::pagenode()
+{
+}
+
+/* Note that NeedBits() only works for n <= 16 */
+#define NeedBits(n) do { \
+ if (BitsAvail < (n)) { \
+ BitAcc |= *sp++ << BitsAvail; \
+ BitsAvail += 16; \
+ } \
+} while (0)
+#define GetBits(n) (BitAcc & ((1<<(n))-1))
+#define ClrBits(n) do { \
+ BitAcc >>= (n); \
+ BitsAvail -= (n); \
+} while (0)
+
+#ifdef DEBUG_FAX
+#define DEBUG_SHOW putchar(BitAcc & (1 << t) ? '1' : '0')
+#define LOOKUP(wid,tab) do { \
+ int t; \
+ NeedBits(wid); \
+ TabEnt = tab + GetBits(wid); \
+ printf("%08lX/%d: %s%5d\t", BitAcc, BitsAvail, \
+ StateNames[TabEnt->State], TabEnt->Param); \
+ for (t = 0; t < TabEnt->Width; t++) \
+ DEBUG_SHOW; \
+ putchar('\n'); \
+ fflush(stdout); \
+ ClrBits(TabEnt->Width); \
+} while (0)
+
+#define SETVAL(x) do { \
+ *pa++ = RunLength + (x); \
+ printf("SETVAL: %d\t%d\n", RunLength + (x), a0); \
+ a0 += x; \
+ RunLength = 0; \
+} while (0)
+
+const char *StateNames[] = {
+ "Null ",
+ "Pass ",
+ "Horiz ",
+ "V0 ",
+ "VR ",
+ "VL ",
+ "Ext ",
+ "TermW ",
+ "TermB ",
+ "MakeUpW",
+ "MakeUpB",
+ "MakeUp ",
+ "EOL ",
+};
+
+#else
+#define LOOKUP(wid,tab) do { \
+ NeedBits(wid); \
+ TabEnt = tab + GetBits(wid); \
+ ClrBits(TabEnt->Width); \
+} while (0)
+
+#define SETVAL(x) do { \
+ *pa++ = RunLength + (x); \
+ a0 += x; \
+ RunLength = 0; \
+} while (0)
+#endif
+
+#define dumpruns(runs) do { \
+ printf("-------------------- %d\n", LineNum); \
+ for (pa = runs, a0 = 0; a0 < lastx; a0 += *pa++) \
+ printf("%4d %d\n", a0, *pa); \
+} while (0)
+
+#define EndOfData(pn) (sp >= pn->data + pn->length/sizeof(*pn->data))
+
+/* This macro handles coding errors in G3 data.
+ We redefine it below for the G4 case */
+#define SKIP_EOL do { \
+ while (!EndOfData(pn)) { \
+ NeedBits(11); \
+ if (GetBits(11) == 0) \
+ break; \
+ ClrBits(1); \
+ } \
+ ClrBits(11); \
+ goto EOL; \
+} while (0)
+#define eol2lab EOL2:
+
+/* the line expanders are written as macros so that they can be reused
+ (twice each) but still have direct access to the local variables of
+ the "calling" function */
+#define expand1d() do { \
+ while (a0 < lastx) { \
+ int done = 0; \
+ while (!done) { /* white first */ \
+ LOOKUP(12, WhiteTable); \
+ switch (TabEnt->State) { \
+ case S_EOL: \
+ EOLcnt = 1; \
+ goto EOL; \
+ case S_TermW: \
+ SETVAL(TabEnt->Param); \
+ done = 1; \
+ break; \
+ case S_MakeUpW: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ case S_Ext: \
+ unexpected("Extension code", LineNum); \
+ SKIP_EOL; \
+ break; \
+ default: \
+ unexpected("WhiteTable", LineNum); \
+ SKIP_EOL; \
+ break; \
+ } \
+ } \
+ done = a0 >= lastx; \
+ while (!done) { /* then black */ \
+ LOOKUP(13, BlackTable); \
+ switch (TabEnt->State) { \
+ case S_EOL: \
+ EOLcnt = 1; \
+ goto EOL; \
+ case S_TermB: \
+ SETVAL(TabEnt->Param); \
+ done = 1; \
+ break; \
+ case S_MakeUpB: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ case S_Ext: \
+ unexpected("Extension code", LineNum); \
+ SKIP_EOL; \
+ break; \
+ default: \
+ unexpected("BlackTable", LineNum); \
+ SKIP_EOL; \
+ break; \
+ } \
+ } \
+ } \
+ EOL: ; \
+} while (0)
+
+#define CHECK_b1 do { \
+ if (pa != thisrun) while (b1 <= a0 && b1 < lastx) { \
+ b1 += pb[0] + pb[1]; \
+ pb += 2; \
+ } \
+} while (0)
+
+#define expand2d(eolab) do { \
+ while (a0 < lastx) { \
+ LOOKUP(7, MainTable); \
+ switch (TabEnt->State) { \
+ case S_Pass: \
+ CHECK_b1; \
+ b1 += *pb++; \
+ RunLength += b1 - a0; \
+ a0 = b1; \
+ b1 += *pb++; \
+ break; \
+ case S_Horiz: \
+ if ((pa-run0)&1) { \
+ int done = 0; \
+ while (!done) { /* black first */ \
+ LOOKUP(13, BlackTable); \
+ switch (TabEnt->State) { \
+ case S_TermB: \
+ SETVAL(TabEnt->Param); \
+ done = 1; \
+ break; \
+ case S_MakeUpB: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ default: \
+ unexpected("BlackTable", LineNum); \
+ SKIP_EOL; \
+ break; \
+ } \
+ } \
+ done = 0; \
+ while (!done) { /* then white */ \
+ LOOKUP(12, WhiteTable); \
+ switch (TabEnt->State) { \
+ case S_TermW: \
+ SETVAL(TabEnt->Param); \
+ done = 1; \
+ break; \
+ case S_MakeUpW: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ default: \
+ unexpected("WhiteTable", LineNum); \
+ SKIP_EOL; \
+ break; \
+ } \
+ } \
+ } \
+ else { \
+ int done = 0; \
+ while (!done) { /* white first */ \
+ LOOKUP(12, WhiteTable); \
+ switch (TabEnt->State) { \
+ case S_TermW: \
+ SETVAL(TabEnt->Param); \
+ done = 1; \
+ break; \
+ case S_MakeUpW: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ default: \
+ unexpected("WhiteTable", LineNum); \
+ SKIP_EOL; \
+ break; \
+ } \
+ } \
+ done = 0; \
+ while (!done) { /* then black */ \
+ LOOKUP(13, BlackTable); \
+ switch (TabEnt->State) { \
+ case S_TermB: \
+ SETVAL(TabEnt->Param); \
+ done = 1; \
+ break; \
+ case S_MakeUpB: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ default: \
+ unexpected("BlackTable", LineNum); \
+ SKIP_EOL; \
+ break; \
+ } \
+ } \
+ } \
+ CHECK_b1; \
+ break; \
+ case S_V0: \
+ CHECK_b1; \
+ SETVAL(b1 - a0); \
+ b1 += *pb++; \
+ break; \
+ case S_VR: \
+ CHECK_b1; \
+ SETVAL(b1 - a0 + TabEnt->Param); \
+ b1 += *pb++; \
+ break; \
+ case S_VL: \
+ CHECK_b1; \
+ SETVAL(b1 - a0 - TabEnt->Param); \
+ b1 -= *--pb; \
+ break; \
+ case S_Ext: \
+ *pa++ = lastx - a0; \
+ if (verbose) \
+ kdDebug() << "Line " << LineNum << ": extension code\n";\
+ SKIP_EOL; \
+ break; \
+ case S_EOL: \
+ *pa++ = lastx - a0; \
+ NeedBits(4); \
+ if (GetBits(4) && verbose) /* already seen 7 zeros */ \
+ kdDebug() << "Line " << LineNum << ": Bad EOL\n"; \
+ ClrBits(4); \
+ EOLcnt = 1; \
+ goto eolab; \
+ break; \
+ default: \
+ unexpected("MainTable", LineNum); \
+ SKIP_EOL; \
+ break; \
+ } \
+ } \
+ if (RunLength) { \
+ if (RunLength + a0 < lastx) { \
+ /* expect a final V0 */ \
+ NeedBits(1); \
+ if (!GetBits(1)) { \
+ unexpected("MainTable", LineNum); \
+ SKIP_EOL; \
+ } \
+ ClrBits(1); \
+ } \
+ SETVAL(0); \
+ } \
+ eol2lab ; \
+} while (0)
+
+static void
+unexpected(const char *what, int LineNum)
+{
+ if (verbose)
+ kdError() << "Line " << LineNum << ": Unexpected state in "
+ << what << endl;
+}
+
+/* Expand tiff modified huffman data (g3-1d without EOLs) */
+void
+MHexpand(struct pagenode *pn, drawfunc df)
+{
+ int a0; /* reference element */
+ int lastx; /* copy line width to register */
+ t32bits BitAcc; /* bit accumulator */
+ int BitsAvail; /* # valid bits in BitAcc */
+ int RunLength; /* Length of current run */
+ t16bits *sp; /* pointer into compressed data */
+ pixnum *pa; /* pointer into new line */
+ int EOLcnt; /* number of consecutive EOLs */
+ int LineNum; /* line number */
+ pixnum *runs; /* list of run lengths */
+ struct tabent *TabEnt;
+
+ sp = pn->data;
+ BitAcc = 0;
+ BitsAvail = 0;
+ lastx = pn->size.width();
+ runs = (pixnum *) malloc(lastx * sizeof(pixnum));
+ for (LineNum = 0; LineNum < pn->rowsperstrip; ) {
+#ifdef DEBUG_FAX
+ printf("\nBitAcc=%08lX, BitsAvail = %d\n", BitAcc, BitsAvail);
+ printf("-------------------- %d\n", LineNum);
+ fflush(stdout);
+#endif
+ RunLength = 0;
+ pa = runs;
+ a0 = 0;
+ EOLcnt = 0;
+ if (BitsAvail & 7) /* skip to byte boundary */
+ ClrBits(BitsAvail & 7);
+ expand1d();
+ if (RunLength)
+ SETVAL(0);
+ if (a0 != lastx) {
+ if (verbose)
+ kdWarning() << "Line " << LineNum << ": length is "
+ << a0 << " (expected "<< lastx << ")\n";
+ while (a0 > lastx)
+ a0 -= *--pa;
+ if (a0 < lastx) {
+ if ((pa - runs) & 1)
+ SETVAL(0);
+ SETVAL(lastx - a0);
+ }
+ }
+ (*df)(runs, LineNum++, pn);
+ }
+ free(runs);
+}
+
+/* Expand group-3 1-dimensional data */
+void
+g31expand(struct pagenode *pn, drawfunc df)
+{
+ int a0; /* reference element */
+ int lastx; /* copy line width to register */
+ t32bits BitAcc; /* bit accumulator */
+ int BitsAvail; /* # valid bits in BitAcc */
+ int RunLength; /* Length of current run */
+ t16bits *sp; /* pointer into compressed data */
+ pixnum *pa; /* pointer into new line */
+ int EOLcnt; /* number of consecutive EOLs */
+ int LineNum; /* line number */
+ pixnum *runs; /* list of run lengths */
+ struct tabent *TabEnt;
+
+ sp = pn->data;
+ BitAcc = 0;
+ BitsAvail = 0;
+ lastx = pn->size.width();
+ runs = (pixnum *) malloc(lastx * sizeof(pixnum));
+ EOLcnt = 0;
+ for (LineNum = 0; LineNum < pn->rowsperstrip; ) {
+#ifdef DEBUG_FAX
+ printf("\nBitAcc=%08lX, BitsAvail = %d\n", BitAcc, BitsAvail);
+ printf("-------------------- %d\n", LineNum);
+ fflush(stdout);
+#endif
+ if (EOLcnt == 0)
+ while (!EndOfData(pn)) {
+ /* skip over garbage after a coding error */
+ NeedBits(11);
+ if (GetBits(11) == 0)
+ break;
+ ClrBits(1);
+ }
+ for (EOLcnt = 1; !EndOfData(pn); EOLcnt++) {
+ /* we have seen 11 zeros, which implies EOL,
+ skip possible fill bits too */
+ while (1) {
+ NeedBits(8);
+ if (GetBits(8))
+ break;
+ ClrBits(8);
+ }
+ while (GetBits(1) == 0)
+ ClrBits(1);
+ ClrBits(1); /* the eol flag */
+ NeedBits(11);
+ if (GetBits(11))
+ break;
+ ClrBits(11);
+ }
+ if (EOLcnt > 1 && EOLcnt != 6 && verbose)
+ kdError() << "Line " << LineNum << ": bad RTC (" << EOLcnt << " EOLs)\n";
+ if (EOLcnt >= 6 || EndOfData(pn)) {
+ free(runs);
+ return;
+ }
+ RunLength = 0;
+ pa = runs;
+ a0 = 0;
+ EOLcnt = 0;
+ expand1d();
+ if (RunLength)
+ SETVAL(0);
+ if (a0 != lastx) {
+ if (verbose)
+ kdWarning() << "Line " << LineNum << ": length is "
+ << a0 << " (expected "<< lastx << ")\n";
+ while (a0 > lastx)
+ a0 -= *--pa;
+ if (a0 < lastx) {
+ if ((pa - runs) & 1)
+ SETVAL(0);
+ SETVAL(lastx - a0);
+ }
+ }
+ (*df)(runs, LineNum++, pn);
+ }
+ free(runs);
+}
+
+/* Expand group-3 2-dimensional data */
+void
+g32expand(struct pagenode *pn, drawfunc df)
+{
+ int RunLength; /* Length of current run */
+ int a0; /* reference element */
+ int b1; /* next change on previous line */
+ int lastx = pn->size.width();/* copy line width to register */
+ pixnum *run0, *run1; /* run length arrays */
+ pixnum *thisrun, *pa, *pb; /* pointers into runs */
+ t16bits *sp; /* pointer into compressed data */
+ t32bits BitAcc; /* bit accumulator */
+ int BitsAvail; /* # valid bits in BitAcc */
+ int EOLcnt; /* number of consecutive EOLs */
+ int refline = 0; /* 1D encoded reference line */
+ int LineNum; /* line number */
+ struct tabent *TabEnt;
+
+ sp = pn->data;
+ BitAcc = 0;
+ BitsAvail = 0;
+ /* allocate space for 2 runlength arrays */
+ run0 = (pixnum *) malloc(2 * ((lastx+5)&~1) * sizeof(pixnum));
+ run1 = run0 + ((lastx+5)&~1);
+ run1[0] = lastx;
+ run1[1] = 0;
+ EOLcnt = 0;
+ for (LineNum = 0; LineNum < pn->rowsperstrip; ) {
+#ifdef DEBUG_FAX
+ printf("\nBitAcc=%08lX, BitsAvail = %d\n", BitAcc, BitsAvail);
+ printf("-------------------- %d\n", LineNum);
+ fflush(stdout);
+#endif
+ if (EOLcnt == 0)
+ while (!EndOfData(pn)) {
+ /* skip over garbage after a coding error */
+ NeedBits(11);
+ if (GetBits(11) == 0)
+ break;
+ ClrBits(1);
+ }
+ for (EOLcnt = 1; !EndOfData(pn); EOLcnt++) {
+ /* we have seen 11 zeros, which implies EOL,
+ skip possible fill bits too */
+ while (1) {
+ NeedBits(8);
+ if (GetBits(8))
+ break;
+ ClrBits(8);
+ }
+ while (GetBits(1) == 0)
+ ClrBits(1);
+ ClrBits(1); /* the eol flag */
+ NeedBits(12);
+ refline = GetBits(1); /* 1D / 2D flag */
+ ClrBits(1);
+ if (GetBits(11))
+ break;
+ ClrBits(11);
+ }
+ if (EOLcnt > 1 && EOLcnt != 6 && verbose)
+ kdError() << "Line " << LineNum << ": bad RTC (" << EOLcnt << " EOLs)\n";
+ if (EOLcnt >= 6 || EndOfData(pn)) {
+ free(run0);
+ return;
+ }
+ if (LineNum == 0 && refline == 0 && verbose)
+ kdDebug() << "First line is 2-D encoded\n";
+ RunLength = 0;
+ if (LineNum & 1) {
+ pa = run1;
+ pb = run0;
+ }
+ else {
+ pa = run0;
+ pb = run1;
+ }
+ thisrun = pa;
+ EOLcnt = 0;
+ a0 = 0;
+ b1 = *pb++;
+
+ if (refline) {
+ expand1d();
+ }
+ else {
+ expand2d(EOL2);
+ }
+ if (RunLength)
+ SETVAL(0);
+ if (a0 != lastx) {
+ if (verbose)
+ kdWarning() << "Line " << LineNum << ": length is "
+ << a0 << " (expected "<< lastx << ")\n";
+ while (a0 > lastx)
+ a0 -= *--pa;
+ if (a0 < lastx) {
+ if ((pa - run0) & 1)
+ SETVAL(0);
+ SETVAL(lastx - a0);
+ }
+ }
+ SETVAL(0); /* imaginary change at end of line for reference */
+ (*df)(thisrun, LineNum++, pn);
+ }
+ free(run0);
+}
+
+/* Redefine the "skip to eol" macro. We cannot recover from coding
+ errors in G4 data */
+#undef SKIP_EOL
+#undef eol2lab
+#define SKIP_EOL do { \
+ if (verbose) \
+ kdError() << "Line " << LineNum << ": G4 coding error\n"; \
+ free(run0); \
+ return; \
+} while (0)
+#define eol2lab
+
+/* Expand group-4 data */
+void
+g4expand(struct pagenode *pn, drawfunc df)
+{
+ int RunLength; /* Length of current run */
+ int a0; /* reference element */
+ int b1; /* next change on previous line */
+ int lastx = pn->size.width();/* copy line width to register */
+ pixnum *run0, *run1; /* run length arrays */
+ pixnum *thisrun, *pa, *pb; /* pointers into runs */
+ t16bits *sp; /* pointer into compressed data */
+ t32bits BitAcc; /* bit accumulator */
+ int BitsAvail; /* # valid bits in BitAcc */
+ int LineNum; /* line number */
+ int EOLcnt;
+ struct tabent *TabEnt;
+
+ sp = pn->data;
+ BitAcc = 0;
+ BitsAvail = 0;
+ /* allocate space for 2 runlength arrays */
+ run0 = (pixnum *) malloc(2 * ((lastx+5)&~1) * sizeof(pixnum));
+ run1 = run0 + ((lastx+5)&~1);
+ run1[0] = lastx; /* initial reference line */
+ run1[1] = 0;
+
+ for (LineNum = 0; LineNum < pn->rowsperstrip; ) {
+#ifdef DEBUG_FAX
+ printf("\nBitAcc=%08lX, BitsAvail = %d\n", BitAcc, BitsAvail);
+ printf("-------------------- %d\n", LineNum);
+ fflush(stdout);
+#endif
+ RunLength = 0;
+ if (LineNum & 1) {
+ pa = run1;
+ pb = run0;
+ }
+ else {
+ pa = run0;
+ pb = run1;
+ }
+ thisrun = pa;
+ a0 = 0;
+ b1 = *pb++;
+ expand2d(EOFB);
+ if (a0 < lastx) {
+ if ((pa - run0) & 1)
+ SETVAL(0);
+ SETVAL(lastx - a0);
+ }
+ SETVAL(0); /* imaginary change at end of line for reference */
+ (*df)(thisrun, LineNum++, pn);
+ continue;
+ EOFB:
+ NeedBits(13);
+ if (GetBits(13) != 0x1001 && verbose)
+ kdError() << "Bad RTC\n";
+ break;
+ }
+ free(run0);
+}
+
+static const unsigned char zerotab[256] = {
+ 0x88, 0x07, 0x16, 0x06, 0x25, 0x05, 0x15, 0x05,
+ 0x34, 0x04, 0x14, 0x04, 0x24, 0x04, 0x14, 0x04,
+ 0x43, 0x03, 0x13, 0x03, 0x23, 0x03, 0x13, 0x03,
+ 0x33, 0x03, 0x13, 0x03, 0x23, 0x03, 0x13, 0x03,
+ 0x52, 0x02, 0x12, 0x02, 0x22, 0x02, 0x12, 0x02,
+ 0x32, 0x02, 0x12, 0x02, 0x22, 0x02, 0x12, 0x02,
+ 0x42, 0x02, 0x12, 0x02, 0x22, 0x02, 0x12, 0x02,
+ 0x32, 0x02, 0x12, 0x02, 0x22, 0x02, 0x12, 0x02,
+ 0x61, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01,
+ 0x31, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01,
+ 0x41, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01,
+ 0x31, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01,
+ 0x51, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01,
+ 0x31, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01,
+ 0x41, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01,
+ 0x31, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01,
+ 0x70, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x40, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x50, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x40, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x60, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x40, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x50, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x40, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00
+};
+
+#define check(v) do { \
+ prezeros = zerotab[v]; \
+ postzeros = prezeros & 15; \
+ prezeros >>= 4; \
+ if (prezeros == 8) { \
+ zeros += 8; \
+ continue; \
+ } \
+ if (zeros + prezeros < 11) { \
+ empty = 0; \
+ zeros = postzeros; \
+ continue; \
+ } \
+ zeros = postzeros; \
+ if (empty) \
+ EOLcnt++; \
+ lines++; \
+ empty = 1; \
+} while (0)
+
+/* count fax lines */
+int
+G3count(struct pagenode *pn, int twoD)
+{
+ t16bits *p = pn->data;
+ t16bits *end = p + pn->length/sizeof(*p);
+ int lines = 0; /* lines seen so far */
+ int zeros = 0; /* number of consecutive zero bits seen */
+ int EOLcnt = 0; /* number of consecutive EOLs seen */
+ int empty = 1; /* empty line */
+ int prezeros, postzeros;
+
+ while (p < end && EOLcnt < 6) {
+ t16bits bits = *p++;
+ check(bits&255);
+ if (twoD && (prezeros + postzeros == 7)) {
+ if (postzeros || ((bits & 0x100) == 0))
+ zeros--;
+ }
+ check(bits>>8);
+ if (twoD && (prezeros + postzeros == 7)) {
+ if (postzeros || ((p < end) && ((*p & 1) == 0)))
+ zeros--;
+ }
+ }
+ return lines - EOLcnt; /* don't count trailing EOLs */
+}
diff --git a/kfaxview/libkfaximage/faxexpand.h b/kfaxview/libkfaximage/faxexpand.h
new file mode 100644
index 00000000..8da4e8bc
--- /dev/null
+++ b/kfaxview/libkfaximage/faxexpand.h
@@ -0,0 +1,126 @@
+/* Include file for fax routines
+ Copyright (C) 1990, 1995 Frank D. Cringle.
+ Copyright (C) 2005 Helge Deller <deller@kde.org>
+
+This file is part of viewfax - g3/g4 fax processing software.
+
+viewfax is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _faxexpand_h_
+#define _faxexpand_h_
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <qglobal.h>
+#include <qimage.h>
+
+#define t32bits Q_UINT32
+#define t16bits Q_UINT16
+
+typedef t16bits pixnum;
+
+class pagenode;
+
+/* drawfunc() points to a function which processes a line of the
+ expanded image described as a list of run lengths.
+ run is the base of an array of lengths, starting with a
+ (possibly empty) white run for line number linenum.
+ pn points to the page descriptor */
+typedef void (*drawfunc)(pixnum *run, int linenum, class pagenode *pn);
+
+struct strip { /* tiff strip descriptor */
+ off_t offset; /* offset in file */
+ off_t size; /* size of this strip */
+};
+
+
+/* defines for the pagenode member: type */
+#define FAX_TIFF 1
+#define FAX_RAW 2
+
+class pagenode { /* compressed page descriptor */
+ public:
+ pagenode();
+ ~pagenode() { };
+ int nstrips; /* number of strips */
+ int rowsperstrip; /* number of rows per strip */
+ int stripnum; /* current strip while expanding */
+ struct strip *strips; /* array of strips containing fax data in file */
+ t16bits *data; /* in-memory copy of strip */
+ size_t length; /* length of data */
+ QSize size; /* width & height of page in pixels */
+ int inverse; /* black <=> white */
+ int lsbfirst; /* bit order is lsb first */
+ int type; /* Bernd: tiff vs no tiff*/
+ int orient; /* orientation - upsidedown, landscape, mirrored */
+ int vres; /* vertical resolution: 1 = fine */
+ QPoint dpi; /* DPI horz/vert */
+ void (*expander)(class pagenode *, drawfunc);
+ QImage image;
+ unsigned int bytes_per_line;
+};
+
+extern class pagenode *firstpage, *lastpage, *thispage;
+extern class pagenode defaultpage;
+
+/* page orientation flags */
+#define TURN_NONE 0
+#define TURN_U 1
+#define TURN_L 2
+#define TURN_M 4
+
+/* fsm state codes */
+#define S_Null 0
+#define S_Pass 1
+#define S_Horiz 2
+#define S_V0 3
+#define S_VR 4
+#define S_VL 5
+#define S_Ext 6
+#define S_TermW 7
+#define S_TermB 8
+#define S_MakeUpW 9
+#define S_MakeUpB 10
+#define S_MakeUp 11
+#define S_EOL 12
+
+/* state table entry */
+struct tabent {
+ unsigned char State;
+ unsigned char Width; /* width of code in bits */
+ pixnum Param; /* run length */
+};
+
+extern struct tabent MainTable[]; /* 2-D state table */
+extern struct tabent WhiteTable[]; /* White run lengths */
+extern struct tabent BlackTable[]; /* Black run lengths */
+
+void MHexpand(class pagenode *pn, drawfunc df);
+void g31expand(class pagenode *pn, drawfunc df);
+void g32expand(class pagenode *pn, drawfunc df);
+void g4expand(class pagenode *pn, drawfunc df);
+
+unsigned char *getstrip(class pagenode *pn, int strip);
+class pagenode *notefile(const char *name);
+int notetiff(const char *name);
+
+/* initialise code tables */
+extern void fax_init_tables(void);
+
+/* count lines in image */
+extern int G3count(class pagenode *pn, int twoD);
+
+#endif
diff --git a/kfaxview/libkfaximage/faxinit.cpp b/kfaxview/libkfaximage/faxinit.cpp
new file mode 100644
index 00000000..aa6166aa
--- /dev/null
+++ b/kfaxview/libkfaximage/faxinit.cpp
@@ -0,0 +1,345 @@
+/* Initialise fax decoder tables
+ Copyright (C) 1990, 1995 Frank D. Cringle.
+
+This file is part of viewfax - g3/g4 fax processing software.
+
+viewfax is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include "faxexpand.h"
+
+struct tabent MainTable[128];
+struct tabent WhiteTable[4096];
+struct tabent BlackTable[8192];
+
+struct proto {
+ t16bits code; /* right justified, lsb-first, zero filled */
+ t16bits val; /* (pixel count)<<4 + code width */
+};
+
+static const struct proto Pass[] = {
+{ 0x0008, 4 },
+{ 0, 0 }
+};
+
+static const struct proto Horiz[] = {
+{ 0x0004, 3 },
+{ 0, 0 }
+};
+
+static const struct proto V0[] = {
+{ 0x0001, 1 },
+{ 0, 0 }
+};
+
+static const struct proto VR[] = {
+{ 0x0006, (1<<4)+3 },
+{ 0x0030, (2<<4)+6 },
+{ 0x0060, (3<<4)+7 },
+{ 0, 0 }
+};
+
+static const struct proto VL[] = {
+{ 0x0002, (1<<4)+3 },
+{ 0x0010, (2<<4)+6 },
+{ 0x0020, (3<<4)+7 },
+{ 0, 0 }
+};
+
+static const struct proto ExtV[] = {
+{ 0x0040, 7 },
+{ 0, 0 }
+};
+
+static const struct proto EOLV[] = {
+{ 0x0000, 7 },
+{ 0, 0 }
+};
+
+static const struct proto MakeUpW[] = {
+{ 0x001b, 1029 },
+{ 0x0009, 2053 },
+{ 0x003a, 3078 },
+{ 0x0076, 4103 },
+{ 0x006c, 5128 },
+{ 0x00ec, 6152 },
+{ 0x0026, 7176 },
+{ 0x00a6, 8200 },
+{ 0x0016, 9224 },
+{ 0x00e6, 10248 },
+{ 0x0066, 11273 },
+{ 0x0166, 12297 },
+{ 0x0096, 13321 },
+{ 0x0196, 14345 },
+{ 0x0056, 15369 },
+{ 0x0156, 16393 },
+{ 0x00d6, 17417 },
+{ 0x01d6, 18441 },
+{ 0x0036, 19465 },
+{ 0x0136, 20489 },
+{ 0x00b6, 21513 },
+{ 0x01b6, 22537 },
+{ 0x0032, 23561 },
+{ 0x0132, 24585 },
+{ 0x00b2, 25609 },
+{ 0x0006, 26630 },
+{ 0x01b2, 27657 },
+{ 0, 0 }
+};
+
+static const struct proto MakeUpB[] = {
+{ 0x03c0, 1034 },
+{ 0x0130, 2060 },
+{ 0x0930, 3084 },
+{ 0x0da0, 4108 },
+{ 0x0cc0, 5132 },
+{ 0x02c0, 6156 },
+{ 0x0ac0, 7180 },
+{ 0x06c0, 8205 },
+{ 0x16c0, 9229 },
+{ 0x0a40, 10253 },
+{ 0x1a40, 11277 },
+{ 0x0640, 12301 },
+{ 0x1640, 13325 },
+{ 0x09c0, 14349 },
+{ 0x19c0, 15373 },
+{ 0x05c0, 16397 },
+{ 0x15c0, 17421 },
+{ 0x0dc0, 18445 },
+{ 0x1dc0, 19469 },
+{ 0x0940, 20493 },
+{ 0x1940, 21517 },
+{ 0x0540, 22541 },
+{ 0x1540, 23565 },
+{ 0x0b40, 24589 },
+{ 0x1b40, 25613 },
+{ 0x04c0, 26637 },
+{ 0x14c0, 27661 },
+{ 0, 0 }
+};
+
+static const struct proto MakeUp[] = {
+{ 0x0080, 28683 },
+{ 0x0180, 29707 },
+{ 0x0580, 30731 },
+{ 0x0480, 31756 },
+{ 0x0c80, 32780 },
+{ 0x0280, 33804 },
+{ 0x0a80, 34828 },
+{ 0x0680, 35852 },
+{ 0x0e80, 36876 },
+{ 0x0380, 37900 },
+{ 0x0b80, 38924 },
+{ 0x0780, 39948 },
+{ 0x0f80, 40972 },
+{ 0, 0 }
+};
+
+static const struct proto TermW[] = {
+{ 0x00ac, 8 },
+{ 0x0038, 22 },
+{ 0x000e, 36 },
+{ 0x0001, 52 },
+{ 0x000d, 68 },
+{ 0x0003, 84 },
+{ 0x0007, 100 },
+{ 0x000f, 116 },
+{ 0x0019, 133 },
+{ 0x0005, 149 },
+{ 0x001c, 165 },
+{ 0x0002, 181 },
+{ 0x0004, 198 },
+{ 0x0030, 214 },
+{ 0x000b, 230 },
+{ 0x002b, 246 },
+{ 0x0015, 262 },
+{ 0x0035, 278 },
+{ 0x0072, 295 },
+{ 0x0018, 311 },
+{ 0x0008, 327 },
+{ 0x0074, 343 },
+{ 0x0060, 359 },
+{ 0x0010, 375 },
+{ 0x000a, 391 },
+{ 0x006a, 407 },
+{ 0x0064, 423 },
+{ 0x0012, 439 },
+{ 0x000c, 455 },
+{ 0x0040, 472 },
+{ 0x00c0, 488 },
+{ 0x0058, 504 },
+{ 0x00d8, 520 },
+{ 0x0048, 536 },
+{ 0x00c8, 552 },
+{ 0x0028, 568 },
+{ 0x00a8, 584 },
+{ 0x0068, 600 },
+{ 0x00e8, 616 },
+{ 0x0014, 632 },
+{ 0x0094, 648 },
+{ 0x0054, 664 },
+{ 0x00d4, 680 },
+{ 0x0034, 696 },
+{ 0x00b4, 712 },
+{ 0x0020, 728 },
+{ 0x00a0, 744 },
+{ 0x0050, 760 },
+{ 0x00d0, 776 },
+{ 0x004a, 792 },
+{ 0x00ca, 808 },
+{ 0x002a, 824 },
+{ 0x00aa, 840 },
+{ 0x0024, 856 },
+{ 0x00a4, 872 },
+{ 0x001a, 888 },
+{ 0x009a, 904 },
+{ 0x005a, 920 },
+{ 0x00da, 936 },
+{ 0x0052, 952 },
+{ 0x00d2, 968 },
+{ 0x004c, 984 },
+{ 0x00cc, 1000 },
+{ 0x002c, 1016 },
+{ 0, 0 }
+};
+
+static const struct proto TermB[] = {
+{ 0x03b0, 10 },
+{ 0x0002, 19 },
+{ 0x0003, 34 },
+{ 0x0001, 50 },
+{ 0x0006, 67 },
+{ 0x000c, 84 },
+{ 0x0004, 100 },
+{ 0x0018, 117 },
+{ 0x0028, 134 },
+{ 0x0008, 150 },
+{ 0x0010, 167 },
+{ 0x0050, 183 },
+{ 0x0070, 199 },
+{ 0x0020, 216 },
+{ 0x00e0, 232 },
+{ 0x0030, 249 },
+{ 0x03a0, 266 },
+{ 0x0060, 282 },
+{ 0x0040, 298 },
+{ 0x0730, 315 },
+{ 0x00b0, 331 },
+{ 0x01b0, 347 },
+{ 0x0760, 363 },
+{ 0x00a0, 379 },
+{ 0x0740, 395 },
+{ 0x00c0, 411 },
+{ 0x0530, 428 },
+{ 0x0d30, 444 },
+{ 0x0330, 460 },
+{ 0x0b30, 476 },
+{ 0x0160, 492 },
+{ 0x0960, 508 },
+{ 0x0560, 524 },
+{ 0x0d60, 540 },
+{ 0x04b0, 556 },
+{ 0x0cb0, 572 },
+{ 0x02b0, 588 },
+{ 0x0ab0, 604 },
+{ 0x06b0, 620 },
+{ 0x0eb0, 636 },
+{ 0x0360, 652 },
+{ 0x0b60, 668 },
+{ 0x05b0, 684 },
+{ 0x0db0, 700 },
+{ 0x02a0, 716 },
+{ 0x0aa0, 732 },
+{ 0x06a0, 748 },
+{ 0x0ea0, 764 },
+{ 0x0260, 780 },
+{ 0x0a60, 796 },
+{ 0x04a0, 812 },
+{ 0x0ca0, 828 },
+{ 0x0240, 844 },
+{ 0x0ec0, 860 },
+{ 0x01c0, 876 },
+{ 0x0e40, 892 },
+{ 0x0140, 908 },
+{ 0x01a0, 924 },
+{ 0x09a0, 940 },
+{ 0x0d40, 956 },
+{ 0x0340, 972 },
+{ 0x05a0, 988 },
+{ 0x0660, 1004 },
+{ 0x0e60, 1020 },
+{ 0, 0 }
+};
+
+static const struct proto ExtH[] = {
+{ 0x0100, 9 },
+{ 0, 0 }
+};
+
+static const struct proto EOLH[] = {
+{ 0x0000, 11 },
+{ 0, 0 }
+};
+
+static void
+FillTable(struct tabent *T, int Size, const struct proto *P, int State)
+{
+ int limit = 1 << Size;
+
+ while (P->val) {
+ int width = P->val & 15;
+ int param = P->val >> 4;
+ int incr = 1 << width;
+ int code;
+ for (code = P->code; code < limit; code += incr) {
+ struct tabent *E = T+code;
+ E->State = State;
+ E->Width = width;
+ E->Param = param;
+ }
+ P++;
+ }
+}
+
+/* initialise the huffman code tables */
+void
+fax_init_tables(void)
+{
+ static bool already_initialized = 0;
+ if (already_initialized)
+ return;
+
+ ++already_initialized;
+
+ FillTable(MainTable, 7, Pass, S_Pass);
+ FillTable(MainTable, 7, Horiz, S_Horiz);
+ FillTable(MainTable, 7, V0, S_V0);
+ FillTable(MainTable, 7, VR, S_VR);
+ FillTable(MainTable, 7, VL, S_VL);
+ FillTable(MainTable, 7, ExtV, S_Ext);
+ FillTable(MainTable, 7, EOLV, S_EOL);
+ FillTable(WhiteTable, 12, MakeUpW, S_MakeUpW);
+ FillTable(WhiteTable, 12, MakeUp, S_MakeUp);
+ FillTable(WhiteTable, 12, TermW, S_TermW);
+ FillTable(WhiteTable, 12, ExtH, S_Ext);
+ FillTable(WhiteTable, 12, EOLH, S_EOL);
+ FillTable(BlackTable, 13, MakeUpB, S_MakeUpB);
+ FillTable(BlackTable, 13, MakeUp, S_MakeUp);
+ FillTable(BlackTable, 13, TermB, S_TermB);
+ FillTable(BlackTable, 13, ExtH, S_Ext);
+ FillTable(BlackTable, 13, EOLH, S_EOL);
+}
diff --git a/kfaxview/libkfaximage/kfaximage.cpp b/kfaxview/libkfaximage/kfaximage.cpp
new file mode 100644
index 00000000..28744923
--- /dev/null
+++ b/kfaxview/libkfaximage/kfaximage.cpp
@@ -0,0 +1,667 @@
+/*
+ This file is part of KDE FAX image library
+ Copyright (c) 2005 Helge Deller <deller@kde.org>
+
+ based on Frank D. Cringle's viewfax package
+ Copyright (C) 1990, 1995 Frank D. Cringle.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <qimage.h>
+#include <qfile.h>
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "faxexpand.h"
+#include "kfaximage.h"
+
+static const char FAXMAGIC[] = "\000PC Research, Inc\000\000\000\000\000\000";
+static const char littleTIFF[] = "\x49\x49\x2a\x00";
+static const char bigTIFF[] = "\x4d\x4d\x00\x2a";
+
+KFaxImage::KFaxImage( const QString &filename, QObject *parent, const char *name )
+ : QObject(parent,name)
+{
+ KGlobal::locale()->insertCatalogue( QString::fromLatin1("libkfaximage") );
+ loadImage(filename);
+}
+
+KFaxImage::~KFaxImage()
+{ }
+
+bool KFaxImage::loadImage( const QString &filename )
+{
+ reset();
+
+ m_filename = filename;
+ m_errorString = QString::null;
+
+ if (m_filename.isEmpty())
+ return false;
+
+ int ok = notetiff();
+ if (!ok) {
+ reset();
+ }
+ return ok == 1;
+}
+
+void KFaxImage::reset()
+{
+ fax_init_tables();
+ m_pagenodes.setAutoDelete(true);
+ m_pagenodes.clear();
+ // do not reset m_errorString and m_filename, since
+ // they may be needed by calling application
+}
+
+QImage KFaxImage::page( unsigned int pageNr )
+{
+ if (pageNr >= numPages()) {
+ kdDebug() << "KFaxImage::page() called with invalid page number\n";
+ return QImage();
+ }
+ pagenode *pn = m_pagenodes.at(pageNr);
+ GetImage(pn);
+ return pn->image;
+}
+
+QPoint KFaxImage::page_dpi( unsigned int pageNr )
+{
+ if (pageNr >= numPages()) {
+ kdDebug() << "KFaxImage::page_dpi() called with invalid page number\n";
+ return QPoint(0,0);
+ }
+ pagenode *pn = m_pagenodes.at(pageNr);
+ GetImage(pn);
+ return pn->dpi;
+}
+
+QSize KFaxImage::page_size( unsigned int pageNr )
+{
+ if (pageNr >= numPages()) {
+ kdDebug() << "KFaxImage::page_size() called with invalid page number\n";
+ return QSize(0,0);
+ }
+ pagenode *pn = m_pagenodes.at(pageNr);
+ GetImage(pn);
+ return pn->size;
+}
+
+
+pagenode *KFaxImage::AppendImageNode(int type)
+{
+ pagenode *pn = new pagenode();
+ if (pn) {
+ pn->type = type;
+ pn->expander = g31expand;
+ pn->strips = NULL;
+ pn->size = QSize(1728,2339);
+ pn->vres = -1;
+ pn->dpi = KFAX_DPI_FINE;
+ m_pagenodes.append(pn);
+ }
+ return pn;
+}
+
+bool KFaxImage::NewImage(pagenode *pn, int w, int h)
+{
+ pn->image = QImage( w, h, 1, 2, QImage::systemByteOrder() );
+ pn->image.setColor(0, qRgb(255,255,255));
+ pn->image.setColor(1, qRgb(0,0,0));
+ pn->data = (Q_UINT16*) pn->image.bits();
+ pn->bytes_per_line = pn->image.bytesPerLine();
+ pn->dpi = KFAX_DPI_FINE;
+
+ return !pn->image.isNull();
+}
+
+void KFaxImage::FreeImage(pagenode *pn)
+{
+ pn->image = QImage();
+ pn->data = NULL;
+ pn->bytes_per_line = 0;
+}
+
+void KFaxImage::kfaxerror(const QString& error)
+{
+ m_errorString = error;
+ kdError() << "kfaxerror: " << error << endl;
+}
+
+
+/* Enter an argument in the linked list of pages */
+pagenode *
+KFaxImage::notefile(int type)
+{
+ pagenode *newnode = new pagenode();
+ newnode->type = type;
+ newnode->size = QSize(1728,0);
+ return newnode;
+}
+
+static t32bits
+get4(unsigned char *p, QImage::Endian endian)
+{
+ return (endian == QImage::BigEndian)
+ ? (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3] :
+ p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24);
+}
+
+static int
+get2(unsigned char *p, QImage::Endian endian)
+{
+ return (endian == QImage::BigEndian) ? (p[0]<<8)|p[1] : p[0]|(p[1]<<8);
+}
+
+/* generate pagenodes for the images in a tiff file */
+int
+KFaxImage::notetiff()
+{
+#define SC(x) (char *)(x)
+ unsigned char header[8];
+ QImage::Endian endian;
+ t32bits IFDoff;
+ pagenode *pn = NULL;
+ QString str;
+
+ QFile file(filename());
+ if (!file.open(IO_ReadOnly)) {
+ kfaxerror(i18n("Unable to open file for reading."));
+ return 0;
+ }
+
+ if (file.readBlock(SC(header), 8) != 8) {
+ kfaxerror(i18n("Unable to read file header (file too short)."));
+ return 0;
+ }
+ if (memcmp(header, &littleTIFF, 4) == 0)
+ endian = QImage::LittleEndian;
+ else if (memcmp(header, &bigTIFF, 4) == 0)
+ endian = QImage::BigEndian;
+ else {
+ maybe_RAW_FAX:
+ kfaxerror(i18n("This is not a TIFF FAX file."));
+ // AppendImageNode(FAX_RAW);
+ return 0;
+ }
+ IFDoff = get4(header+4, endian);
+ if (IFDoff & 1) {
+ goto maybe_RAW_FAX;
+ }
+ do { /* for each page */
+ unsigned char buf[8];
+ unsigned char *dir = NULL , *dp = NULL;
+ int ndirent;
+ pixnum iwidth = 1728;
+ pixnum iheight = 2339;
+ int inverse = false;
+ int lsbfirst = 0;
+ int t4opt = 0, comp = 0;
+ int orient = TURN_NONE;
+ int yres = 196; /* 98.0 */
+ struct strip *strips = NULL;
+ unsigned int rowsperstrip = 0;
+ t32bits nstrips = 1;
+
+ if (!file.at(IFDoff)) {
+ realbad:
+ kfaxerror( i18n("Invalid or incomplete TIFF file.") );
+ bad:
+ if (strips)
+ free(strips);
+ if (dir)
+ free(dir);
+ file.close();
+ return 1;
+ }
+ if (file.readBlock(SC(buf), 2) != 2)
+ goto realbad;
+ ndirent = get2(buf, endian);
+ int len = 12*ndirent+4;
+ dir = (unsigned char *) malloc(len);
+ if (file.readBlock(SC(dir), len) != len)
+ goto realbad;
+ for (dp = dir; ndirent; ndirent--, dp += 12) {
+ /* for each directory entry */
+ int tag, ftype;
+ t32bits count, value = 0;
+ tag = get2(dp, endian);
+ ftype = get2(dp+2, endian);
+ count = get4(dp+4, endian);
+ switch(ftype) { /* value is offset to list if count*size > 4 */
+ case 3: /* short */
+ value = get2(dp+8, endian);
+ break;
+ case 4: /* long */
+ value = get4(dp+8, endian);
+ break;
+ case 5: /* offset to rational */
+ value = get4(dp+8, endian);
+ break;
+ }
+ switch(tag) {
+ case 256: /* ImageWidth */
+ iwidth = value;
+ break;
+ case 257: /* ImageLength */
+ iheight = value;
+ break;
+ case 259: /* Compression */
+ comp = value;
+ break;
+ case 262: /* PhotometricInterpretation */
+ inverse ^= (value == 1);
+ break;
+ case 266: /* FillOrder */
+ lsbfirst = (value == 2);
+ break;
+ case 273: /* StripOffsets */
+ nstrips = count;
+ strips = (struct strip *) malloc(count * sizeof *strips);
+ if (count == 1 || (count == 2 && ftype == 3)) {
+ strips[0].offset = value;
+ if (count == 2)
+ strips[1].offset = get2(dp+10, endian);
+ break;
+ }
+ if (!file.at(value))
+ goto realbad;
+ for (count = 0; count < nstrips; count++) {
+ if (file.readBlock(SC(buf), (ftype == 3) ? 2 : 4) <= 0)
+ goto realbad;
+ strips[count].offset = (ftype == 3) ?
+ get2(buf, endian) : get4(buf, endian);
+ }
+ break;
+ case 274: /* Orientation */
+ switch(value) {
+ default: /* row0 at top, col0 at left */
+ orient = 0;
+ break;
+ case 2: /* row0 at top, col0 at right */
+ orient = TURN_M;
+ break;
+ case 3: /* row0 at bottom, col0 at right */
+ orient = TURN_U;
+ break;
+ case 4: /* row0 at bottom, col0 at left */
+ orient = TURN_U|TURN_M;
+ break;
+ case 5: /* row0 at left, col0 at top */
+ orient = TURN_M|TURN_L;
+ break;
+ case 6: /* row0 at right, col0 at top */
+ orient = TURN_U|TURN_L;
+ break;
+ case 7: /* row0 at right, col0 at bottom */
+ orient = TURN_U|TURN_M|TURN_L;
+ break;
+ case 8: /* row0 at left, col0 at bottom */
+ orient = TURN_L;
+ break;
+ }
+ break;
+ case 278: /* RowsPerStrip */
+ rowsperstrip = value;
+ break;
+ case 279: /* StripByteCounts */
+ if (count != nstrips) {
+ str = i18n("In file %1\nStripsPerImage tag 273=%2,tag279=%3\n")
+ .arg(filename()).arg(nstrips).arg(count);
+ kfaxerror(str);
+ goto realbad;
+ }
+ if (count == 1 || (count == 2 && ftype == 3)) {
+ strips[0].size = value;
+ if (count == 2)
+ strips[1].size = get2(dp+10, endian);
+ break;
+ }
+ if (!file.at(value))
+ goto realbad;
+ for (count = 0; count < nstrips; count++) {
+ if (file.readBlock(SC(buf), (ftype == 3) ? 2 : 4) <= 0)
+ goto realbad;
+ strips[count].size = (ftype == 3) ?
+ get2(buf, endian) : get4(buf, endian);
+ }
+ break;
+ case 283: /* YResolution */
+ if (!file.at(value) ||
+ file.readBlock(SC(buf), 8) != 8)
+ goto realbad;
+ yres = get4(buf, endian) / get4(buf+4, endian);
+ break;
+ case 292: /* T4Options */
+ t4opt = value;
+ break;
+ case 293: /* T6Options */
+ /* later */
+ break;
+ case 296: /* ResolutionUnit */
+ if (value == 3)
+ yres = (yres * 254) / 100; /* *2.54 */
+ break;
+ }
+ }
+ IFDoff = get4(dp, endian);
+ free(dir);
+ dir = NULL;
+ if (comp == 5) {
+ // compression type 5 is LZW compression // XXX
+ kfaxerror(i18n("Due to patent reasons LZW (Lempel-Ziv & Welch) "
+ "compressed Fax files cannot be loaded yet.\n"));
+ goto bad;
+ }
+ if (comp < 2 || comp > 4) {
+ kfaxerror(i18n("This version can only handle Fax files\n"));
+ goto bad;
+ }
+ pn = AppendImageNode(FAX_TIFF);
+ pn->nstrips = nstrips;
+ pn->rowsperstrip = nstrips > 1 ? rowsperstrip : iheight;
+ pn->strips = strips;
+ pn->size = QSize(iwidth,iheight);
+ pn->inverse = inverse;
+ pn->lsbfirst = lsbfirst;
+ pn->orient = orient;
+ pn->dpi.setY(yres);
+ pn->vres = (yres > 150) ? 1:0; /* arbitrary threshold for fine resolution */
+ if (comp == 2)
+ pn->expander = MHexpand;
+ else if (comp == 3)
+ pn->expander = (t4opt & 1) ? g32expand : g31expand;
+ else
+ pn->expander = g4expand;
+ } while (IFDoff);
+ file.close();
+ return 1;
+#undef UC
+}
+
+/* report error and remove bad file from the list */
+void
+KFaxImage::badfile(pagenode *pn)
+{
+ kfaxerror(i18n("%1: Bad Fax File").arg(filename()));
+ FreeImage(pn);
+}
+
+/* rearrange input bits into t16bits lsb-first chunks */
+static void
+normalize(pagenode *pn, int revbits, int swapbytes, size_t length)
+{
+ t32bits *p = (t32bits *) pn->data;
+
+ kdDebug() << "normalize = " << ((revbits<<1)|swapbytes) << endl;
+ switch ((revbits<<1)|swapbytes) {
+ case 0:
+ break;
+ case 1:
+ for ( ; length; length -= 4) {
+ t32bits t = *p;
+ *p++ = ((t & 0xff00ff00) >> 8) | ((t & 0x00ff00ff) << 8);
+ }
+ break;
+ case 2:
+ for ( ; length; length -= 4) {
+ t32bits t = *p;
+ t = ((t & 0xf0f0f0f0) >> 4) | ((t & 0x0f0f0f0f) << 4);
+ t = ((t & 0xcccccccc) >> 2) | ((t & 0x33333333) << 2);
+ *p++ = ((t & 0xaaaaaaaa) >> 1) | ((t & 0x55555555) << 1);
+ }
+ break;
+ case 3:
+ for ( ; length; length -= 4) {
+ t32bits t = *p;
+ t = ((t & 0xff00ff00) >> 8) | ((t & 0x00ff00ff) << 8);
+ t = ((t & 0xf0f0f0f0) >> 4) | ((t & 0x0f0f0f0f) << 4);
+ t = ((t & 0xcccccccc) >> 2) | ((t & 0x33333333) << 2);
+ *p++ = ((t & 0xaaaaaaaa) >> 1) | ((t & 0x55555555) << 1);
+ }
+ }
+}
+
+
+/* get compressed data into memory */
+unsigned char *
+KFaxImage::getstrip(pagenode *pn, int strip)
+{
+ size_t offset, roundup;
+ unsigned char *Data;
+
+ union { t16bits s; unsigned char b[2]; } so;
+#define ShortOrder so.b[1]
+ so.s = 1; /* XXX */
+
+ QFile file(filename());
+ if (!file.open(IO_ReadOnly)) {
+ badfile(pn);
+ return NULL;
+ }
+
+ if (pn->strips == NULL) {
+ offset = 0;
+ pn->length = file.size();
+ }
+ else if (strip < pn->nstrips) {
+ offset = pn->strips[strip].offset;
+ pn->length = pn->strips[strip].size;
+ }
+ else {
+ kfaxerror( i18n("Trying to expand too many strips.") );
+ return NULL;
+ }
+
+ /* round size to full boundary plus t32bits */
+ roundup = (pn->length + 7) & ~3;
+
+ Data = (unsigned char *) malloc(roundup);
+ /* clear the last 2 t32bits, to force the expander to terminate
+ even if the file ends in the middle of a fax line */
+ *((t32bits *) Data + roundup/4 - 2) = 0;
+ *((t32bits *) Data + roundup/4 - 1) = 0;
+
+ /* we expect to get it in one gulp... */
+ if (!file.at(offset) ||
+ (size_t) file.readBlock((char *)Data, pn->length) != pn->length) {
+ badfile(pn);
+ free(Data);
+ return NULL;
+ }
+ file.close();
+
+ pn->data = (t16bits *) Data;
+ if (pn->strips == NULL && memcmp(Data, FAXMAGIC, sizeof(FAXMAGIC)-1) == 0) {
+ /* handle ghostscript / PC Research fax file */
+ if (Data[24] != 1 || Data[25] != 0){
+ kfaxerror( i18n("Only the first page of the PC Research multipage file will be shown.") );
+ }
+ pn->length -= 64;
+ pn->vres = Data[29];
+ pn->data += 32;
+ roundup -= 64;
+ }
+
+ normalize(pn, !pn->lsbfirst, ShortOrder, roundup);
+ if (pn->size.height() == 0)
+ pn->size.setHeight( G3count(pn, pn->expander == g32expand) );
+ if (pn->size.height() == 0) {
+
+ kfaxerror( i18n("No fax found in file.") );
+ badfile(pn);
+ free(Data);
+ return NULL;
+ }
+ if (pn->strips == NULL)
+ pn->rowsperstrip = pn->size.height();
+ return Data;
+}
+
+
+static void
+drawline(pixnum *run, int LineNum, pagenode *pn)
+{
+ t32bits *p, *p1; /* p - current line, p1 - low-res duplicate */
+ pixnum *r; /* pointer to run-lengths */
+ t32bits pix; /* current pixel value */
+ t32bits acc; /* pixel accumulator */
+ int nacc; /* number of valid bits in acc */
+ int tot; /* total pixels in line */
+ int n;
+
+ LineNum += pn->stripnum * pn->rowsperstrip;
+ if (LineNum >= pn->size.height()) {
+ if (LineNum == pn->size.height())
+ kdError() << "Height exceeded\n";
+ return;
+ }
+
+ p = (t32bits *) pn->image.scanLine(LineNum*(2-pn->vres));
+ p1 =(t32bits *)( pn->vres ? 0 : pn->image.scanLine(1+LineNum*(2-pn->vres)));
+ r = run;
+ acc = 0;
+ nacc = 0;
+ pix = pn->inverse ? ~0 : 0;
+ tot = 0;
+ while (tot < pn->size.width()) {
+ n = *r++;
+ tot += n;
+ /* Watch out for buffer overruns, e.g. when n == 65535. */
+ if (tot > pn->size.width())
+ break;
+ if (pix)
+ acc |= (~(t32bits)0 >> nacc);
+ else if (nacc)
+ acc &= (~(t32bits)0 << (32 - nacc));
+ else
+ acc = 0;
+ if (nacc + n < 32) {
+ nacc += n;
+ pix = ~pix;
+ continue;
+ }
+ *p++ = acc;
+ if (p1)
+ *p1++ = acc;
+ n -= 32 - nacc;
+ while (n >= 32) {
+ n -= 32;
+ *p++ = pix;
+ if (p1)
+ *p1++ = pix;
+ }
+ acc = pix;
+ nacc = n;
+ pix = ~pix;
+ }
+ if (nacc) {
+ *p++ = acc;
+ if (p1)
+ *p1++ = acc;
+ }
+}
+
+int
+KFaxImage::GetPartImage(pagenode *pn, int n)
+{
+ unsigned char *Data = getstrip(pn, n);
+ if (Data == 0)
+ return 3;
+ pn->stripnum = n;
+ (*pn->expander)(pn, drawline);
+ free(Data);
+ return 1;
+}
+
+int
+KFaxImage::GetImage(pagenode *pn)
+{
+ if (!pn->image.isNull())
+ return 1;
+
+ int i;
+ if (pn->strips == 0) {
+
+ kdDebug() << "Loading RAW fax file " << m_filename << " size=" << pn->size << endl;
+
+ /* raw file; maybe we don't have the height yet */
+ unsigned char *Data = getstrip(pn, 0);
+ if (Data == 0){
+ return 0;
+ }
+ if (!NewImage(pn, pn->size.width(), (pn->vres ? 1:2) * pn->size.height()))
+ return 0;
+
+ (*pn->expander)(pn, drawline);
+ }
+ else {
+ /* multi-strip tiff */
+ kdDebug() << "Loading MULTI STRIP TIFF fax file " << m_filename << endl;
+
+ if (!NewImage(pn, pn->size.width(), (pn->vres ? 1:2) * pn->size.height()))
+ return 0;
+ pn->stripnum = 0;
+ kdDebug() << "has " << pn->nstrips << " strips.\n";
+ for (i = 0; i < pn->nstrips; i++){
+
+ int k = GetPartImage(pn, i);
+ if ( k == 3 ){
+ FreeImage(pn);
+ kfaxerror( i18n("Fax G3 format not yet supported.") );
+ return k;
+ }
+
+ }
+ }
+
+ // byte-swapping the image on little endian machines
+#if defined(Q_BYTE_ORDER) && (Q_BYTE_ORDER == Q_LITTLE_ENDIAN)
+ for (int y=pn->image.height()-1; y>=0; --y) {
+ Q_UINT32 *source = (Q_UINT32 *) pn->image.scanLine(y);
+ Q_UINT32 *dest = source;
+ for (int x=(pn->bytes_per_line/4)-1; x>=0; --x) {
+ Q_UINT32 dv = 0, sv = *source;
+ for (int bit=32; bit>0; --bit) {
+ dv <<= 1;
+ dv |= sv&1;
+ sv >>= 1;
+ }
+ *dest = dv;
+ ++dest;
+ ++source;
+ }
+ }
+#endif
+
+ kdDebug() << filename()
+ << "\n\tsize = " << pn->size
+ << "\n\tDPI = " << pn->dpi
+ << "\n\tresolution = " << (pn->vres ? "fine" : "normal")
+ << endl;
+
+ return 1;
+}
+
+
+#include "kfaximage.moc"
diff --git a/kfaxview/libkfaximage/kfaximage.h b/kfaxview/libkfaximage/kfaximage.h
new file mode 100644
index 00000000..0ed2db90
--- /dev/null
+++ b/kfaxview/libkfaximage/kfaximage.h
@@ -0,0 +1,162 @@
+/*
+ This file is part of KDE FAX image loading library
+ Copyright (c) 2005 Helge Deller <deller@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _LIBKFAXIMAGE_H_
+#define _LIBKFAXIMAGE_H_
+
+#include <qobject.h>
+#include <qstring.h>
+#include <qimage.h>
+#include <qptrlist.h>
+#include <kdelibs_export.h>
+
+class pagenode;
+
+
+/**
+ * This is KFaxImage, a class for loading FAX files under KDE
+ *
+ * @short KFaxImage
+ * @author Helge Deller
+ * @version 0.1
+ *
+ *
+ * Standard fax dpi values:
+ * ------------------------
+ * Standard: 203 dpi x 98 lpi
+ * Fine: 203 dpi x 196 lpi
+ * Super Fine: 203 dpi y 392 lpi, or
+ * 406 dpi x 392 lpi
+ */
+
+#define KFAX_DPI_STANDARD QPoint(203,98)
+#define KFAX_DPI_FINE QPoint(203,196)
+#define KFAX_DPI_SUPERFINE QPoint(406,392)
+
+
+class KDE_EXPORT KFaxImage : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ /**
+ * KFaxImage - the KDE FAX loader class
+ * constructor.
+ * @param filename: an optional FAX file which should be loaded.
+ * @see: numPages
+ */
+
+ KFaxImage( const QString &filename = QString::null, QObject *parent = 0, const char *name = 0 );
+
+ /**
+ * Destructor
+ *
+ * releases internal allocated memory.
+ */
+
+ virtual ~KFaxImage();
+
+ /**
+ * loads the FAX image and returns true when sucessful.
+ * @param filename: the file which should be loaded.
+ * @return boolean value on success or failure
+ * @see: numPages
+ * @see: errorString
+ */
+
+ bool loadImage( const QString &filename );
+
+ /**
+ * returns currently loaded image file name.
+ * @return FAX filename
+ */
+
+ QString filename() { return m_filename; };
+
+ /**
+ * returns number of pages which are stored in the FAX file
+ * @return page count
+ */
+
+ unsigned int numPages() const { return m_pagenodes.count(); };
+
+ /**
+ * returns a QImage which holds the contents of page pageNr
+ * @param pageNr: page number (starting with 0)
+ * @return QImage of the page pageNr
+ */
+
+ QImage page( unsigned int pageNr );
+
+ /**
+ * returns the DPI (dots per inch) of page pageNr
+ * @param pageNr: page number (starting with 0)
+ * @return a QPoint value with the DPIs in X- and Y-direction
+ */
+
+ QPoint page_dpi( unsigned int pageNr );
+
+ /**
+ * returns the physical pixels of page pageNr
+ * @param pageNr: page number (starting with 0)
+ * @return a QSize value with the width and height of the image
+ */
+
+ QSize page_size( unsigned int pageNr );
+
+ /**
+ * @return a user-visible, translated error string
+ */
+
+ const QString errorString() const { return m_errorString; };
+
+
+
+ private:
+
+ /**
+ * private member variables
+ */
+
+ QString m_filename;
+ QString m_errorString;
+
+ typedef QPtrList<pagenode> t_PageNodeList;
+ t_PageNodeList m_pagenodes;
+
+ /**
+ * private member functions
+ */
+
+ void reset();
+ void kfaxerror(const QString& error);
+ pagenode *AppendImageNode(int type);
+ bool NewImage(pagenode *pn, int w, int h);
+ void FreeImage(pagenode *pn);
+ unsigned char *getstrip(pagenode *pn, int strip);
+ int GetPartImage(pagenode *pn, int n);
+ int GetImage(pagenode *pn);
+ pagenode *notefile(int type);
+ int notetiff();
+ void badfile(pagenode *pn);
+};
+
+#endif /* _LIBKFAXIMAGE_H_ */
+
diff --git a/kfaxview/main.cpp b/kfaxview/main.cpp
new file mode 100644
index 00000000..8e967a96
--- /dev/null
+++ b/kfaxview/main.cpp
@@ -0,0 +1,174 @@
+#include <config.h>
+
+#include <dcopclient.h>
+#include <dcopref.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kdebug.h>
+#include <kurl.h>
+#include <klocale.h>
+#include <kaboutdata.h>
+#include <qdir.h>
+
+#include <stdlib.h>
+
+#include "kviewshell.h"
+
+
+static KCmdLineOptions options[] =
+{
+ { "unique", I18N_NOOP("Check if the file is loaded in another KFaxView instance.\nIf it is, bring up the other KFaxView. Otherwise, load the file."), 0 },
+ { "g", 0, 0 },
+ { "goto <pagenumber>", I18N_NOOP("Navigate to this page"), 0 },
+ // The rest of the options are only for compability with the old KFax
+ { "f", 0, 0 },
+ { "fine", I18N_NOOP("(obsolete)"), 0 },
+ { "n", 0, 0 },
+ { "normal", I18N_NOOP("(obsolete)"), 0 },
+ { "height", I18N_NOOP("(obsolete)"), 0 },
+ { "w", 0, 0 },
+ { "width", I18N_NOOP("(obsolete)"), 0 },
+ { "l", 0, 0 },
+ { "landscape", I18N_NOOP("(obsolete)"), 0 },
+ { "u", 0, 0 },
+ { "upsidedown", I18N_NOOP("(obsolete)"), 0 },
+ { "i", 0, 0 },
+ { "invert", I18N_NOOP("(obsolete)"), 0 },
+ { "m", 0, 0 },
+ { "mem <bytes>", I18N_NOOP("(obsolete)"), 0 },
+ { "r", 0, 0 },
+ { "reverse", I18N_NOOP("(obsolete)"), 0 },
+ { "2" , I18N_NOOP("(obsolete)"), 0 },
+ { "4", I18N_NOOP("(obsolete)"), 0 },
+ { "+file(s)", I18N_NOOP("Files to load"), 0 },
+ KCmdLineLastOption
+};
+
+
+static const char description[] = I18N_NOOP("A previewer for Fax files.");
+
+
+int main(int argc, char** argv)
+{
+ KAboutData about ("kfaxview", I18N_NOOP("KFaxView"), "3.5",
+ description, KAboutData::License_GPL,
+ "Stephan Kebekus, Helge Deller",
+ I18N_NOOP("Fax-G3 plugin for the KViewShell document viewer framework."));
+
+ about.addAuthor ("Stefan Kebekus",
+ I18N_NOOP("KViewShell plugin"),
+ "kebekus@kde.org",
+ "http://www.mi.uni-koeln.de/~kebekus");
+
+ about.addAuthor ("Wilfried Huss",
+ I18N_NOOP("KViewShell maintainer"),
+ "Wilfried.Huss@gmx.at");
+
+ about.addAuthor ("Helge Deller",
+ I18N_NOOP("Fax file loading"),
+ "deller@gmx.de");
+
+ KCmdLineArgs::init(argc, argv, &about);
+ KCmdLineArgs::addCmdLineOptions(options);
+ KApplication app;
+
+ // see if we are starting with session management
+ if (app.isRestored())
+ {
+ RESTORE(KViewShell);
+ }
+ else
+ {
+ KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
+
+ if (args->isSet("unique"))
+ {
+ // With --unique, we need 2 arguments.
+ if (args->count() < 1)
+ {
+ args->usage();
+ exit(-1);
+ }
+
+ // Find the fully qualified file name of the file we are
+ // loading. Complain, if we are given a URL which does not point
+ // to a local file.
+ KURL url(args->url(0));
+
+ if (!url.isValid())
+ {
+ kdError(4300) << QString(I18N_NOOP("The URL %1 is not well-formed.")).arg(args->arg(0)) << endl;
+ return -1;
+ }
+
+ if (!url.isLocalFile())
+ {
+ kdError(4300) << QString(I18N_NOOP("The URL %1 does not point to a local file. You can only specify local "
+ "files if you are using the '--unique' option.")).arg(args->arg(0)) << endl;
+ return -1;
+ }
+
+ QString qualPath = QFileInfo(url.path()).absFilePath();
+
+ app.dcopClient()->attach();
+ // We need to register as "kviewshell" to stay compatible with existing DCOP-skripts.
+ QCString id = app.dcopClient()->registerAs("unique-kviewshell");
+ if (id.isNull())
+ kdError(4300) << "There was an error using dcopClient()->registerAs()." << endl;
+ QCStringList apps = app.dcopClient()->registeredApplications();
+ for ( QCStringList::Iterator it = apps.begin(); it != apps.end(); ++it )
+ {
+ if ((*it).find("kviewshell") == 0)
+ {
+ QByteArray data, replyData;
+ QCString replyType;
+ QDataStream arg(data, IO_WriteOnly);
+ bool result;
+ arg << qualPath.stripWhiteSpace();
+ if (!app.dcopClient()->call( *it, "kmultipage", "is_file_loaded(QString)", data, replyType, replyData))
+ kdError(4300) << "There was an error using DCOP." << endl;
+ else
+ {
+ QDataStream reply(replyData, IO_ReadOnly);
+ if (replyType == "bool")
+ {
+ reply >> result;
+ if (result == true)
+ {
+ if (app.dcopClient()->send( *it, "kmultipage", "jumpToReference(QString)", url.ref()) == true)
+ {
+ app.dcopClient()->detach();
+ return 0;
+ }
+ }
+ }
+ else
+ kdError(4300) << "The DCOP function 'doIt' returned an unexpected type of reply!";
+ }
+ }
+ }
+ }
+
+ // We need to register as "kviewshell" to stay compatible with existing DCOP-skripts.
+ app.dcopClient()->registerAs("kviewshell");
+ KViewShell* shell = new KViewShell("image/fax-g3");
+ shell->show();
+ app.processEvents();
+
+ if (args->count() > 0)
+ {
+ KURL url = args->url(0);
+ if (!url.hasRef() && args->isSet("goto"))
+ {
+ // If the url doesn't already has a reference part, add the
+ // argument of --goto to the url as reference, to make the
+ // KViewShell jump to this page.
+ QString reference = args->getOption("goto");
+ url.setHTMLRef(reference);
+ }
+ shell->openURL(url);
+ }
+ }
+
+ return app.exec();
+}