summaryrefslogtreecommitdiff
path: root/plugins/AdvaImg/src/FreeImage/PluginG3.cpp
diff options
context:
space:
mode:
authorKirill Volinsky <mataes2007@gmail.com>2012-12-22 16:38:58 +0000
committerKirill Volinsky <mataes2007@gmail.com>2012-12-22 16:38:58 +0000
commit87d155ba9f4e699293adc65954c89f20fc65b36d (patch)
treed79d69145cc6ef4e97d2ad2912b4d645c7b27158 /plugins/AdvaImg/src/FreeImage/PluginG3.cpp
parenta8bd33017b1959588d60c9a8a5ae3a744cb75e4d (diff)
AdvaImg plugin folder renaming
git-svn-id: http://svn.miranda-ng.org/main/trunk@2801 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/AdvaImg/src/FreeImage/PluginG3.cpp')
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginG3.cpp433
1 files changed, 433 insertions, 0 deletions
diff --git a/plugins/AdvaImg/src/FreeImage/PluginG3.cpp b/plugins/AdvaImg/src/FreeImage/PluginG3.cpp
new file mode 100644
index 0000000000..c383a455b7
--- /dev/null
+++ b/plugins/AdvaImg/src/FreeImage/PluginG3.cpp
@@ -0,0 +1,433 @@
+// ==========================================================
+// G3 Fax Loader
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+// - Petr Pytelka (pyta@lightcomp.com)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "../LibTIFF4/tiffiop.h"
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Constant/Macro declarations
+// ==========================================================
+
+#define G3_DEFAULT_WIDTH 1728
+
+#define TIFFhowmany8(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3)
+
+// ==========================================================
+// libtiff interface
+// ==========================================================
+
+static tmsize_t
+_g3ReadProc(thandle_t handle, void *buf, tmsize_t size) {
+ // returns an error when reading the TIFF header
+ return 0;
+}
+
+static tmsize_t
+_g3WriteProc(thandle_t handle, void *buf, tmsize_t size) {
+ // returns ok when writing the TIFF header
+ return size;
+}
+
+static toff_t
+_g3SeekProc(thandle_t handle, toff_t off, int whence) {
+ return 0;
+}
+
+static int
+_g3CloseProc(thandle_t handle) {
+ return 0;
+}
+
+static toff_t
+_g3SizeProc(thandle_t handle) {
+ return 0;
+}
+
+static int
+_g3MapProc(thandle_t, void** base, toff_t* size) {
+ return 0;
+}
+
+static void
+_g3UnmapProc(thandle_t, void* base, toff_t size) {
+}
+
+// --------------------------------------------------------------
+
+static tmsize_t
+G3GetFileSize(FreeImageIO *io, fi_handle handle) {
+ long currentPos = io->tell_proc(handle);
+ io->seek_proc(handle, 0, SEEK_END);
+ long fileSize = io->tell_proc(handle);
+ io->seek_proc(handle, currentPos, SEEK_SET);
+ return fileSize;
+}
+
+static BOOL
+G3ReadFile(FreeImageIO *io, fi_handle handle, uint8 *tif_rawdata, tmsize_t tif_rawdatasize) {
+ return ((tmsize_t)(io->read_proc(tif_rawdata, tif_rawdatasize, 1, handle) * tif_rawdatasize) == tif_rawdatasize);
+}
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+static int
+copyFaxFile(FreeImageIO *io, fi_handle handle, TIFF* tifin, uint32 xsize, int stretch, FIMEMORY *memory) {
+ BYTE *rowbuf = NULL;
+ BYTE *refbuf = NULL;
+ uint32 row;
+ uint16 badrun;
+ uint16 badfaxrun;
+ uint32 badfaxlines;
+ int ok;
+
+ try {
+
+ uint32 linesize = TIFFhowmany8(xsize);
+ rowbuf = (BYTE*) _TIFFmalloc(linesize);
+ refbuf = (BYTE*) _TIFFmalloc(linesize);
+ if (rowbuf == NULL || refbuf == NULL) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ tifin->tif_rawdatasize = G3GetFileSize(io, handle);
+ tifin->tif_rawdata = (tidata_t) _TIFFmalloc(tifin->tif_rawdatasize);
+ if (tifin->tif_rawdata == NULL) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ if (!G3ReadFile(io, handle, tifin->tif_rawdata, tifin->tif_rawdatasize)) {
+ throw "Read error at scanline 0";
+ }
+ tifin->tif_rawcp = tifin->tif_rawdata;
+ tifin->tif_rawcc = tifin->tif_rawdatasize;
+
+ (*tifin->tif_setupdecode)(tifin);
+ (*tifin->tif_predecode)(tifin, (uint16) 0);
+ tifin->tif_row = 0;
+ badfaxlines = 0;
+ badfaxrun = 0;
+
+ _TIFFmemset(refbuf, 0, linesize);
+ row = 0;
+ badrun = 0; // current run of bad lines
+ while (tifin->tif_rawcc > 0) {
+ ok = (*tifin->tif_decoderow)(tifin, rowbuf, linesize, 0);
+ if (!ok) {
+ badfaxlines++;
+ badrun++;
+ // regenerate line from previous good line
+ _TIFFmemcpy(rowbuf, refbuf, linesize);
+ } else {
+ if (badrun > badfaxrun)
+ badfaxrun = badrun;
+ badrun = 0;
+ _TIFFmemcpy(refbuf, rowbuf, linesize);
+ }
+ tifin->tif_row++;
+
+ FreeImage_WriteMemory(rowbuf, linesize, 1, memory);
+ row++;
+ if (stretch) {
+ FreeImage_WriteMemory(rowbuf, linesize, 1, memory);
+ row++;
+ }
+ }
+ if (badrun > badfaxrun)
+ badfaxrun = badrun;
+
+ _TIFFfree(tifin->tif_rawdata);
+ tifin->tif_rawdata = NULL;
+
+ _TIFFfree(rowbuf);
+ _TIFFfree(refbuf);
+
+ /*
+ if (verbose) {
+ fprintf(stderr, "%d rows in input\n", rows);
+ fprintf(stderr, "%ld total bad rows\n", (long) badfaxlines);
+ fprintf(stderr, "%d max consecutive bad rows\n", badfaxrun);
+ }
+ */
+
+ } catch(const char *message) {
+ if(rowbuf) _TIFFfree(rowbuf);
+ if(refbuf) _TIFFfree(refbuf);
+ if(tifin->tif_rawdata) {
+ _TIFFfree(tifin->tif_rawdata);
+ tifin->tif_rawdata = NULL;
+ }
+ FreeImage_OutputMessageProc(s_format_id, message);
+
+ return -1;
+ }
+
+ return (row);
+}
+
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "G3";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Raw fax format CCITT G.3";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "g3";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL; // there is now reasonable regexp for raw G3
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/fax-g3";
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ TIFF *faxTIFF = NULL;
+ FIBITMAP *dib = NULL;
+ FIMEMORY *memory = NULL;
+
+ //int verbose = 0;
+ int stretch = 0;
+ int rows;
+ float resX = 204.0;
+ float resY = 196.0;
+
+ uint32 xsize = G3_DEFAULT_WIDTH;
+ int compression_in = COMPRESSION_CCITTFAX3;
+ int fillorder_in = FILLORDER_LSB2MSB;
+ uint32 group3options_in = 0; // 1d-encoded
+ uint32 group4options_in = 0; // compressed
+ int photometric_in = PHOTOMETRIC_MINISWHITE;
+
+ if(handle==NULL) return NULL;
+
+ try {
+ // set default load options
+
+ compression_in = COMPRESSION_CCITTFAX3; // input is g3-encoded
+ group3options_in &= ~GROUP3OPT_2DENCODING; // input is 1d-encoded (g3 only)
+ fillorder_in = FILLORDER_MSB2LSB; // input has msb-to-lsb fillorder
+
+ /*
+ Original input-related fax2tiff options
+
+ while ((c = getopt(argc, argv, "R:X:o:1234ABLMPUW5678abcflmprsuvwz?")) != -1) {
+ switch (c) {
+ // input-related options
+ case '3': // input is g3-encoded
+ compression_in = COMPRESSION_CCITTFAX3;
+ break;
+ case '4': // input is g4-encoded
+ compression_in = COMPRESSION_CCITTFAX4;
+ break;
+ case 'U': // input is uncompressed (g3 and g4)
+ group3options_in |= GROUP3OPT_UNCOMPRESSED;
+ group4options_in |= GROUP4OPT_UNCOMPRESSED;
+ break;
+ case '1': // input is 1d-encoded (g3 only)
+ group3options_in &= ~GROUP3OPT_2DENCODING;
+ break;
+ case '2': // input is 2d-encoded (g3 only)
+ group3options_in |= GROUP3OPT_2DENCODING;
+ break;
+ case 'P': // input has not-aligned EOL (g3 only)
+ group3options_in &= ~GROUP3OPT_FILLBITS;
+ break;
+ case 'A': // input has aligned EOL (g3 only)
+ group3options_in |= GROUP3OPT_FILLBITS;
+ break;
+ case 'W': // input has 0 mean white
+ photometric_in = PHOTOMETRIC_MINISWHITE;
+ break;
+ case 'B': // input has 0 mean black
+ photometric_in = PHOTOMETRIC_MINISBLACK;
+ break;
+ case 'L': // input has lsb-to-msb fillorder
+ fillorder_in = FILLORDER_LSB2MSB;
+ break;
+ case 'M': // input has msb-to-lsb fillorder
+ fillorder_in = FILLORDER_MSB2LSB;
+ break;
+ case 'R': // input resolution
+ resY = (float) atof(optarg);
+ break;
+ case 'X': // input width
+ xsize = (uint32) atoi(optarg);
+ break;
+
+ // output-related options
+ case 's': // stretch image by dup'ng scanlines
+ stretch = 1;
+ break;
+ case 'v': // -v for info
+ verbose++;
+ break;
+ }
+ }
+
+ */
+
+ // open a temporary memory buffer to save decoded scanlines
+ memory = FreeImage_OpenMemory();
+ if (!memory) throw FI_MSG_ERROR_MEMORY;
+
+ // wrap the raw fax file
+ faxTIFF = TIFFClientOpen("(FakeInput)", "w",
+ // TIFFClientOpen() fails if we don't set existing value here
+ NULL,
+ _g3ReadProc, _g3WriteProc,
+ _g3SeekProc, _g3CloseProc,
+ _g3SizeProc, _g3MapProc,
+ _g3UnmapProc);
+
+ if (faxTIFF == NULL) {
+ throw "Can not create fake input file";
+ }
+ TIFFSetMode(faxTIFF, O_RDONLY);
+ TIFFSetField(faxTIFF, TIFFTAG_IMAGEWIDTH, xsize);
+ TIFFSetField(faxTIFF, TIFFTAG_SAMPLESPERPIXEL, 1);
+ TIFFSetField(faxTIFF, TIFFTAG_BITSPERSAMPLE, 1);
+ TIFFSetField(faxTIFF, TIFFTAG_FILLORDER, fillorder_in);
+ TIFFSetField(faxTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
+ TIFFSetField(faxTIFF, TIFFTAG_PHOTOMETRIC, photometric_in);
+ TIFFSetField(faxTIFF, TIFFTAG_YRESOLUTION, resY);
+ TIFFSetField(faxTIFF, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
+
+ // NB: this must be done after directory info is setup
+ TIFFSetField(faxTIFF, TIFFTAG_COMPRESSION, compression_in);
+ if (compression_in == COMPRESSION_CCITTFAX3)
+ TIFFSetField(faxTIFF, TIFFTAG_GROUP3OPTIONS, group3options_in);
+ else if (compression_in == COMPRESSION_CCITTFAX4)
+ TIFFSetField(faxTIFF, TIFFTAG_GROUP4OPTIONS, group4options_in);
+
+ resX = 204;
+ if (!stretch) {
+ TIFFGetField(faxTIFF, TIFFTAG_YRESOLUTION, &resY);
+ } else {
+ resY = 196;
+ }
+
+ // decode the raw fax data
+ rows = copyFaxFile(io, handle, faxTIFF, xsize, stretch, memory);
+ if(rows <= 0) throw "Error when decoding raw fax file : check the decoder options";
+
+
+ // allocate the output dib
+ dib = FreeImage_Allocate(xsize, rows, 1);
+ unsigned pitch = FreeImage_GetPitch(dib);
+ uint32 linesize = TIFFhowmany8(xsize);
+
+ // fill the bitmap structure ...
+ // ... palette
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+ if(photometric_in == PHOTOMETRIC_MINISWHITE) {
+ pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255;
+ pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 0;
+ } else {
+ pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
+ pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
+ }
+ // ... resolution
+ FreeImage_SetDotsPerMeterX(dib, (unsigned)(resX/0.0254000 + 0.5));
+ FreeImage_SetDotsPerMeterY(dib, (unsigned)(resY/0.0254000 + 0.5));
+
+ // read the decoded scanline and fill the bitmap data
+ FreeImage_SeekMemory(memory, 0, SEEK_SET);
+ BYTE *bits = FreeImage_GetScanLine(dib, rows - 1);
+ for(int k = 0; k < rows; k++) {
+ FreeImage_ReadMemory(bits, linesize, 1, memory);
+ bits -= pitch;
+ }
+
+ // free the TIFF wrapper
+ TIFFClose(faxTIFF);
+
+ // free the memory buffer
+ FreeImage_CloseMemory(memory);
+
+ } catch(const char *message) {
+ if(memory) FreeImage_CloseMemory(memory);
+ if(faxTIFF) TIFFClose(faxTIFF);
+ if(dib) FreeImage_Unload(dib);
+ FreeImage_OutputMessageProc(s_format_id, message);
+ return NULL;
+ }
+
+ return dib;
+
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitG3(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = NULL;
+ plugin->validate_proc = NULL;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = NULL;
+ plugin->supports_icc_profiles_proc = NULL;
+}