diff options
Diffstat (limited to 'filter/source/graphicfilter/itiff')
-rw-r--r-- | filter/source/graphicfilter/itiff/ccidecom.cxx | 1112 | ||||
-rw-r--r-- | filter/source/graphicfilter/itiff/ccidecom.hxx | 125 | ||||
-rw-r--r-- | filter/source/graphicfilter/itiff/exports.map | 7 | ||||
-rw-r--r-- | filter/source/graphicfilter/itiff/itiff.cxx | 1342 | ||||
-rw-r--r-- | filter/source/graphicfilter/itiff/lzwdecom.cxx | 192 | ||||
-rw-r--r-- | filter/source/graphicfilter/itiff/lzwdecom.hxx | 79 | ||||
-rw-r--r-- | filter/source/graphicfilter/itiff/makefile.mk | 71 |
7 files changed, 2928 insertions, 0 deletions
diff --git a/filter/source/graphicfilter/itiff/ccidecom.cxx b/filter/source/graphicfilter/itiff/ccidecom.cxx new file mode 100644 index 000000000000..5e9e75cbf815 --- /dev/null +++ b/filter/source/graphicfilter/itiff/ccidecom.cxx @@ -0,0 +1,1112 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_filter.hxx" + +#include "ccidecom.hxx" + +//=============================== Huffman-Tabellen ======================== + +//---------------------------- White-Run ------------------------------ + +#define CCIWhiteTableSize 105 + +const CCIHuffmanTableEntry CCIWhiteTable[CCIWhiteTableSize]={ + { 0, 0x0035, 8 }, + { 1, 0x0007, 6 }, + { 2, 0x0007, 4 }, + { 3, 0x0008, 4 }, + { 4, 0x000b, 4 }, + { 5, 0x000c, 4 }, + { 6, 0x000e, 4 }, + { 7, 0x000f, 4 }, + { 8, 0x0013, 5 }, + { 9, 0x0014, 5 }, + { 10, 0x0007, 5 }, + { 11, 0x0008, 5 }, + { 12, 0x0008, 6 }, + { 13, 0x0003, 6 }, + { 14, 0x0034, 6 }, + { 15, 0x0035, 6 }, + { 16, 0x002a, 6 }, + { 17, 0x002b, 6 }, + { 18, 0x0027, 7 }, + { 19, 0x000c, 7 }, + { 20, 0x0008, 7 }, + { 21, 0x0017, 7 }, + { 22, 0x0003, 7 }, + { 23, 0x0004, 7 }, + { 24, 0x0028, 7 }, + { 25, 0x002b, 7 }, + { 26, 0x0013, 7 }, + { 27, 0x0024, 7 }, + { 28, 0x0018, 7 }, + { 29, 0x0002, 8 }, + { 30, 0x0003, 8 }, + { 31, 0x001a, 8 }, + { 32, 0x001b, 8 }, + { 33, 0x0012, 8 }, + { 34, 0x0013, 8 }, + { 35, 0x0014, 8 }, + { 36, 0x0015, 8 }, + { 37, 0x0016, 8 }, + { 38, 0x0017, 8 }, + { 39, 0x0028, 8 }, + { 40, 0x0029, 8 }, + { 41, 0x002a, 8 }, + { 42, 0x002b, 8 }, + { 43, 0x002c, 8 }, + { 44, 0x002d, 8 }, + { 45, 0x0004, 8 }, + { 46, 0x0005, 8 }, + { 47, 0x000a, 8 }, + { 48, 0x000b, 8 }, + { 49, 0x0052, 8 }, + { 50, 0x0053, 8 }, + { 51, 0x0054, 8 }, + { 52, 0x0055, 8 }, + { 53, 0x0024, 8 }, + { 54, 0x0025, 8 }, + { 55, 0x0058, 8 }, + { 56, 0x0059, 8 }, + { 57, 0x005a, 8 }, + { 58, 0x005b, 8 }, + { 59, 0x004a, 8 }, + { 60, 0x004b, 8 }, + { 61, 0x0032, 8 }, + { 62, 0x0033, 8 }, + { 63, 0x0034, 8 }, + { 64, 0x001b, 5 }, + { 128, 0x0012, 5 }, + { 192, 0x0017, 6 }, + { 256, 0x0037, 7 }, + { 320, 0x0036, 8 }, + { 384, 0x0037, 8 }, + { 448, 0x0064, 8 }, + { 512, 0x0065, 8 }, + { 576, 0x0068, 8 }, + { 640, 0x0067, 8 }, + { 704, 0x00cc, 9 }, + { 768, 0x00cd, 9 }, + { 832, 0x00d2, 9 }, + { 896, 0x00d3, 9 }, + { 960, 0x00d4, 9 }, + { 1024, 0x00d5, 9 }, + { 1088, 0x00d6, 9 }, + { 1152, 0x00d7, 9 }, + { 1216, 0x00d8, 9 }, + { 1280, 0x00d9, 9 }, + { 1344, 0x00da, 9 }, + { 1408, 0x00db, 9 }, + { 1472, 0x0098, 9 }, + { 1536, 0x0099, 9 }, + { 1600, 0x009a, 9 }, + { 1664, 0x0018, 6 }, + { 1728, 0x009b, 9 }, + { 1792, 0x0008, 11 }, + { 1856, 0x000c, 11 }, + { 1920, 0x000d, 11 }, + { 1984, 0x0012, 12 }, + { 2048, 0x0013, 12 }, + { 2112, 0x0014, 12 }, + { 2176, 0x0015, 12 }, + { 2240, 0x0016, 12 }, + { 2304, 0x0017, 12 }, + { 2368, 0x001c, 12 }, + { 2432, 0x001d, 12 }, + { 2496, 0x001e, 12 }, + { 2560, 0x001f, 12 }, + { 9999, 0x0001, 12 } // EOL +}; + +//---------------------------- Black-Run ------------------------------ + +#define CCIBlackTableSize 105 + +const CCIHuffmanTableEntry CCIBlackTable[CCIBlackTableSize]={ + { 0, 0x0037, 10 }, + { 1, 0x0002, 3 }, + { 2, 0x0003, 2 }, + { 3, 0x0002, 2 }, + { 4, 0x0003, 3 }, + { 5, 0x0003, 4 }, + { 6, 0x0002, 4 }, + { 7, 0x0003, 5 }, + { 8, 0x0005, 6 }, + { 9, 0x0004, 6 }, + { 10, 0x0004, 7 }, + { 11, 0x0005, 7 }, + { 12, 0x0007, 7 }, + { 13, 0x0004, 8 }, + { 14, 0x0007, 8 }, + { 15, 0x0018, 9 }, + { 16, 0x0017, 10 }, + { 17, 0x0018, 10 }, + { 18, 0x0008, 10 }, + { 19, 0x0067, 11 }, + { 20, 0x0068, 11 }, + { 21, 0x006c, 11 }, + { 22, 0x0037, 11 }, + { 23, 0x0028, 11 }, + { 24, 0x0017, 11 }, + { 25, 0x0018, 11 }, + { 26, 0x00ca, 12 }, + { 27, 0x00cb, 12 }, + { 28, 0x00cc, 12 }, + { 29, 0x00cd, 12 }, + { 30, 0x0068, 12 }, + { 31, 0x0069, 12 }, + { 32, 0x006a, 12 }, + { 33, 0x006b, 12 }, + { 34, 0x00d2, 12 }, + { 35, 0x00d3, 12 }, + { 36, 0x00d4, 12 }, + { 37, 0x00d5, 12 }, + { 38, 0x00d6, 12 }, + { 39, 0x00d7, 12 }, + { 40, 0x006c, 12 }, + { 41, 0x006d, 12 }, + { 42, 0x00da, 12 }, + { 43, 0x00db, 12 }, + { 44, 0x0054, 12 }, + { 45, 0x0055, 12 }, + { 46, 0x0056, 12 }, + { 47, 0x0057, 12 }, + { 48, 0x0064, 12 }, + { 49, 0x0065, 12 }, + { 50, 0x0052, 12 }, + { 51, 0x0053, 12 }, + { 52, 0x0024, 12 }, + { 53, 0x0037, 12 }, + { 54, 0x0038, 12 }, + { 55, 0x0027, 12 }, + { 56, 0x0028, 12 }, + { 57, 0x0058, 12 }, + { 58, 0x0059, 12 }, + { 59, 0x002b, 12 }, + { 60, 0x002c, 12 }, + { 61, 0x005a, 12 }, + { 62, 0x0066, 12 }, + { 63, 0x0067, 12 }, + { 64, 0x000f, 10 }, + { 128, 0x00c8, 12 }, + { 192, 0x00c9, 12 }, + { 256, 0x005b, 12 }, + { 320, 0x0033, 12 }, + { 384, 0x0034, 12 }, + { 448, 0x0035, 12 }, + { 512, 0x006c, 13 }, + { 576, 0x006d, 13 }, + { 640, 0x004a, 13 }, + { 704, 0x004b, 13 }, + { 768, 0x004c, 13 }, + { 832, 0x004d, 13 }, + { 896, 0x0072, 13 }, + { 960, 0x0073, 13 }, + { 1024, 0x0074, 13 }, + { 1088, 0x0075, 13 }, + { 1152, 0x0076, 13 }, + { 1216, 0x0077, 13 }, + { 1280, 0x0052, 13 }, + { 1344, 0x0053, 13 }, + { 1408, 0x0054, 13 }, + { 1472, 0x0055, 13 }, + { 1536, 0x005a, 13 }, + { 1600, 0x005b, 13 }, + { 1664, 0x0064, 13 }, + { 1728, 0x0065, 13 }, + { 1792, 0x0008, 11 }, + { 1856, 0x000c, 11 }, + { 1920, 0x000d, 11 }, + { 1984, 0x0012, 12 }, + { 2048, 0x0013, 12 }, + { 2112, 0x0014, 12 }, + { 2176, 0x0015, 12 }, + { 2240, 0x0016, 12 }, + { 2304, 0x0017, 12 }, + { 2368, 0x001c, 12 }, + { 2432, 0x001d, 12 }, + { 2496, 0x001e, 12 }, + { 2560, 0x001f, 12 }, + { 9999, 0x0001, 12 } // EOL +}; + + +//---------------------------- 2D-Mode -------------------------------- + +#define CCI2DMODE_UNCOMP 0 +#define CCI2DMODE_PASS 1 +#define CCI2DMODE_HORZ 2 +#define CCI2DMODE_VERT_L3 3 +#define CCI2DMODE_VERT_L2 4 +#define CCI2DMODE_VERT_L1 5 +#define CCI2DMODE_VERT_0 6 +#define CCI2DMODE_VERT_R1 7 +#define CCI2DMODE_VERT_R2 8 +#define CCI2DMODE_VERT_R3 9 + +#define CCI2DModeTableSize 10 + +const CCIHuffmanTableEntry CCI2DModeTable[CCI2DModeTableSize]={ + { CCI2DMODE_UNCOMP , 0x000f, 10 }, + { CCI2DMODE_PASS , 0x0001, 4 }, + { CCI2DMODE_HORZ , 0x0001, 3 }, + { CCI2DMODE_VERT_L3, 0x0002, 7 }, + { CCI2DMODE_VERT_L2, 0x0002, 6 }, + { CCI2DMODE_VERT_L1, 0x0002, 3 }, + { CCI2DMODE_VERT_0 , 0x0001, 1 }, + { CCI2DMODE_VERT_R1, 0x0003, 3 }, + { CCI2DMODE_VERT_R2, 0x0003, 6 }, + { CCI2DMODE_VERT_R3, 0x0003, 7 } +}; + + +//-------------------------- 2D-Uncompressed-Mode ---------------------- + +#define CCIUNCOMP_0White_1Black 0 +#define CCIUNCOMP_1White_1Black 1 +#define CCIUNCOMP_2White_1Black 2 +#define CCIUNCOMP_3White_1Black 3 +#define CCIUNCOMP_4White_1Black 4 +#define CCIUNCOMP_5White 5 +#define CCIUNCOMP_0White_End 6 +#define CCIUNCOMP_1White_End 7 +#define CCIUNCOMP_2White_End 8 +#define CCIUNCOMP_3White_End 9 +#define CCIUNCOMP_4White_End 10 + +#define CCIUncompTableSize 11 + +const CCIHuffmanTableEntry CCIUncompTable[CCIUncompTableSize]={ + { CCIUNCOMP_0White_1Black, 0x0001, 1 }, + { CCIUNCOMP_1White_1Black, 0x0001, 2 }, + { CCIUNCOMP_2White_1Black, 0x0001, 3 }, + { CCIUNCOMP_3White_1Black, 0x0001, 4 }, + { CCIUNCOMP_4White_1Black, 0x0001, 5 }, + { CCIUNCOMP_5White , 0x0001, 6 }, + { CCIUNCOMP_0White_End , 0x0001, 7 }, + { CCIUNCOMP_1White_End , 0x0001, 8 }, + { CCIUNCOMP_2White_End , 0x0001, 9 }, + { CCIUNCOMP_3White_End , 0x0001, 10 }, + { CCIUNCOMP_4White_End , 0x0001, 11 } +}; + + +//================== Sicherheitskopie der Huffman-Tabellen ================ +// Um sicher zugehen, dass die Huffman-Tabellen keine Fehler enthalten, +// wurden sie zweimal von unterschiedlichen Quellen eingegeben (Uff) und +// verglichen. +// Da sich aber im Laufe der Pflege des Source-Codes mal ein Fehler +// einschleichen koennte (z.B. versehentlicher druck einer Taste im Editor) +// werden die Tablellen hier weiterhin zweimal aufgefuehrt und zur Laufzeit +// verglichen. (Wenn der Vergleich fehlschlaegt, liefert CCIDecompressor +// immer einen Fehler). Das Ganze mag etwas wahnsinnig erscheinen, aber ein Fehler +// in den Tabellen waere sonst sehr sehr schwer zu erkennen, zumal es +// unwahrscheinlich ist, dass eine oder mehere Beispieldateien alle Codes +// durchlaufen. + +const CCIHuffmanTableEntry CCIWhiteTableSave[CCIWhiteTableSize]={ + { 0, 0x0035, 8 }, + { 1, 0x0007, 6 }, + { 2, 0x0007, 4 }, + { 3, 0x0008, 4 }, + { 4, 0x000b, 4 }, + { 5, 0x000c, 4 }, + { 6, 0x000e, 4 }, + { 7, 0x000f, 4 }, + { 8, 0x0013, 5 }, + { 9, 0x0014, 5 }, + { 10, 0x0007, 5 }, + { 11, 0x0008, 5 }, + { 12, 0x0008, 6 }, + { 13, 0x0003, 6 }, + { 14, 0x0034, 6 }, + { 15, 0x0035, 6 }, + { 16, 0x002a, 6 }, + { 17, 0x002b, 6 }, + { 18, 0x0027, 7 }, + { 19, 0x000c, 7 }, + { 20, 0x0008, 7 }, + { 21, 0x0017, 7 }, + { 22, 0x0003, 7 }, + { 23, 0x0004, 7 }, + { 24, 0x0028, 7 }, + { 25, 0x002b, 7 }, + { 26, 0x0013, 7 }, + { 27, 0x0024, 7 }, + { 28, 0x0018, 7 }, + { 29, 0x0002, 8 }, + { 30, 0x0003, 8 }, + { 31, 0x001a, 8 }, + { 32, 0x001b, 8 }, + { 33, 0x0012, 8 }, + { 34, 0x0013, 8 }, + { 35, 0x0014, 8 }, + { 36, 0x0015, 8 }, + { 37, 0x0016, 8 }, + { 38, 0x0017, 8 }, + { 39, 0x0028, 8 }, + { 40, 0x0029, 8 }, + { 41, 0x002a, 8 }, + { 42, 0x002b, 8 }, + { 43, 0x002c, 8 }, + { 44, 0x002d, 8 }, + { 45, 0x0004, 8 }, + { 46, 0x0005, 8 }, + { 47, 0x000a, 8 }, + { 48, 0x000b, 8 }, + { 49, 0x0052, 8 }, + { 50, 0x0053, 8 }, + { 51, 0x0054, 8 }, + { 52, 0x0055, 8 }, + { 53, 0x0024, 8 }, + { 54, 0x0025, 8 }, + { 55, 0x0058, 8 }, + { 56, 0x0059, 8 }, + { 57, 0x005a, 8 }, + { 58, 0x005b, 8 }, + { 59, 0x004a, 8 }, + { 60, 0x004b, 8 }, + { 61, 0x0032, 8 }, + { 62, 0x0033, 8 }, + { 63, 0x0034, 8 }, + { 64, 0x001b, 5 }, + { 128, 0x0012, 5 }, + { 192, 0x0017, 6 }, + { 256, 0x0037, 7 }, + { 320, 0x0036, 8 }, + { 384, 0x0037, 8 }, + { 448, 0x0064, 8 }, + { 512, 0x0065, 8 }, + { 576, 0x0068, 8 }, + { 640, 0x0067, 8 }, + { 704, 0x00cc, 9 }, + { 768, 0x00cd, 9 }, + { 832, 0x00d2, 9 }, + { 896, 0x00d3, 9 }, + { 960, 0x00d4, 9 }, + { 1024, 0x00d5, 9 }, + { 1088, 0x00d6, 9 }, + { 1152, 0x00d7, 9 }, + { 1216, 0x00d8, 9 }, + { 1280, 0x00d9, 9 }, + { 1344, 0x00da, 9 }, + { 1408, 0x00db, 9 }, + { 1472, 0x0098, 9 }, + { 1536, 0x0099, 9 }, + { 1600, 0x009a, 9 }, + { 1664, 0x0018, 6 }, + { 1728, 0x009b, 9 }, + { 1792, 0x0008, 11 }, + { 1856, 0x000c, 11 }, + { 1920, 0x000d, 11 }, + { 1984, 0x0012, 12 }, + { 2048, 0x0013, 12 }, + { 2112, 0x0014, 12 }, + { 2176, 0x0015, 12 }, + { 2240, 0x0016, 12 }, + { 2304, 0x0017, 12 }, + { 2368, 0x001c, 12 }, + { 2432, 0x001d, 12 }, + { 2496, 0x001e, 12 }, + { 2560, 0x001f, 12 }, + { 9999, 0x0001, 12 } // EOL +}; + +const CCIHuffmanTableEntry CCIBlackTableSave[CCIBlackTableSize]={ + { 0, 0x0037, 10 }, + { 1, 0x0002, 3 }, + { 2, 0x0003, 2 }, + { 3, 0x0002, 2 }, + { 4, 0x0003, 3 }, + { 5, 0x0003, 4 }, + { 6, 0x0002, 4 }, + { 7, 0x0003, 5 }, + { 8, 0x0005, 6 }, + { 9, 0x0004, 6 }, + { 10, 0x0004, 7 }, + { 11, 0x0005, 7 }, + { 12, 0x0007, 7 }, + { 13, 0x0004, 8 }, + { 14, 0x0007, 8 }, + { 15, 0x0018, 9 }, + { 16, 0x0017, 10 }, + { 17, 0x0018, 10 }, + { 18, 0x0008, 10 }, + { 19, 0x0067, 11 }, + { 20, 0x0068, 11 }, + { 21, 0x006c, 11 }, + { 22, 0x0037, 11 }, + { 23, 0x0028, 11 }, + { 24, 0x0017, 11 }, + { 25, 0x0018, 11 }, + { 26, 0x00ca, 12 }, + { 27, 0x00cb, 12 }, + { 28, 0x00cc, 12 }, + { 29, 0x00cd, 12 }, + { 30, 0x0068, 12 }, + { 31, 0x0069, 12 }, + { 32, 0x006a, 12 }, + { 33, 0x006b, 12 }, + { 34, 0x00d2, 12 }, + { 35, 0x00d3, 12 }, + { 36, 0x00d4, 12 }, + { 37, 0x00d5, 12 }, + { 38, 0x00d6, 12 }, + { 39, 0x00d7, 12 }, + { 40, 0x006c, 12 }, + { 41, 0x006d, 12 }, + { 42, 0x00da, 12 }, + { 43, 0x00db, 12 }, + { 44, 0x0054, 12 }, + { 45, 0x0055, 12 }, + { 46, 0x0056, 12 }, + { 47, 0x0057, 12 }, + { 48, 0x0064, 12 }, + { 49, 0x0065, 12 }, + { 50, 0x0052, 12 }, + { 51, 0x0053, 12 }, + { 52, 0x0024, 12 }, + { 53, 0x0037, 12 }, + { 54, 0x0038, 12 }, + { 55, 0x0027, 12 }, + { 56, 0x0028, 12 }, + { 57, 0x0058, 12 }, + { 58, 0x0059, 12 }, + { 59, 0x002b, 12 }, + { 60, 0x002c, 12 }, + { 61, 0x005a, 12 }, + { 62, 0x0066, 12 }, + { 63, 0x0067, 12 }, + { 64, 0x000f, 10 }, + { 128, 0x00c8, 12 }, + { 192, 0x00c9, 12 }, + { 256, 0x005b, 12 }, + { 320, 0x0033, 12 }, + { 384, 0x0034, 12 }, + { 448, 0x0035, 12 }, + { 512, 0x006c, 13 }, + { 576, 0x006d, 13 }, + { 640, 0x004a, 13 }, + { 704, 0x004b, 13 }, + { 768, 0x004c, 13 }, + { 832, 0x004d, 13 }, + { 896, 0x0072, 13 }, + { 960, 0x0073, 13 }, + { 1024, 0x0074, 13 }, + { 1088, 0x0075, 13 }, + { 1152, 0x0076, 13 }, + { 1216, 0x0077, 13 }, + { 1280, 0x0052, 13 }, + { 1344, 0x0053, 13 }, + { 1408, 0x0054, 13 }, + { 1472, 0x0055, 13 }, + { 1536, 0x005a, 13 }, + { 1600, 0x005b, 13 }, + { 1664, 0x0064, 13 }, + { 1728, 0x0065, 13 }, + { 1792, 0x0008, 11 }, + { 1856, 0x000c, 11 }, + { 1920, 0x000d, 11 }, + { 1984, 0x0012, 12 }, + { 2048, 0x0013, 12 }, + { 2112, 0x0014, 12 }, + { 2176, 0x0015, 12 }, + { 2240, 0x0016, 12 }, + { 2304, 0x0017, 12 }, + { 2368, 0x001c, 12 }, + { 2432, 0x001d, 12 }, + { 2496, 0x001e, 12 }, + { 2560, 0x001f, 12 }, + { 9999, 0x0001, 12 } // EOL +}; + + +const CCIHuffmanTableEntry CCI2DModeTableSave[CCI2DModeTableSize]={ + { CCI2DMODE_UNCOMP , 0x000f, 10 }, + { CCI2DMODE_PASS , 0x0001, 4 }, + { CCI2DMODE_HORZ , 0x0001, 3 }, + { CCI2DMODE_VERT_L3, 0x0002, 7 }, + { CCI2DMODE_VERT_L2, 0x0002, 6 }, + { CCI2DMODE_VERT_L1, 0x0002, 3 }, + { CCI2DMODE_VERT_0 , 0x0001, 1 }, + { CCI2DMODE_VERT_R1, 0x0003, 3 }, + { CCI2DMODE_VERT_R2, 0x0003, 6 }, + { CCI2DMODE_VERT_R3, 0x0003, 7 } +}; + + +const CCIHuffmanTableEntry CCIUncompTableSave[CCIUncompTableSize]={ + { CCIUNCOMP_0White_1Black, 0x0001, 1 }, + { CCIUNCOMP_1White_1Black, 0x0001, 2 }, + { CCIUNCOMP_2White_1Black, 0x0001, 3 }, + { CCIUNCOMP_3White_1Black, 0x0001, 4 }, + { CCIUNCOMP_4White_1Black, 0x0001, 5 }, + { CCIUNCOMP_5White , 0x0001, 6 }, + { CCIUNCOMP_0White_End , 0x0001, 7 }, + { CCIUNCOMP_1White_End , 0x0001, 8 }, + { CCIUNCOMP_2White_End , 0x0001, 9 }, + { CCIUNCOMP_3White_End , 0x0001, 10 }, + { CCIUNCOMP_4White_End , 0x0001, 11 } +}; + +//========================================================================= + + +CCIDecompressor::CCIDecompressor( ULONG nOpts, UINT32 nImageWidth ) : + bTableBad ( FALSE ), + bStatus ( FALSE ), + pByteSwap ( NULL ), + nWidth ( nImageWidth ), + nOptions ( nOpts ), + pLastLine ( NULL ) +{ + if ( nOpts & CCI_OPTION_INVERSEBITORDER ) + { + pByteSwap = new BYTE[ 256 ]; + for ( int i = 0; i < 256; i++ ) + { + pByteSwap[ i ] = sal::static_int_cast< BYTE >( + ( i << 7 ) | ( ( i & 2 ) << 5 ) | ( ( i & 4 ) << 3 ) | ( ( i & 8 ) << 1 ) | + ( ( i & 16 ) >> 1 ) | ( ( i & 32 ) >> 3 ) | ( ( i & 64 ) >> 5 ) | ( ( i & 128 ) >> 7 )); + } + } + + pWhiteLookUp =new CCILookUpTableEntry[1<<13]; + pBlackLookUp =new CCILookUpTableEntry[1<<13]; + p2DModeLookUp=new CCILookUpTableEntry[1<<10]; + pUncompLookUp=new CCILookUpTableEntry[1<<11]; + + MakeLookUp(CCIWhiteTable,CCIWhiteTableSave,pWhiteLookUp,CCIWhiteTableSize,13); + MakeLookUp(CCIBlackTable,CCIBlackTableSave,pBlackLookUp,CCIBlackTableSize,13); + MakeLookUp(CCI2DModeTable,CCI2DModeTableSave,p2DModeLookUp,CCI2DModeTableSize,10); + MakeLookUp(CCIUncompTable,CCIUncompTableSave,pUncompLookUp,CCIUncompTableSize,11); +} + + +CCIDecompressor::~CCIDecompressor() +{ + delete[] pByteSwap; + delete[] pLastLine; + delete[] pWhiteLookUp; + delete[] pBlackLookUp; + delete[] p2DModeLookUp; + delete[] pUncompLookUp; +} + + +void CCIDecompressor::StartDecompression( SvStream & rIStream ) +{ + pIStream = &rIStream; + nInputBitsBufSize = 0; + bFirstEOL = TRUE; + bStatus = TRUE; + nEOLCount = 0; + + if ( bTableBad == TRUE ) + return; +} + + +BOOL CCIDecompressor::DecompressScanline( BYTE * pTarget, ULONG nTargetBits ) +{ + USHORT i; + BYTE * pSrc,* pDst; + BOOL b2D; + + if ( nEOLCount >= 5 ) // RTC( Return To Controller ) + return TRUE; + + if ( bStatus == FALSE ) + return FALSE; + + // Wenn EOL-Codes vorhanden sind, steht der EOL-Code auch vor der ersten Zeile. + // (und ich dachte EOL heisst 'End Of Line'...) + // Daher lesen wir den EOL-Code immer vor jeder Zeile als erstes ein: + if ( nOptions & CCI_OPTION_EOL ) + { + if ( bFirstEOL ) + { + UINT32 nCurPos = pIStream->Tell(); + UINT16 nOldInputBitsBufSize = nInputBitsBufSize; + UINT32 nOldInputBitsBuf = nInputBitsBuf; + if ( ReadEOL( 32 ) == FALSE ) + { + nInputBitsBufSize = nOldInputBitsBufSize; + nInputBitsBuf = nOldInputBitsBuf; + pIStream->Seek( nCurPos ); + nOptions &=~ CCI_OPTION_EOL; // CCITT Group 3 - Compression Type 2 + } + bFirstEOL = FALSE; + } + else + { + if ( ReadEOL( nTargetBits ) == FALSE ) + { + return bStatus; + } + } + } + + if ( nEOLCount >= 5 ) // RTC( Return To Controller ) + return TRUE; + + // ggf. eine weisse vorherige Zeile herstellen fuer 2D: + if ( nOptions & CCI_OPTION_2D ) + { + if ( pLastLine == NULL || nLastLineSize != ( ( nTargetBits + 7 ) >> 3 ) ) + { + if ( pLastLine == NULL ) + delete[] pLastLine; + nLastLineSize = ( nTargetBits + 7 ) >> 3; + pLastLine = new BYTE[ nLastLineSize ]; + pDst = pLastLine; + for ( i = 0; i < nLastLineSize; i++ ) *( pDst++ ) = 0x00; + } + } + // ggf. Zeilen-Anfang auf naechste Byte-Grenze runden: + if ( nOptions & CCI_OPTION_BYTEALIGNROW ) + nInputBitsBufSize &= 0xfff8; + + // Ist es eine 2D-Zeile ?: + if ( nOptions & CCI_OPTION_2D ) + { + if ( nOptions & CCI_OPTION_EOL ) + b2D = Read2DTag(); + else + b2D = TRUE; + } + else + b2D = FALSE; + + // Zeile einlesen: + if ( b2D ) + Read2DScanlineData( pTarget, (USHORT)nTargetBits ); + else + Read1DScanlineData( pTarget, (USHORT)nTargetBits ); + + // Wenn wir im 2D-Modus sind, muessen wir uns die Zeile merken: + if ( nOptions & CCI_OPTION_2D && bStatus == TRUE ) + { + pSrc = pTarget; + pDst = pLastLine; + for ( i = 0; i < nLastLineSize; i++ ) *(pDst++)=*(pSrc++); + } + + if ( pIStream->GetError() ) + bStatus = FALSE; + + return bStatus; +} + + +void CCIDecompressor::MakeLookUp(const CCIHuffmanTableEntry * pHufTab, + const CCIHuffmanTableEntry * pHufTabSave, + CCILookUpTableEntry * pLookUp, + USHORT nHuffmanTableSize, + USHORT nMaxCodeBits) +{ + USHORT i,j,nMinCode,nMaxCode,nLookUpSize,nMask; + + if (bTableBad==TRUE) return; + + nLookUpSize=1<<nMaxCodeBits; + + nMask=0xffff>>(16-nMaxCodeBits); + + for (i=0; i<nLookUpSize; i++) pLookUp[i].nCodeBits=0; + for (i=0; i<nHuffmanTableSize; i++) { + if ( pHufTab[i].nValue!=pHufTabSave[i].nValue || + pHufTab[i].nCode!=pHufTabSave[i].nCode || + pHufTab[i].nCodeBits!=pHufTabSave[i].nCodeBits || + pHufTab[i].nCodeBits==0 || + pHufTab[i].nCodeBits>nMaxCodeBits ) + { + bTableBad=TRUE; + return; + } + nMinCode = nMask & (pHufTab[i].nCode << (nMaxCodeBits-pHufTab[i].nCodeBits)); + nMaxCode = nMinCode | (nMask >> pHufTab[i].nCodeBits); + for (j=nMinCode; j<=nMaxCode; j++) { + if (pLookUp[j].nCodeBits!=0) { + bTableBad=TRUE; + return; + } + pLookUp[j].nValue=pHufTab[i].nValue; + pLookUp[j].nCodeBits=pHufTab[i].nCodeBits; + } + } +} + + +BOOL CCIDecompressor::ReadEOL( UINT32 /*nMaxFillBits*/ ) +{ + USHORT nCode; + BYTE nByte; + + // if (nOptions&CCI_OPTION_BYTEALIGNEOL) nMaxFillBits=7; else nMaxFillBits=0; + // Buuuh: Entweder wird die Option in itiff.cxx nicht richtig gesetzt (-> Fehler in Doku) + // oder es gibt tatsaechlich gemeine Export-Filter, die immer ein Align machen. + // Ausserdem wurden Dateien gefunden, in denen mehr als die maximal 7 noetigen + // Fuellbits vor dem EOL-Code stehen. Daher akzeptieren wir nun grundsaetzlich + // bis zu 32-Bloedsinn-Bits vor dem EOL-Code: + // und ich habe eine Datei gefunden in der bis zu ??? Bloedsinn Bits stehen, zudem ist dort die Bit Reihenfolge verdreht (SJ); + + UINT32 nMaxPos = pIStream->Tell(); + nMaxPos += nWidth >> 3; + + for ( ;; ) + { + while ( nInputBitsBufSize < 12 ) + { + *pIStream >> nByte; + if ( pIStream->IsEof() ) + return FALSE; + if ( pIStream->Tell() > nMaxPos ) + return FALSE; + + if ( nOptions & CCI_OPTION_INVERSEBITORDER ) + nByte = pByteSwap[ nByte ]; + nInputBitsBuf=(nInputBitsBuf<<8) | (ULONG)nByte; + nInputBitsBufSize += 8; + } + nCode = (USHORT)( ( nInputBitsBuf >> ( nInputBitsBufSize - 12 ) ) & 0x0fff ); + if ( nCode == 0x0001 ) + { + nEOLCount++; + nInputBitsBufSize -= 12; + break; + } + else + nInputBitsBufSize--; + } + return TRUE; +} + + +BOOL CCIDecompressor::Read2DTag() +{ + BYTE nByte; + + // Ein Bit einlesen und TRUE liefern, wenn es 0 ist, sonst FALSE + if (nInputBitsBufSize==0) { + *pIStream >> nByte; + if ( nOptions & CCI_OPTION_INVERSEBITORDER ) + nByte = pByteSwap[ nByte ]; + nInputBitsBuf=(ULONG)nByte; + nInputBitsBufSize=8; + } + nInputBitsBufSize--; + if ( ((nInputBitsBuf>>nInputBitsBufSize)&0x0001) ) return FALSE; + else return TRUE; +} + + +BYTE CCIDecompressor::ReadBlackOrWhite() +{ + BYTE nByte; + + // Ein Bit einlesen und 0x00 liefern, wenn es 0 ist, sonst 0xff + if (nInputBitsBufSize==0) { + *pIStream >> nByte; + if ( nOptions & CCI_OPTION_INVERSEBITORDER ) + nByte = pByteSwap[ nByte ]; + nInputBitsBuf=(ULONG)nByte; + nInputBitsBufSize=8; + } + nInputBitsBufSize--; + if ( ((nInputBitsBuf>>nInputBitsBufSize)&0x0001) ) return 0xff; + else return 0x00; +} + + +USHORT CCIDecompressor::ReadCodeAndDecode(const CCILookUpTableEntry * pLookUp, + USHORT nMaxCodeBits) +{ + USHORT nCode,nCodeBits; + BYTE nByte; + + // Einen Huffman-Code einlesen und dekodieren: + while (nInputBitsBufSize<nMaxCodeBits) { + *pIStream >> nByte; + if ( nOptions & CCI_OPTION_INVERSEBITORDER ) + nByte = pByteSwap[ nByte ]; + nInputBitsBuf=(nInputBitsBuf<<8) | (ULONG)nByte; + nInputBitsBufSize+=8; + } + nCode=(USHORT)((nInputBitsBuf>>(nInputBitsBufSize-nMaxCodeBits)) + &(0xffff>>(16-nMaxCodeBits))); + nCodeBits=pLookUp[nCode].nCodeBits; + if (nCodeBits==0) bStatus=FALSE; + nInputBitsBufSize = nInputBitsBufSize - nCodeBits; + return pLookUp[nCode].nValue; +} + + +void CCIDecompressor::FillBits(BYTE * pTarget, USHORT nTargetBits, + USHORT nBitPos, USHORT nNumBits, + BYTE nBlackOrWhite) +{ + if ( nBitPos >= nTargetBits ) + return; + if ( nBitPos + nNumBits > nTargetBits ) + nNumBits = nTargetBits - nBitPos; + + pTarget+=nBitPos>>3; + nBitPos&=7; + + if (nBlackOrWhite==0x00) *pTarget &= 0xff << (8-nBitPos); + else *pTarget |= 0xff >> nBitPos; + if (nNumBits>8-nBitPos) { + nNumBits-=8-nBitPos; + while (nNumBits>=8) { + *(++pTarget)=nBlackOrWhite; + nNumBits-=8; + } + if (nNumBits>0) *(++pTarget)=nBlackOrWhite; + } +} + + +USHORT CCIDecompressor::CountBits(const BYTE * pData, USHORT nDataSizeBits, + USHORT nBitPos, BYTE nBlackOrWhite) +{ + USHORT nPos,nLo; + BYTE nData; + + // Hier wird die Anzahl der zusammenhaengenden Bits gezaehlt, die + // ab Position nBitPos in pTarget alle die Farbe nBlackOrWhite + // (0xff oder 0x00) haben. + + nPos=nBitPos; + for (;;) { + if (nPos>=nDataSizeBits) { + nPos=nDataSizeBits; + break; + } + nData=pData[nPos>>3]; + nLo=nPos & 7; + if ( nLo==0 && nData==nBlackOrWhite) nPos+=8; + else { + if ( ((nData^nBlackOrWhite) & (0x80 >> nLo))!=0) break; + nPos++; + } + } + if (nPos<=nBitPos) return 0; + else return nPos-nBitPos; +} + + +void CCIDecompressor::Read1DScanlineData(BYTE * pTarget, USHORT nTargetBits) +{ + USHORT nCode,nCodeBits,nDataBits,nTgtFreeByteBits; + BYTE nByte; + BYTE nBlackOrWhite; // ist 0xff fuer Black oder 0x00 fuer White + BOOL bTerminatingCode; + + // Der erste Code ist immer eine "White-Code": + nBlackOrWhite=0x00; + + // Anzahl der Bits, die im Byte *pTarget noch nicht geschrieben sind: + nTgtFreeByteBits=8; + + // Schleife ueber Codes aus dem Eingabe-Stream: + do { + + // die naechsten 13 Bits nach nCode holen, aber noch nicht + // aus dem Eingabe-Buffer loeschen: + while (nInputBitsBufSize<13) { + *pIStream >> nByte; + if ( nOptions & CCI_OPTION_INVERSEBITORDER ) + nByte = pByteSwap[ nByte ]; + nInputBitsBuf=(nInputBitsBuf<<8) | (ULONG)nByte; + nInputBitsBufSize+=8; + } + nCode=(USHORT)((nInputBitsBuf>>(nInputBitsBufSize-13))&0x1fff); + + // Anzahl der DatenBits und Anzahl der CodeBits ermitteln: + if (nBlackOrWhite) { + nCodeBits=pBlackLookUp[nCode].nCodeBits; + nDataBits=pBlackLookUp[nCode].nValue; + } + else { + nCodeBits=pWhiteLookUp[nCode].nCodeBits; + nDataBits=pWhiteLookUp[nCode].nValue; + } + // Ist es ein Ungueltiger Code ? + if ( nDataBits == 9999 ) + { + return; + } + if ( nCodeBits == 0 ) + { + return; // das koennen sich jetzt um FuellBits handeln + } + nEOLCount = 0; + // Zuviele Daten ? + if (nDataBits>nTargetBits) { + // Ja, koennte ein Folge-Fehler durch ungueltigen Code sein, + // daher irdenwie weitermachen: + nDataBits=nTargetBits; + } + + // Ist es ein 'Terminating-Code' ? + if (nDataBits<64) bTerminatingCode=TRUE; else bTerminatingCode=FALSE; + + // Die gelesenen Bits aus dem Eingabe-Buffer entfernen: + nInputBitsBufSize = nInputBitsBufSize - nCodeBits; + + // Die Anzahl Daten-Bits in die Scanline schreiben: + if (nDataBits>0) { + nTargetBits = nTargetBits - nDataBits; + if (nBlackOrWhite==0x00) *pTarget &= 0xff << nTgtFreeByteBits; + else *pTarget |= 0xff >> (8-nTgtFreeByteBits); + if (nDataBits<=nTgtFreeByteBits) { + if (nDataBits==nTgtFreeByteBits) { + pTarget++; + nTgtFreeByteBits=8; + } + else nTgtFreeByteBits = nTgtFreeByteBits - nDataBits; + } + else { + nDataBits = nDataBits - nTgtFreeByteBits; + pTarget++; + nTgtFreeByteBits=8; + while (nDataBits>=8) { + *(pTarget++)=nBlackOrWhite; + nDataBits-=8; + } + if (nDataBits>0) { + *pTarget=nBlackOrWhite; + nTgtFreeByteBits = nTgtFreeByteBits - nDataBits; + } + } + } + + // ggf. Umschaltung Black <-> White: + if (bTerminatingCode==TRUE) nBlackOrWhite=~nBlackOrWhite; + + } while (nTargetBits>0 || bTerminatingCode==FALSE); +} + + + +void CCIDecompressor::Read2DScanlineData(BYTE * pTarget, USHORT nTargetBits) +{ + USHORT n2DMode,nBitPos,nUncomp,nRun,nRun2,nt; + BYTE nBlackOrWhite; + + nBlackOrWhite=0x00; + nBitPos=0; + + while (nBitPos<nTargetBits && bStatus==TRUE) { + + n2DMode=ReadCodeAndDecode(p2DModeLookUp,10); + if (bStatus==FALSE) return; + + if (n2DMode==CCI2DMODE_UNCOMP) { + for (;;) { + nUncomp=ReadCodeAndDecode(pUncompLookUp,11); + if ( nUncomp <= CCIUNCOMP_4White_1Black ) { + nRun=nUncomp-CCIUNCOMP_0White_1Black; + FillBits(pTarget,nTargetBits,nBitPos,nRun,0x00); + nBitPos = nBitPos + nRun; + FillBits(pTarget,nTargetBits,nBitPos,1,0xff); + nBitPos++; + } + else if ( nUncomp == CCIUNCOMP_5White ) { + FillBits(pTarget,nTargetBits,nBitPos,5,0x00); + nBitPos = nBitPos + 5; + } + else { + nRun=nUncomp-CCIUNCOMP_0White_End; + FillBits(pTarget,nTargetBits,nBitPos,nRun,0x00); + nBitPos = nBitPos + nRun; + nBlackOrWhite=ReadBlackOrWhite(); + break; + } + } + } + + else if (n2DMode==CCI2DMODE_PASS) { + if (nBitPos==0 && nBlackOrWhite==0x00 && CountBits(pLastLine,nTargetBits,0,0xff)!=0) nRun=0; + else { + nRun=CountBits(pLastLine,nTargetBits,nBitPos,~nBlackOrWhite); + nRun = nRun + CountBits(pLastLine,nTargetBits,nBitPos+nRun,nBlackOrWhite); + } + nRun = nRun + CountBits(pLastLine,nTargetBits,nBitPos+nRun,~nBlackOrWhite); + FillBits(pTarget,nTargetBits,nBitPos,nRun,nBlackOrWhite); + nBitPos = nBitPos + nRun; + } + + else if (n2DMode==CCI2DMODE_HORZ) { + if (nBlackOrWhite==0x00) { + nRun=0; + do { + nt=ReadCodeAndDecode(pWhiteLookUp,13); + nRun = nRun + nt; + } while (nt>=64); + nRun2=0; + do { + nt=ReadCodeAndDecode(pBlackLookUp,13); + nRun2 = nRun2 + nt; + } while (nt>=64); + } + else { + nRun=0; + do { + nt=ReadCodeAndDecode(pBlackLookUp,13); + nRun = nRun + nt; + } while (nt>=64); + nRun2=0; + do { + nt=ReadCodeAndDecode(pWhiteLookUp,13); + nRun2 = nRun2 + nt; + } while (nt>=64); + } + FillBits(pTarget,nTargetBits,nBitPos,nRun,nBlackOrWhite); + nBitPos = nBitPos + nRun; + FillBits(pTarget,nTargetBits,nBitPos,nRun2,~nBlackOrWhite); + nBitPos = nBitPos + nRun2; + } + + else { // Es ist einer der Modi CCI2DMODE_VERT_... + if (nBitPos==0 && nBlackOrWhite==0x00 && CountBits(pLastLine,nTargetBits,0,0xff)!=0) nRun=0; + else { + nRun=CountBits(pLastLine,nTargetBits,nBitPos,~nBlackOrWhite); + nRun = nRun + CountBits(pLastLine,nTargetBits,nBitPos+nRun,nBlackOrWhite); + } + nRun+=n2DMode-CCI2DMODE_VERT_0; + FillBits(pTarget,nTargetBits,nBitPos,nRun,nBlackOrWhite); + nBitPos = nBitPos + nRun; + nBlackOrWhite=~nBlackOrWhite; + } + } +} + + diff --git a/filter/source/graphicfilter/itiff/ccidecom.hxx b/filter/source/graphicfilter/itiff/ccidecom.hxx new file mode 100644 index 000000000000..2543be82d052 --- /dev/null +++ b/filter/source/graphicfilter/itiff/ccidecom.hxx @@ -0,0 +1,125 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _CCIDECOM_HXX +#define _CCIDECOM_HXX + +#include <tools/stream.hxx> + + +#define CCI_OPTION_2D 1 // 2D-Komprimierung (statt 1D) +#define CCI_OPTION_EOL 2 // EOL-Codes am Ende jeder Zeile vorhanden +#define CCI_OPTION_BYTEALIGNEOL 4 // Fuellbits vor jedem EOL-Code, so dass + // Ende von EOL auf Bytes aligend +#define CCI_OPTION_BYTEALIGNROW 8 // Rows beginnen immer auf Byte-Grenze +#define CCI_OPTION_INVERSEBITORDER 16 + +// Eintrag in eine Huffman-Tabelle: +struct CCIHuffmanTableEntry { + USHORT nValue; // Der Daten-Wert. + USHORT nCode; // Der Code durch den der Daten-Wert repraesentiert wird. + USHORT nCodeBits; // Laenge des Codes in Bits. +}; + + +// Eintrag in eine Hash-Tabelle zur schnellen Dekodierung +struct CCILookUpTableEntry { + USHORT nValue; + USHORT nCodeBits; +}; + + +class CCIDecompressor { + +public: + + CCIDecompressor( ULONG nOptions, UINT32 nImageWidth ); + ~CCIDecompressor(); + + void StartDecompression( SvStream & rIStream ); + + BOOL DecompressScanline(BYTE * pTarget, ULONG nTargetBits ); + +private: + + void MakeLookUp(const CCIHuffmanTableEntry * pHufTab, + const CCIHuffmanTableEntry * pHufTabSave, + CCILookUpTableEntry * pLookUp, + USHORT nHuffmanTableSize, + USHORT nMaxCodeBits); + + BOOL ReadEOL( UINT32 nMaxFillBits ); + + BOOL Read2DTag(); + + BYTE ReadBlackOrWhite(); + + USHORT ReadCodeAndDecode(const CCILookUpTableEntry * pLookUp, + USHORT nMaxCodeBits); + + void FillBits(BYTE * pTarget, USHORT nTargetBits, + USHORT nBitPos, USHORT nNumBits, + BYTE nBlackOrWhite); + + USHORT CountBits(const BYTE * pData, USHORT nDataSizeBits, + USHORT nBitPos, BYTE nBlackOrWhite); + + void Read1DScanlineData(BYTE * pTarget, USHORT nTargetBits); + + void Read2DScanlineData(BYTE * pTarget, USHORT nTargetBits); + + BOOL bTableBad; + + BOOL bStatus; + + BYTE* pByteSwap; + + SvStream * pIStream; + + UINT32 nEOLCount; + + UINT32 nWidth; + + ULONG nOptions; + + BOOL bFirstEOL; + + CCILookUpTableEntry * pWhiteLookUp; + CCILookUpTableEntry * pBlackLookUp; + CCILookUpTableEntry * p2DModeLookUp; + CCILookUpTableEntry * pUncompLookUp; + + ULONG nInputBitsBuf; + USHORT nInputBitsBufSize; + + BYTE * pLastLine; + ULONG nLastLineSize; +}; + + +#endif + diff --git a/filter/source/graphicfilter/itiff/exports.map b/filter/source/graphicfilter/itiff/exports.map new file mode 100644 index 000000000000..941e4ab9bde8 --- /dev/null +++ b/filter/source/graphicfilter/itiff/exports.map @@ -0,0 +1,7 @@ +UDK_3_0_0 { + global: + GraphicImport; + + local: + *; +}; diff --git a/filter/source/graphicfilter/itiff/itiff.cxx b/filter/source/graphicfilter/itiff/itiff.cxx new file mode 100644 index 000000000000..5ad400fc3149 --- /dev/null +++ b/filter/source/graphicfilter/itiff/itiff.cxx @@ -0,0 +1,1342 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_filter.hxx" +#include <vcl/graph.hxx> +#include <vcl/bmpacc.hxx> +#ifndef _SV_FLTCALL_HXX +#include <svtools/fltcall.hxx> +#endif +#include <vcl/animate.hxx> +#include "lzwdecom.hxx" +#include "ccidecom.hxx" + +#define OOODEBUG(str,Num) //(InfoBox(NULL,String(str)+String(" ")+String(Num)).Execute(); + +namespace { + +template< typename T > T BYTESWAP(T nByte) { + return ( nByte << 7 ) | ( ( nByte & 2 ) << 5 ) | ( ( nByte & 4 ) << 3 ) | + ( ( nByte & 8 ) << 1 ) | ( ( nByte & 16 ) >> 1 ) | + ( ( nByte & 32 ) >> 3 ) | ( ( nByte & 64 ) >> 5 ) | + ( ( nByte & 128 ) >> 7 ); +} + +} + +//============================ TIFFReader ================================== + +class TIFFReader +{ + +private: + + BOOL bStatus; // Ob bisher kein Fehler auftrat + Animation aAnimation; + ULONG nLastPercent; + + SvStream* pTIFF; // Die einzulesende TIFF-Datei + Bitmap aBitmap; + BitmapWriteAccess* pAcc; + USHORT nDstBitsPerPixel; + + ULONG nOrigPos; // Anfaengliche Position in pTIFF + UINT16 nOrigNumberFormat; // Anfaengliches Nummern-Format von pTIFF + + + UINT16 nDataType; + // Daten, die aus dem TIFF-Tags entnommen werden: + BOOL bByteSwap; // TRUE wenn bits 0..7 -> 7..0 invertiert werden sollen ( FILLORDER = 2 ); + BYTE nByte1; // 'I', wenn Format LittleEndian + + ULONG nNewSubFile; // + ULONG nSubFile; // + ULONG nImageWidth; // Bildbreite in Pixel + ULONG nImageLength; // Bildhoehe in Pixel + ULONG nBitsPerSample; // Bits pro Pixel pro Ebene + ULONG nCompression; // Art der Kompriemierung + ULONG nPhotometricInterpretation; // + ULONG nThresholding; // + ULONG nCellWidth; // + ULONG nCellLength; // + ULONG nFillOrder; // + ULONG* pStripOffsets; // Feld von Offsets zu den Bitmap-Daten-"Strips" + ULONG nNumStripOffsets; // Groesse obigen Feldes + ULONG nOrientation; // + ULONG nSamplesPerPixel; // Anzahl der Ebenen + ULONG nRowsPerStrip; // Wenn nicht komprimiert: Zahl der Zeilen pro Strip + ULONG* pStripByteCounts; // Wenn komprimiert (bestimmte Art): Groesse der Strips + ULONG nNumStripByteCounts; // Anzahl der Eintraege in obiges Feld + ULONG nMinSampleValue; // + ULONG nMaxSampleValue; // + double fXResolution; // X-Aufloesung oder 0.0 + double fYResolution; // Y-Aufloesung oder 0.0 + ULONG nPlanarConfiguration; // + ULONG nGroup3Options; // + ULONG nGroup4Options; // + ULONG nResolutionUnit; // Einheit von fX/YResolution: 1=unbekannt, 2(default)=Zoll, 3=cm + ULONG nPredictor; // + ULONG* pColorMap; // Farb-Palette + ULONG nNumColors; // Anzahl Farben in der Farbpalette + + ULONG nPlanes; // Anzahl der Ebenen in der Tiff-Datei + ULONG nStripsPerPlane; // Anzahl der Strips pro Ebene + ULONG nBytesPerRow; // Bytes pro Zeile pro Ebene in der Tiff-Datei ( unkomprimiert ) + BYTE* pMap[ 4 ]; // Temporaere Scanline + + + void MayCallback( ULONG nPercent ); + + ULONG DataTypeSize(); + ULONG ReadIntData(); + double ReadDoubleData(); + + void ReadHeader(); + void ReadTagData( USHORT nTagType, sal_uInt32 nDataLen ); + + BOOL ReadMap( ULONG nMinPercent, ULONG nMaxPercent ); + // Liesst/dekomprimert die Bitmap-Daten, und fuellt pMap + + ULONG GetBits( const BYTE * pSrc, ULONG nBitsPos, ULONG nBitsCount ); + // Holt nBitsCount Bits aus pSrc[..] an der Bit-Position nBitsPos + + void MakePalCol( void ); + // Erzeugt die Bitmap aus der temporaeren Bitmap pMap + // und loescht dabei pMap teilweise + BOOL ConvertScanline( ULONG nY ); + // Konvertiert eine Scanline in das Windows-BMP-Format + +public: + + TIFFReader() {} + ~TIFFReader() {} + + BOOL ReadTIFF( SvStream & rTIFF, Graphic & rGraphic ); +}; + +//=================== Methoden von TIFFReader ============================== + +void TIFFReader::MayCallback( ULONG /*nPercent*/ ) +{ +/* + if ( nPercent >= nLastPercent + 3 ) + { + nLastPercent=nPercent; + if ( pCallback != NULL && nPercent <= 100 && bStatus == TRUE ) + { + if (((*pCallback)(pCallerData,(USHORT)nPercent)) == TRUE ) + bStatus = FALSE; + } + } +*/ +} + +// --------------------------------------------------------------------------------- + +ULONG TIFFReader::DataTypeSize() +{ + ULONG nSize; + switch ( nDataType ) + { + case 1 : // BYTE + case 2 : // ACSII + case 6 : // SIGNED Byte + case 7 : // UNDEFINED + nSize = 1; + break; + case 3 : // UINT16 + case 8 : // INT16 + nSize = 2; + break; + case 4 : // UINT32 + case 9 : // INT32 + case 11 : // FLOAT + nSize = 4; + break; + case 5 : // RATIONAL + case 10 : // SIGNED RATINAL + case 12 : // DOUBLE + nSize = 8; + break; + default: + pTIFF->SetError(SVSTREAM_FILEFORMAT_ERROR); + nSize=1; + } + return nSize; +} + +// --------------------------------------------------------------------------------- + +ULONG TIFFReader::ReadIntData() +{ + double nDOUBLE; + float nFLOAT; + UINT32 nUINT32a, nUINT32b; + INT32 nINT32; + UINT16 nUINT16; + INT16 nINT16; + BYTE nBYTE; + char nCHAR; + + switch( nDataType ) + { + case 0 : //?? + case 1 : + case 2 : + case 7 : + *pTIFF >> nBYTE; + nUINT32a = (ULONG)nBYTE; + break; + case 3 : + *pTIFF >> nUINT16; + nUINT32a = (ULONG)nUINT16; + break; + case 9 : + case 4 : + *pTIFF >> nUINT32a; + break; + case 5 : + *pTIFF >> nUINT32a >> nUINT32b; + if ( nUINT32b != 0 ) + nUINT32a /= nUINT32b; + break; + case 6 : + *pTIFF >> nCHAR; + nUINT32a = (INT32)nCHAR; + break; + case 8 : + *pTIFF >> nINT16; + nUINT32a = (INT32)nINT16; + break; + case 10 : + *pTIFF >> nUINT32a >> nINT32; + if ( nINT32 != 0 ) + nUINT32a /= nINT32; + break; + case 11 : + *pTIFF >> nFLOAT; + nUINT32a = (INT32)nFLOAT; + break; + case 12 : + *pTIFF >> nDOUBLE; + nUINT32a = (INT32)nDOUBLE; + break; + default: + *pTIFF >> nUINT32a; + break; + } + return nUINT32a; +} + +// --------------------------------------------------------------------------------- + +double TIFFReader::ReadDoubleData() +{ + sal_uInt32 nulong; + double nd; + + if ( nDataType == 5 ) + { + *pTIFF >> nulong; + nd = (double)nulong; + *pTIFF >> nulong; + if ( nulong != 0 ) + nd /= (double)nulong; + } + else + nd = (double)ReadIntData(); + return nd; +} + +// --------------------------------------------------------------------------------- + +void TIFFReader::ReadTagData( USHORT nTagType, sal_uInt32 nDataLen) +{ + if ( bStatus == FALSE ) + return; + + switch ( nTagType ) + { + case 0x00fe: // New Sub File + nNewSubFile = ReadIntData(); + OOODEBUG("NewSubFile",nNewSubFile); + break; + + case 0x00ff: // Sub File + nSubFile = ReadIntData(); + OOODEBUG("SubFile",nSubFile); + break; + + case 0x0100: // Image Width + nImageWidth = ReadIntData(); + OOODEBUG("ImageWidth",nImageWidth); + break; + + case 0x0101: // Image Length + nImageLength = ReadIntData(); + OOODEBUG("ImageLength",nImageLength); + break; + + case 0x0102: // Bits Per Sample + nBitsPerSample = ReadIntData(); + OOODEBUG("BitsPerSample",nBitsPerSample); + break; + + case 0x0103: // Compression + nCompression = ReadIntData(); + OOODEBUG("Compression",nCompression); + break; + + case 0x0106: // Photometric Interpreation + nPhotometricInterpretation = ReadIntData(); + OOODEBUG("PhotometricInterpretation",nPhotometricInterpretation); + break; + + case 0x0107: // Thresholding + nThresholding = ReadIntData(); + OOODEBUG("Thresholding",nThresholding); + break; + + case 0x0108: // Cell Width + nCellWidth = ReadIntData(); + break; + + case 0x0109: // Cell Length + nCellLength = ReadIntData(); + break; + + case 0x010a: // Fill Order + nFillOrder = ReadIntData(); + OOODEBUG("FillOrder",nFillOrder); + break; + + case 0x0111: { // Strip Offset(s) + ULONG nOldNumSO, i, * pOldSO; + pOldSO = pStripOffsets; + if ( pOldSO == NULL ) + nNumStripOffsets = 0; + nOldNumSO = nNumStripOffsets; + nDataLen += nOldNumSO; + if ( ( nDataLen > nOldNumSO ) && ( nDataLen < SAL_MAX_UINT32 / sizeof( sal_uInt32 ) ) ) + { + nNumStripOffsets = nDataLen; + try + { + pStripOffsets = new ULONG[ nNumStripOffsets ]; + } + catch (std::bad_alloc) + { + pStripOffsets = NULL; + nNumStripOffsets = 0; + } + if ( pStripOffsets ) + { + for ( i = 0; i < nOldNumSO; i++ ) + pStripOffsets[ i ] = pOldSO[ i ] + nOrigPos; + for ( i = nOldNumSO; i < nNumStripOffsets; i++ ) + pStripOffsets[ i ] = ReadIntData() + nOrigPos; + } + delete[] pOldSO; + } + OOODEBUG("StripOffsets (Anzahl:)",nDataLen); + break; + } + case 0x0112: // Orientation + nOrientation = ReadIntData(); + OOODEBUG("Orientation",nOrientation); + break; + + case 0x0115: // Samples Per Pixel + nSamplesPerPixel = ReadIntData(); + OOODEBUG("SamplesPerPixel",nSamplesPerPixel); + break; + + case 0x0116: // Rows Per Strip + nRowsPerStrip = ReadIntData(); + OOODEBUG("RowsPerStrip",nRowsPerStrip); + break; + + case 0x0117: { // Strip Byte Counts + ULONG nOldNumSBC, i, * pOldSBC; + pOldSBC = pStripByteCounts; + if ( pOldSBC == NULL ) + nNumStripByteCounts = 0; // Sicherheitshalber + nOldNumSBC = nNumStripByteCounts; + nDataLen += nOldNumSBC; + if ( ( nDataLen > nOldNumSBC ) && ( nDataLen < SAL_MAX_UINT32 / sizeof( sal_uInt32 ) ) ) + { + nNumStripByteCounts = nDataLen; + try + { + pStripByteCounts = new ULONG[ nNumStripByteCounts ]; + } + catch (std::bad_alloc) + { + pStripByteCounts = NULL; + nNumStripByteCounts = 0; + } + if ( pStripByteCounts ) + { + for ( i = 0; i < nOldNumSBC; i++ ) + pStripByteCounts[ i ] = pOldSBC[ i ]; + for ( i = nOldNumSBC; i < nNumStripByteCounts; i++) + pStripByteCounts[ i ] = ReadIntData(); + } + delete[] pOldSBC; + } + OOODEBUG("StripByteCounts (Anzahl:)",nDataLen); + break; + } + case 0x0118: // Min Sample Value + nMinSampleValue = ReadIntData(); + OOODEBUG("MinSampleValue",nMinSampleValue); + break; + + case 0x0119: // Max Sample Value + nMaxSampleValue = ReadIntData(); + OOODEBUG("MaxSampleValue",nMaxSampleValue); + break; + + case 0x011a: // X Resolution + fXResolution = ReadDoubleData(); + break; + + case 0x011b: // Y Resolution + fYResolution = ReadDoubleData(); + break; + + case 0x011c: // Planar Configuration + nPlanarConfiguration = ReadIntData(); + OOODEBUG("PlanarConfiguration",nPlanarConfiguration); + break; + + case 0x0124: // Group 3 Options + nGroup3Options = ReadIntData(); + OOODEBUG("Group3Options",nGroup3Options); + break; + + case 0x0125: // Group 4 Options + nGroup4Options = ReadIntData(); + OOODEBUG("Group4Options",nGroup4Options); + break; + + case 0x0128: // Resolution Unit + nResolutionUnit = ReadIntData(); + break; + + case 0x013d: // Predictor + nPredictor = ReadIntData(); + OOODEBUG("Predictor",nPredictor); + break; + + case 0x0140: { // Color Map + USHORT nVal; + ULONG i; + nNumColors= ( 1 << nBitsPerSample ); + if ( nDataType == 3 && nNumColors <= 256) + { + pColorMap = new ULONG[ 256 ]; + for ( i = 0; i < nNumColors; i++ ) + pColorMap[ i ] = 0; + for ( i = 0; i < nNumColors; i++ ) + { + *pTIFF >> nVal; + pColorMap[ i ] |= ( ( (ULONG)nVal ) << 8 ) & 0x00ff0000; + } + for ( i = 0; i < nNumColors; i++ ) + { + *pTIFF >> nVal; + pColorMap[ i ] |= ( (ULONG)nVal ) & 0x0000ff00; + } + for ( i = 0; i < nNumColors; i++ ) + { + *pTIFF >> nVal; + pColorMap[ i ] |= ( ( (ULONG)nVal ) >> 8 ) & 0x000000ff; + } + } + else + bStatus = FALSE; + OOODEBUG("ColorMap (Anzahl Farben:)", nNumColors); + break; + } + } + + if ( pTIFF->GetError() ) + bStatus = FALSE; +} + +// --------------------------------------------------------------------------------- + +BOOL TIFFReader::ReadMap( ULONG nMinPercent, ULONG nMaxPercent ) +{ + if ( nCompression == 1 || nCompression == 32771 ) + { + ULONG ny, np, nStrip, nStripBytesPerRow; + + if ( nCompression == 1 ) + nStripBytesPerRow = nBytesPerRow; + else + nStripBytesPerRow = ( nBytesPerRow + 1 ) & 0xfffffffe; + for ( ny = 0; ny < nImageLength; ny++ ) + { + for ( np = 0; np < nPlanes; np++ ) + { + nStrip = ny / nRowsPerStrip + np * nStripsPerPlane; + if ( nStrip >= nNumStripOffsets ) + return FALSE; + pTIFF->Seek( pStripOffsets[ nStrip ] + ( ny % nRowsPerStrip ) * nStripBytesPerRow ); + pTIFF->Read( pMap[ np ], nBytesPerRow ); + if ( pTIFF->GetError() ) + return FALSE; + MayCallback( nMinPercent + ( nMaxPercent - nMinPercent ) * ( np * nImageLength + ny) / ( nImageLength * nPlanes ) ); + } + if ( !ConvertScanline( ny ) ) + return FALSE; + } + } + else if ( nCompression == 2 || nCompression == 3 || nCompression == 4 ) + { + ULONG ny, np, nStrip, nOptions; + if ( nCompression == 2 ) + { + nOptions = CCI_OPTION_BYTEALIGNROW; + } + else if ( nCompression == 3 ) + { + nOptions = CCI_OPTION_EOL; + if ( nGroup3Options & 0x00000001 ) + nOptions |= CCI_OPTION_2D; + if ( nGroup3Options & 0x00000004 ) + nOptions |= CCI_OPTION_BYTEALIGNEOL; + if ( nGroup3Options & 0xfffffffa ) + return FALSE; + } + else + { // nCompression==4 + nOptions = CCI_OPTION_2D; + if ( nGroup4Options & 0xffffffff ) + return FALSE; + } + if ( nFillOrder == 2 ) + { + nOptions |= CCI_OPTION_INVERSEBITORDER; + bByteSwap = FALSE; + } + nStrip = 0; + if ( nStrip >= nNumStripOffsets ) + return FALSE; + pTIFF->Seek(pStripOffsets[nStrip]); + + CCIDecompressor aCCIDecom( nOptions, nImageWidth ); + + aCCIDecom.StartDecompression( *pTIFF ); + + for ( ny = 0; ny < nImageLength; ny++ ) + { + for ( np = 0; np < nPlanes; np++ ) + { + if ( ny / nRowsPerStrip + np * nStripsPerPlane > nStrip ) + { + nStrip=ny/nRowsPerStrip+np*nStripsPerPlane; + if ( nStrip >= nNumStripOffsets ) + return FALSE; + pTIFF->Seek( pStripOffsets[ nStrip ] ); + aCCIDecom.StartDecompression( *pTIFF ); + } + if ( aCCIDecom.DecompressScanline( pMap[ np ], nImageWidth * nBitsPerSample * nSamplesPerPixel / nPlanes ) == FALSE ) + return FALSE; + if ( pTIFF->GetError() ) + return FALSE; + MayCallback(nMinPercent+(nMaxPercent-nMinPercent)*(np*nImageLength+ny)/(nImageLength*nPlanes)); + } + if ( !ConvertScanline( ny ) ) + return FALSE; + } + } + else if ( nCompression == 5 ) + { + LZWDecompressor aLZWDecom; + ULONG ny, np, nStrip; + nStrip=0; + if ( nStrip >= nNumStripOffsets ) + return FALSE; + pTIFF->Seek(pStripOffsets[nStrip]); + aLZWDecom.StartDecompression(*pTIFF); + for ( ny = 0; ny < nImageLength; ny++ ) + { + for ( np = 0; np < nPlanes; np++ ) + { + if ( ny / nRowsPerStrip + np * nStripsPerPlane > nStrip ) + { + nStrip = ny / nRowsPerStrip + np * nStripsPerPlane; + if ( nStrip >= nNumStripOffsets ) + return FALSE; + pTIFF->Seek(pStripOffsets[nStrip]); + aLZWDecom.StartDecompression(*pTIFF); + } + if ( ( aLZWDecom.Decompress( pMap[ np ], nBytesPerRow ) != nBytesPerRow ) || pTIFF->GetError() ) + return FALSE; + MayCallback(nMinPercent+(nMaxPercent-nMinPercent)*(np*nImageLength+ny)/(nImageLength*nPlanes)); + } + if ( !ConvertScanline( ny ) ) + return FALSE; + } + } + else if ( nCompression == 32773 ) + { + ULONG nStrip,nRecCount,nRowBytesLeft,ny,np,i; + BYTE * pdst, nRecHeader, nRecData; + nStrip = 0; + if ( nStrip >= nNumStripOffsets ) + return FALSE; + pTIFF->Seek(pStripOffsets[nStrip]); + for ( ny = 0; ny < nImageLength; ny++ ) + { + for ( np = 0; np < nPlanes; np++ ) + { + if ( ny / nRowsPerStrip + np * nStripsPerPlane > nStrip ) + { + nStrip=ny/nRowsPerStrip+np*nStripsPerPlane; + if ( nStrip >= nNumStripOffsets ) + return FALSE; + pTIFF->Seek(pStripOffsets[nStrip]); + } + nRowBytesLeft = nBytesPerRow; + pdst=pMap[ np ]; + do + { + *pTIFF >> nRecHeader; + if ((nRecHeader&0x80)==0) + { + nRecCount=0x00000001+((ULONG)nRecHeader); + if ( nRecCount > nRowBytesLeft ) + return FALSE; + pTIFF->Read(pdst,nRecCount); + pdst+=nRecCount; + nRowBytesLeft-=nRecCount; + } + else if ( nRecHeader != 0x80 ) + { + nRecCount = 0x000000101 - ( (ULONG)nRecHeader ); + if ( nRecCount > nRowBytesLeft ) + { + nRecCount = nRowBytesLeft; + +// bStatus = FALSE; +// return; + + } + *pTIFF >> nRecData; + for ( i = 0; i < nRecCount; i++ ) + *(pdst++) = nRecData; + nRowBytesLeft -= nRecCount; + } + } while ( nRowBytesLeft != 0 ); + if ( pTIFF->GetError() ) + return FALSE; + MayCallback(nMinPercent+(nMaxPercent-nMinPercent)*(np*nImageLength+ny)/(nImageLength*nPlanes)); + } + if ( !ConvertScanline( ny ) ) + return FALSE; + } + } + else + return FALSE; + return TRUE; +} + +ULONG TIFFReader::GetBits( const BYTE * pSrc, ULONG nBitsPos, ULONG nBitsCount ) +{ + ULONG nRes; + if ( bByteSwap ) + { + pSrc += ( nBitsPos >> 3 ); + nBitsPos &= 7; + BYTE nDat = *pSrc; + nRes = (ULONG)( BYTESWAP( nDat ) & ( 0xff >> nBitsPos ) ); + + if ( nBitsCount <= 8 - nBitsPos ) + { + nRes >>= ( 8 - nBitsPos - nBitsCount ); + } + else + { + pSrc++; + nBitsCount -= 8 - nBitsPos; + while ( nBitsCount >= 8 ) + { + nDat = *(pSrc++); + nRes = ( nRes << 8 ) | ((ULONG)BYTESWAP( nDat ) ); + nBitsCount -= 8; + } + if ( nBitsCount > 0 ) + { + nDat = *pSrc; + nRes = ( nRes << nBitsCount ) | (((ULONG)BYTESWAP(nDat))>>(8-nBitsCount)); + } + } + } + else + { + pSrc += ( nBitsPos >> 3 ); + nBitsPos &= 7; + nRes = (ULONG)((*pSrc)&(0xff>>nBitsPos)); + if ( nBitsCount <= 8 - nBitsPos ) + { + nRes >>= ( 8 - nBitsPos - nBitsCount ); + } + else + { + pSrc++; + nBitsCount -= 8 - nBitsPos; + while ( nBitsCount >= 8 ) + { + nRes = ( nRes << 8 ) | ((ULONG)*(pSrc++)); + nBitsCount -= 8; + } + if ( nBitsCount > 0 ) + nRes = ( nRes << nBitsCount ) | (((ULONG)*pSrc)>>(8-nBitsCount)); + } + } + return nRes; +} + +// --------------------------------------------------------------------------------- + +BOOL TIFFReader::ConvertScanline( ULONG nY ) +{ + UINT32 nRed, nGreen, nBlue, ns, nx, nVal, nByteCount; + BYTE nByteVal; + + if ( nDstBitsPerPixel == 24 ) + { + if ( nBitsPerSample == 8 && nSamplesPerPixel >= 3 && + nPlanes == 1 && nPhotometricInterpretation == 2 ) + { + BYTE* pt = pMap[ 0 ]; + + // sind die Werte als Differenz abgelegt? + if ( 2 == nPredictor ) + { + BYTE nLRed = 0; + BYTE nLGreen = 0; + BYTE nLBlue = 0; + for ( nx = 0; nx < nImageWidth; nx++, pt += nSamplesPerPixel ) + { + nLRed = nLRed + pt[ 0 ]; + nLGreen = nLGreen + pt[ 1 ]; + nLBlue = nLBlue + pt[ 2 ]; + pAcc->SetPixel( nY, nx, Color( nLRed, nLGreen, nLBlue ) ); + } + } + else + { + for ( nx = 0; nx < nImageWidth; nx++, pt += nSamplesPerPixel ) + { + pAcc->SetPixel( nY, nx, Color( pt[0], pt[1], pt[2] ) ); + } + } + } + else if ( nPhotometricInterpretation == 2 && nSamplesPerPixel >= 3 ) + { + ULONG nMinMax = nMinSampleValue * 255 / ( nMaxSampleValue - nMinSampleValue ); + for ( nx = 0; nx < nImageWidth; nx++ ) + { + if ( nPlanes < 3 ) + { + nRed = GetBits( pMap[ 0 ], ( nx * nSamplesPerPixel + 0 ) * nBitsPerSample, nBitsPerSample ); + nGreen = GetBits( pMap[ 1 ], ( nx * nSamplesPerPixel + 1 ) * nBitsPerSample, nBitsPerSample ); + nBlue = GetBits( pMap[ 2 ], ( nx * nSamplesPerPixel + 2 ) * nBitsPerSample, nBitsPerSample ); + } + else + { + nRed = GetBits( pMap[ 0 ], nx * nBitsPerSample, nBitsPerSample ); + nGreen = GetBits( pMap[ 1 ], nx * nBitsPerSample, nBitsPerSample ); + nBlue = GetBits( pMap[ 2 ], nx * nBitsPerSample, nBitsPerSample ); + } + pAcc->SetPixel( nY, nx, Color( (BYTE)( nRed - nMinMax ), (BYTE)( nGreen - nMinMax ), (BYTE)(nBlue - nMinMax) ) ); + } + } + else if ( nPhotometricInterpretation == 5 && nSamplesPerPixel == 3 ) + { + ULONG nMinMax = nMinSampleValue * 255 / ( nMaxSampleValue - nMinSampleValue ); + for ( nx = 0; nx < nImageWidth; nx++ ) + { + if ( nPlanes < 3 ) + { + nRed = GetBits( pMap[ 0 ],( nx * nSamplesPerPixel + 0 ) * nBitsPerSample, nBitsPerSample ); + nGreen = GetBits( pMap[ 0 ],( nx * nSamplesPerPixel + 1 ) * nBitsPerSample, nBitsPerSample ); + nBlue = GetBits( pMap[ 0 ],( nx * nSamplesPerPixel + 2 ) * nBitsPerSample, nBitsPerSample ); + } + else + { + nRed = GetBits( pMap[ 0 ], nx * nBitsPerSample, nBitsPerSample ); + nGreen = GetBits( pMap[ 1 ], nx * nBitsPerSample, nBitsPerSample ); + nBlue = GetBits( pMap[ 2 ], nx * nBitsPerSample, nBitsPerSample ); + } + nRed = 255 - (BYTE)( nRed - nMinMax ); + nGreen = 255 - (BYTE)( nGreen - nMinMax ); + nBlue = 255 - (BYTE)( nBlue - nMinMax ); + pAcc->SetPixel( nY, nx, Color( (BYTE) nRed, (BYTE) nGreen, (BYTE) nBlue ) ); + } + } + else if( nPhotometricInterpretation == 5 && nSamplesPerPixel == 4 ) + { + BYTE nSamp[ 4 ]; + BYTE nSampLast[ 4 ] = { 0, 0, 0, 0 }; + long nBlack; + + for( nx = 0; nx < nImageWidth; nx++ ) + { + // sind die Werte als Differenz abgelegt? + if( 2 == nPredictor ) + { + for( ns = 0; ns < 4; ns++ ) + { + if( nPlanes < 3 ) + nSampLast[ ns ] = nSampLast[ ns ] + (BYTE) GetBits( pMap[ 0 ], ( nx * nSamplesPerPixel + ns ) * nBitsPerSample, nBitsPerSample ); + else + nSampLast[ ns ] = nSampLast[ ns ] + (BYTE) GetBits( pMap[ ns ], nx * nBitsPerSample, nBitsPerSample ); + nSamp[ ns ] = nSampLast[ ns ]; + } + } + else + { + for( ns = 0; ns < 4; ns++ ) + { + if( nPlanes < 3 ) + nSamp[ ns ] = (BYTE) GetBits( pMap[ 0 ], ( nx * nSamplesPerPixel + ns ) * nBitsPerSample, nBitsPerSample ); + else + nSamp[ ns ]= (BYTE) GetBits( pMap[ ns ], nx * nBitsPerSample, nBitsPerSample ); + } + } + nBlack = nSamp[ 3 ]; + nRed = (BYTE) Max( 0L, 255L - ( ( (long) nSamp[ 0 ] + nBlack - ( ( (long) nMinSampleValue ) << 1 ) ) * + 255L/(long)(nMaxSampleValue-nMinSampleValue) ) ); + nGreen = (BYTE) Max( 0L, 255L - ( ( (long) nSamp[ 1 ] + nBlack - ( ( (long) nMinSampleValue ) << 1 ) ) * + 255L/(long)(nMaxSampleValue-nMinSampleValue) ) ); + nBlue = (BYTE) Max( 0L, 255L - ( ( (long) nSamp[ 2 ] + nBlack - ( ( (long) nMinSampleValue ) << 1 ) ) * + 255L/(long)(nMaxSampleValue-nMinSampleValue) ) ); + pAcc->SetPixel( nY, nx, Color ( (BYTE)nRed, (BYTE)nGreen, (BYTE)nBlue ) ); + + } + } + } + else if ( nSamplesPerPixel == 1 && ( nPhotometricInterpretation <= 1 || nPhotometricInterpretation == 3 ) ) + { + ULONG nMinMax = ( ( 1 << nDstBitsPerPixel ) - 1 ) / ( nMaxSampleValue - nMinSampleValue ); + BYTE* pt = pMap[ 0 ]; + BYTE nShift; + + switch ( nDstBitsPerPixel ) + { + case 8 : + { + BYTE nLast; + if ( bByteSwap ) + { + if ( nPredictor == 2 ) + { + nLast = BYTESWAP( (BYTE)*pt++ ); + for ( nx = 0; nx < nImageWidth; nx++ ) + { + pAcc->SetPixel( nY, nx, nLast ); + nLast = nLast + *pt++; + } + } + else + { + for ( nx = 0; nx < nImageWidth; nx++ ) + { + nLast = *pt++; + pAcc->SetPixel( nY, nx, (BYTE)( ( (BYTESWAP((ULONG)nLast ) - nMinSampleValue ) * nMinMax ) ) ); + } + } + } + else + { + if ( nPredictor == 2 ) + { + nLast = *pt++; + for ( nx = 0; nx < nImageWidth; nx++ ) + { + pAcc->SetPixel( nY, nx, nLast ); + nLast = nLast + *pt++; + } + } + else + { + for ( nx = 0; nx < nImageWidth; nx++ ) + { + pAcc->SetPixel( nY, nx, (BYTE)( ( (ULONG)*pt++ - nMinSampleValue ) * nMinMax ) ); + + } + } + } + } + break; + + case 7 : + case 6 : + case 5 : + case 4 : + case 3 : + case 2 : + { + for ( nx = 0; nx < nImageWidth; nx++ ) + { + nVal = ( GetBits( pt, nx * nBitsPerSample, nBitsPerSample ) - nMinSampleValue ) * nMinMax; + pAcc->SetPixel( nY, nx, (BYTE)nVal ); + } + } + break; + + case 1 : + { + if ( bByteSwap ) + { + nx = 0; + nByteCount = ( nImageWidth >> 3 ) + 1; + while ( --nByteCount ) + { + nByteVal = *pt++; + pAcc->SetPixel( nY, nx++, nByteVal & 1 ); + nByteVal >>= 1; + pAcc->SetPixel( nY, nx++, nByteVal & 1 ); + nByteVal >>= 1; + pAcc->SetPixel( nY, nx++, nByteVal & 1 ); + nByteVal >>= 1; + pAcc->SetPixel( nY, nx++, nByteVal & 1 ); + nByteVal >>= 1; + pAcc->SetPixel( nY, nx++, nByteVal & 1 ); + nByteVal >>= 1; + pAcc->SetPixel( nY, nx++, nByteVal & 1 ); + nByteVal >>= 1; + pAcc->SetPixel( nY, nx++, nByteVal & 1 ); + nByteVal >>= 1; + pAcc->SetPixel( nY, nx++, nByteVal ); + } + if ( nImageWidth & 7 ) + { + nByteVal = *pt++; + while ( nx < nImageWidth ) + { + pAcc->SetPixel( nY, nx++, nByteVal & 1 ); + nByteVal >>= 1; + } + } + } + else + { + nx = 7; + nByteCount = ( nImageWidth >> 3 ) + 1; + while ( --nByteCount ) + { + nByteVal = *pt++; + pAcc->SetPixel( nY, nx, nByteVal & 1 ); + nByteVal >>= 1; + pAcc->SetPixel( nY, --nx, nByteVal & 1 ); + nByteVal >>= 1; + pAcc->SetPixel( nY, --nx, nByteVal & 1 ); + nByteVal >>= 1; + pAcc->SetPixel( nY, --nx, nByteVal & 1 ); + nByteVal >>= 1; + pAcc->SetPixel( nY, --nx, nByteVal & 1 ); + nByteVal >>= 1; + pAcc->SetPixel( nY, --nx, nByteVal & 1 ); + nByteVal >>= 1; + pAcc->SetPixel( nY, --nx, nByteVal & 1 ); + nByteVal >>= 1; + pAcc->SetPixel( nY, --nx, nByteVal ); + nx += 15; + } + if ( nImageWidth & 7 ) + { + nx -= 7; + nByteVal = *pt++; + nShift = 7; + while ( nx < nImageWidth ) + { + pAcc->SetPixel( nY, nx++, ( nByteVal >> nShift ) & 1); + } + } + } + } + break; + + default : + return FALSE; + } + } + else if ( ( nSamplesPerPixel == 2 ) && ( nBitsPerSample == 8 ) && + ( nPlanarConfiguration == 1 ) && ( pColorMap == 0 ) ) // grayscale + { + ULONG nMinMax = ( ( 1 << 8 /*nDstBitsPerPixel*/ ) - 1 ) / ( nMaxSampleValue - nMinSampleValue ); + BYTE* pt = pMap[ 0 ]; + if ( nByte1 == 'I' ) + pt++; + for ( nx = 0; nx < nImageWidth; nx++, pt += 2 ) + { + pAcc->SetPixel( nY, nx, (BYTE)( ( (ULONG)*pt - nMinSampleValue ) * nMinMax ) ); + } + } + else + return FALSE; + return TRUE; +} + +// --------------------------------------------------------------------------------- + +void TIFFReader::MakePalCol( void ) +{ + if ( nDstBitsPerPixel <= 8 ) + { + ULONG i, nVal, n0RGB; + if ( pColorMap == NULL ) + pColorMap = new ULONG[ 256 ]; + if ( nPhotometricInterpretation <= 1 ) + { + nNumColors = 1 << nBitsPerSample; + if ( nNumColors > 256 ) + nNumColors = 256; + pAcc->SetPaletteEntryCount( (USHORT)nNumColors ); + for ( i = 0; i < nNumColors; i++ ) + { + nVal = ( i * 255 / ( nNumColors - 1 ) ) & 0xff; + n0RGB = nVal | ( nVal << 8 ) | ( nVal << 16 ); + if ( nPhotometricInterpretation == 1 ) + pColorMap[ i ] = n0RGB; + else + pColorMap[ nNumColors - i - 1 ] = n0RGB; + } + } + for ( i = 0; i < nNumColors; i++ ) + { + pAcc->SetPaletteColor( (USHORT)i, BitmapColor( (BYTE)( pColorMap[ i ] >> 16 ), + (BYTE)( pColorMap[ i ] >> 8 ), (BYTE)pColorMap[ i ] ) ); + } + } + + if ( fXResolution > 1.0 && fYResolution > 1.0 && ( nResolutionUnit == 2 || nResolutionUnit == 3 ) ) + { + ULONG nRX,nRY; + if (nResolutionUnit==2) + { + nRX=(ULONG)(fXResolution+0.5); + nRY=(ULONG)(fYResolution+0.5); + } + else + { + nRX=(ULONG)(fXResolution*2.54+0.5); + nRY=(ULONG)(fYResolution*2.54+0.5); + } + MapMode aMapMode(MAP_INCH,Point(0,0),Fraction(1,nRX),Fraction(1,nRY)); + aBitmap.SetPrefMapMode(aMapMode); + aBitmap.SetPrefSize(Size(nImageWidth,nImageLength)); + } +} + +// --------------------------------------------------------------------------------- + +void TIFFReader::ReadHeader() +{ + BYTE nbyte1, nbyte2; + USHORT nushort; + + *pTIFF >> nbyte1; + if ( nbyte1 == 'I' ) + pTIFF->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); + else + pTIFF->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN ); + + *pTIFF >> nbyte2 >> nushort; + if ( nbyte1 != nbyte2 || ( nbyte1 != 'I' && nbyte1 != 'M' ) || nushort != 0x002a ) + bStatus = FALSE; +} + +// --------------------------------------------------------------------------------- + +BOOL TIFFReader::ReadTIFF(SvStream & rTIFF, Graphic & rGraphic ) +{ + USHORT i, nNumTags, nTagType; + ULONG nMaxPos; + ULONG nPos; + sal_uInt32 nFirstIfd, nDataLen; + + bStatus = TRUE; + nLastPercent = 0; + + pTIFF = &rTIFF; + nMaxPos = nOrigPos = pTIFF->Tell(); + nOrigNumberFormat = pTIFF->GetNumberFormatInt(); + + MayCallback( 0 ); + + // Kopf einlesen: + ReadHeader(); + + // Ersten IFD einlesen: + *pTIFF >> nFirstIfd; + + if( !nFirstIfd || pTIFF->GetError() ) + bStatus = FALSE; + + if ( bStatus ) + { + sal_uInt32 nOffset = nFirstIfd; + + // calculate length of TIFF file + do + { + pTIFF->Seek( nOrigPos + nOffset ); + + if( pTIFF->GetError() ) + { + pTIFF->ResetError(); + break; + }; + nMaxPos = Max( pTIFF->Tell(), nMaxPos ); + + *pTIFF >> nNumTags; + + // Schleife ueber Tags: + for( i = 0; i < nNumTags; i++ ) + { + *pTIFF >> nTagType >> nDataType >> nDataLen >> nOffset; + + if( DataTypeSize() * nDataLen > 4 ) + nMaxPos = Max( nOrigPos + nOffset + DataTypeSize() * nDataLen, nMaxPos ); + } + *pTIFF >> nOffset; + if ( pTIFF->IsEof() ) + nOffset = 0; + + nMaxPos = Max( pTIFF->Tell(), nMaxPos ); + if ( !nOffset ) + nMaxPos = Max( pTIFF->Tell(), nMaxPos ); + } + while( nOffset ); + + for ( UINT32 nNextIfd = nFirstIfd; nNextIfd && bStatus; ) + { + pTIFF->Seek( nOrigPos + nNextIfd ); + { + bByteSwap = FALSE; + + nNewSubFile = 0; + nSubFile = 0; + nImageWidth = 0; + nImageLength = 0; + nBitsPerSample = 1; // Defaultwert laut Doku + nCompression = 1; + nPhotometricInterpretation = 0; + nThresholding = 1; // Defaultwert laut Doku + nCellWidth = 1; + nCellLength = 1; + nFillOrder = 1; // Defaultwert laut Doku + nNumStripOffsets = 0; + nOrientation = 1; + nSamplesPerPixel = 1; // Defaultwert laut Doku + nRowsPerStrip = 0xffffffff; // Defaultwert laut Doku + nNumStripByteCounts = 0; + nMinSampleValue = 0; // Defaultwert laut Doku + nMaxSampleValue = 0; + fXResolution = 0.0; + fYResolution = 0.0; + nPlanarConfiguration = 1; + nGroup3Options = 0; // Defaultwert laut Doku + nGroup4Options = 0; // Defaultwert laut Doku + nResolutionUnit = 2; // Defaultwert laut Doku + nPredictor = 1; + nNumColors = 0; + + pAcc = NULL; + pColorMap = NULL; + pStripOffsets = NULL; + pStripByteCounts = NULL; + pMap[ 0 ] = pMap[ 1 ] = pMap[ 2 ] = pMap[ 3 ] = NULL; + + *pTIFF >> nNumTags; + nPos = pTIFF->Tell(); + + // Schleife ueber Tags: + for( i = 0; i < nNumTags; i++ ) + { + *pTIFF >> nTagType >> nDataType >> nDataLen; + + if( DataTypeSize() * nDataLen > 4 ) + { + *pTIFF >> nOffset; + pTIFF->Seek( nOrigPos + nOffset ); + } + ReadTagData( nTagType, nDataLen ); + nPos += 12; pTIFF->Seek( nPos ); + + if ( pTIFF->GetError() ) + bStatus = FALSE; + + if ( bStatus == FALSE ) + break; + } + *pTIFF >> nNextIfd; + if ( pTIFF->IsEof() ) + nNextIfd = 0; + } + if ( bStatus ) + { + if ( nMaxSampleValue == 0 ) + nMaxSampleValue = ( 1 << nBitsPerSample ) - 1; + + if ( nPhotometricInterpretation == 2 || nPhotometricInterpretation == 5 || nPhotometricInterpretation == 6 ) + nDstBitsPerPixel = 24; + else if ( nBitsPerSample*nSamplesPerPixel <= 1 ) + nDstBitsPerPixel = 1; + else if ( nBitsPerSample*nSamplesPerPixel <= 4 ) + nDstBitsPerPixel = 4; + else + nDstBitsPerPixel = 8; + + aBitmap = Bitmap( Size( nImageWidth, nImageLength ), nDstBitsPerPixel ); + pAcc = aBitmap.AcquireWriteAccess(); + if ( pAcc ) + { + if ( nPlanarConfiguration == 1 ) + nPlanes = 1; + else + nPlanes = nSamplesPerPixel; + + if ( ( nFillOrder == 2 ) && ( nCompression != 5 ) ) // im LZW Mode werden die bits schon invertiert + bByteSwap = TRUE; + + nStripsPerPlane = ( nImageLength - 1 ) / nRowsPerStrip + 1; + nBytesPerRow = ( nImageWidth * nSamplesPerPixel / nPlanes * nBitsPerSample + 7 ) >> 3; + + for ( ULONG j = 0; j < 4; j++ ) + { + try + { + pMap[ j ] = new BYTE[ nBytesPerRow ]; + } + catch (std::bad_alloc) + { + pMap[ j ] = NULL; + bStatus = FALSE; + break; + } + } + + if ( bStatus && ReadMap( 10, 60 ) ) + { + nMaxPos = Max( pTIFF->Tell(), nMaxPos ); + MakePalCol(); + nMaxPos = Max( pTIFF->Tell(), nMaxPos ); + } + else + bStatus = FALSE; + + if( pAcc ) + { + aBitmap.ReleaseAccess( pAcc ); + if ( bStatus ) + { + AnimationBitmap aAnimationBitmap( aBitmap, Point( 0, 0 ), aBitmap.GetSizePixel(), + ANIMATION_TIMEOUT_ON_CLICK, DISPOSE_BACK ); + + aAnimation.Insert( aAnimationBitmap ); + } + } + // Aufraeumen: + for ( i = 0; i < 4; i++ ) + delete[] pMap[ i ]; + + delete[] pColorMap; + delete[] pStripOffsets; + delete[] pStripByteCounts; + } + } + } + } + + // seek to end of TIFF if succeeded + pTIFF->SetNumberFormatInt( nOrigNumberFormat ); + pTIFF->Seek( bStatus ? nMaxPos : nOrigPos ); + + if ( aAnimation.Count() ) + { + if ( aAnimation.Count() == 1 ) + rGraphic = aAnimation.GetBitmapEx(); + else + rGraphic = aAnimation; //aBitmap; + + return TRUE; + } + else + return FALSE; +} + + +//================== GraphicImport - die exportierte Funktion ================ + +extern "C" BOOL __LOADONCALLAPI GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, BOOL ) +{ + TIFFReader aTIFFReader; + + if ( aTIFFReader.ReadTIFF( rStream, rGraphic ) == FALSE ) + return FALSE; + + return TRUE; +} + +//============================= fuer Windows ================================== +#ifndef GCC +#endif + +#ifdef WIN + +static HINSTANCE hDLLInst = 0; // HANDLE der DLL + +extern "C" int CALLBACK LibMain( HINSTANCE hDLL, WORD, WORD nHeap, LPSTR ) +{ +#ifndef WNT + if ( nHeap ) + UnlockData( 0 ); +#endif + + hDLLInst = hDLL; + + return TRUE; +} + +extern "C" int CALLBACK WEP( int ) +{ + return 1; +} + +#endif + + diff --git a/filter/source/graphicfilter/itiff/lzwdecom.cxx b/filter/source/graphicfilter/itiff/lzwdecom.cxx new file mode 100644 index 000000000000..9460ed6ecf45 --- /dev/null +++ b/filter/source/graphicfilter/itiff/lzwdecom.cxx @@ -0,0 +1,192 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_filter.hxx" + +#include "lzwdecom.hxx" + +LZWDecompressor::LZWDecompressor() +{ + USHORT i; + + pTable=new LZWTableEntry[4096]; + pOutBuf=new BYTE[4096]; + for (i=0; i<4096; i++) + { + pTable[i].nPrevCode=0; + pTable[i].nDataCount=1; + pTable[i].nData=(BYTE)i; + } + pIStream=NULL; + bFirst = TRUE; + nOldCode = 0; +} + + +LZWDecompressor::~LZWDecompressor() +{ + delete[] pOutBuf; + delete[] pTable; +} + + +void LZWDecompressor::StartDecompression(SvStream & rIStream) +{ + pIStream=&rIStream; + + nTableSize=258; + + bEOIFound=FALSE; + + nOutBufDataLen=0; + + *pIStream >> nInputBitsBuf; + + nInputBitsBufSize=8; + + if ( bFirst ) + { + bInvert = nInputBitsBuf == 1; + bFirst = FALSE; + } + + if ( bInvert ) + nInputBitsBuf = ( ( nInputBitsBuf & 1 ) << 7 ) | ( ( nInputBitsBuf & 2 ) << 5 ) | ( ( nInputBitsBuf & 4 ) << 3 ) | ( ( nInputBitsBuf & 8 ) << 1 ) | ( ( nInputBitsBuf & 16 ) >> 1 ) | ( ( nInputBitsBuf & 32 ) >> 3 ) | ( ( nInputBitsBuf & 64 ) >> 5 ) | ( (nInputBitsBuf & 128 ) >> 7 ); +} + + +ULONG LZWDecompressor::Decompress(BYTE * pTarget, ULONG nMaxCount) +{ + ULONG nCount; + + if (pIStream==NULL) return 0; + + nCount=0; + for (;;) { + + if (pIStream->GetError()) break; + + if (((ULONG)nOutBufDataLen)>=nMaxCount) { + nOutBufDataLen = nOutBufDataLen - (USHORT)nMaxCount; + nCount+=nMaxCount; + while (nMaxCount>0) { + *(pTarget++)=*(pOutBufData++); + nMaxCount--; + } + break; + } + + nMaxCount-=(ULONG)nOutBufDataLen; + nCount+=nOutBufDataLen; + while (nOutBufDataLen>0) { + *(pTarget++)=*(pOutBufData++); + nOutBufDataLen--; + } + + if (bEOIFound==TRUE) break; + + DecompressSome(); + + } + + return nCount; +} + + +USHORT LZWDecompressor::GetNextCode() +{ + USHORT nBits,nCode; + + if (nTableSize<511) nBits=9; + else if (nTableSize<1023) nBits=10; + else if (nTableSize<2047) nBits=11; + else nBits=12; + + nCode=0; + do { + if (nInputBitsBufSize<=nBits) + { + nCode=(nCode<<nInputBitsBufSize) | nInputBitsBuf; + nBits = nBits - nInputBitsBufSize; + *pIStream >> nInputBitsBuf; + if ( bInvert ) + nInputBitsBuf = ( ( nInputBitsBuf & 1 ) << 7 ) | ( ( nInputBitsBuf & 2 ) << 5 ) | ( ( nInputBitsBuf & 4 ) << 3 ) | ( ( nInputBitsBuf & 8 ) << 1 ) | ( ( nInputBitsBuf & 16 ) >> 1 ) | ( ( nInputBitsBuf & 32 ) >> 3 ) | ( ( nInputBitsBuf & 64 ) >> 5 ) | ( (nInputBitsBuf & 128 ) >> 7 ); + nInputBitsBufSize=8; + } + else + { + nCode=(nCode<<nBits) | (nInputBitsBuf>>(nInputBitsBufSize-nBits)); + nInputBitsBufSize = nInputBitsBufSize - nBits; + nInputBitsBuf&=0x00ff>>(8-nInputBitsBufSize); + nBits=0; + } + } while (nBits>0); + + return nCode; +} + + +void LZWDecompressor::AddToTable(USHORT nPrevCode, USHORT nCodeFirstData) +{ + while (pTable[nCodeFirstData].nDataCount>1) + nCodeFirstData=pTable[nCodeFirstData].nPrevCode; + + pTable[nTableSize].nPrevCode=nPrevCode; + pTable[nTableSize].nDataCount=pTable[nPrevCode].nDataCount+1; + pTable[nTableSize].nData=pTable[nCodeFirstData].nData; + + nTableSize++; +} + + +void LZWDecompressor::DecompressSome() +{ + USHORT i,nCode; + + nCode=GetNextCode(); + if (nCode==256) { + nTableSize=258; + nCode=GetNextCode(); + if (nCode==257) { bEOIFound=TRUE; return; } + } + else if (nCode<nTableSize) AddToTable(nOldCode,nCode); + else if (nCode==nTableSize) AddToTable(nOldCode,nOldCode); + else { bEOIFound=TRUE; return; } + + nOldCode=nCode; + + nOutBufDataLen=pTable[nCode].nDataCount; + pOutBufData=pOutBuf+nOutBufDataLen; + for (i=0; i<nOutBufDataLen; i++) { + *(--pOutBufData)=pTable[nCode].nData; + nCode=pTable[nCode].nPrevCode; + } +} + + + diff --git a/filter/source/graphicfilter/itiff/lzwdecom.hxx b/filter/source/graphicfilter/itiff/lzwdecom.hxx new file mode 100644 index 000000000000..164812878865 --- /dev/null +++ b/filter/source/graphicfilter/itiff/lzwdecom.hxx @@ -0,0 +1,79 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _LZWDECOM_HXX +#define _LZWDECOM_HXX + +#include <tools/stream.hxx> + +struct LZWTableEntry { + USHORT nPrevCode; + USHORT nDataCount; + BYTE nData; +}; + +class LZWDecompressor { + +public: + + LZWDecompressor(); + ~LZWDecompressor(); + + void StartDecompression(SvStream & rIStream); + + ULONG Decompress(BYTE * pTarget, ULONG nMaxCount); + // Liefert die Anzahl der geschriebenen Bytes, wenn < nMaxCount, + // sind keine weiteren Daten zu entpacken, oder es ist ein + // Fehler aufgetreten. + +private: + + USHORT GetNextCode(); + void AddToTable(USHORT nPrevCode, USHORT nCodeFirstData); + void DecompressSome(); + + SvStream * pIStream; + + LZWTableEntry * pTable; + USHORT nTableSize; + + BOOL bEOIFound, bInvert, bFirst; + + USHORT nOldCode; + + BYTE * pOutBuf; + BYTE * pOutBufData; + USHORT nOutBufDataLen; + + BYTE nInputBitsBuf; + USHORT nInputBitsBufSize; +}; + + +#endif + + diff --git a/filter/source/graphicfilter/itiff/makefile.mk b/filter/source/graphicfilter/itiff/makefile.mk new file mode 100644 index 000000000000..07fcf0ffdff4 --- /dev/null +++ b/filter/source/graphicfilter/itiff/makefile.mk @@ -0,0 +1,71 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=filter +TARGET=itiff +DEPTARGET=vitiff + +# --- Settings ----------------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Allgemein ---------------------------------------------------------- + +.IF "$(editdebug)"!="" || "$(EDITDEBUG)"!="" +CDEFS+= -DEDITDEBUG +.ENDIF +.IF "$(L10N_framework)"=="" +SLOFILES = $(SLO)$/itiff.obj \ + $(SLO)$/lzwdecom.obj \ + $(SLO)$/ccidecom.obj + +EXCEPTIONSNOOPTFILES= $(SLO)$/itiff.obj + +# ========================================================================== + +SHL1TARGET= iti$(DLLPOSTFIX) +SHL1IMPLIB= itiff +SHL1STDLIBS= $(VCLLIB) $(TOOLSLIB) $(SALLIB) +SHL1LIBS= $(SLB)$/itiff.lib # $(LB)$/rtftoken.lib + +.IF "$(GUI)" != "UNX" +.IF "$(COM)" != "GCC" +SHL1OBJS= $(SLO)$/itiff.obj +.ENDIF +.ENDIF + +SHL1VERSIONMAP=exports.map +SHL1DEF= $(MISC)$/$(SHL1TARGET).def + +DEF1NAME=$(SHL1TARGET) +.ENDIF + +# ========================================================================== + +.INCLUDE : target.mk |