Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Updated from cvs.

  • Loading branch information...
commit f05584f612f02ea44ac66b5dfa6ad61615c6f9db 1 parent 66efae0
Thomas Richter authored
26 README
@@ -126,3 +126,29 @@ the extension layer. For numbers smaller than 100, no extension layer is present
126 126 for numbers larger than 90, the base layer has quality 90 and the extension layer quality
127 127 q - 90, where q is the given quality.
128 128
  129 +-------------------------------------------------------------------------------------
  130 +
  131 +Release 0.6:
  132 +
  133 +Only minor modifications were made in this release. The Huffman coder now fills
  134 +undefined bits at the end of the entropy coded segment by ones, and potentially
  135 +inserts a stuffed zero byte. Note that the standard defines this only in an
  136 +informative note, so it is likely not required. The insertion of a stuffed zero
  137 +byte at this position might also be unnecessary as a parser should identify the
  138 +first 0xff byte ahead of the marker as "fill byte".
  139 +
  140 +Residual coding has been reworked and uses now a simple progressive scan with the
  141 +special DC case removed. The performance does not differ significantly, and it
  142 +makes integration into legacy software or hardware easier.
  143 +
  144 +Default Huffman tables are now also provided for progressive and lossless scans,
  145 +thus optimizing the Huffman tables just for these scan types is no longer
  146 +necessary. Residual or refinement scans still require this argument, though.
  147 +
  148 +Usage of the codec does not differ from previous releases, though codestreams
  149 +using the residual coding mode are not compatible to those generated by 0.5.
  150 +Note that this is still experimental software and the codestream might still
  151 +change until the ISO committee decides on the technology.
  152 +
  153 +Finally, a couple of workarounds for earlier releases of the g++ compiler have
  154 +been added.
26 README.history
@@ -58,3 +58,29 @@ software was unit-tested with the 10918-2 (JPEG part 2) test streams and various
58 58 bugs of the lossless predictive arithmetic coding and lossless predictive coding
59 59 were removed. New command line switches allow the encoding of pfm images (floating
60 60 point, for high-dynamic range) and the number of extension refinement scans.
  61 +
  62 +Revision 0.60
  63 +-----------------------------
  64 +
  65 +Only minor modifications were made in this release. The Huffman coder now fills
  66 +undefined bits at the end of the entropy coded segment by ones, and potentially
  67 +inserts a stuffed zero byte. Note that the standard defines this only in an
  68 +informative note, so it is likely not required. The insertion of a stuffed zero
  69 +byte at this position might also be unnecessary as a parser should identify the
  70 +first 0xff byte ahead of the marker as "fill byte".
  71 +
  72 +Residual coding has been reworked and uses now a simple progressive scan with the
  73 +special DC case removed. The performance does not differ significantly, and it
  74 +makes integration into legacy software or hardware easier.
  75 +
  76 +Default Huffman tables are now also provided for progressive and lossless scans,
  77 +thus optimizing the Huffman tables just for these scan types is no longer
  78 +necessary. Residual or refinement scans still require this argument, though.
  79 +
  80 +Usage of the codec does not differ from previous releases, though codestreams
  81 +using the residual coding mode are not compatible to those generated by 0.5.
  82 +Note that this is still experimental software and the codestream might still
  83 +change until the ISO committee decides on the technology.
  84 +
  85 +Finally, a couple of workarounds for earlier releases of the g++ compiler have
  86 +been added.
13 cmd/main.cpp
@@ -46,7 +46,7 @@ the committee itself.
46 46 /*
47 47 ** This header provides the main function.
48 48 **
49   -** $Id: main.cpp,v 1.80 2012-09-22 15:09:07 thor Exp $
  49 +** $Id: main.cpp,v 1.81 2012-10-11 12:54:03 thor Exp $
50 50 **
51 51 */
52 52
@@ -1182,11 +1182,12 @@ int main(int argc,char **argv)
1182 1182 " Note that the UBC software will not able to decode streams created by\n"
1183 1183 " this software due to a limitation of the UBC code - the streams are\n"
1184 1184 " nevertheless fully conforming.\n"
1185   - " Mode 3 is also available, but not a JPEG LS conforming profile.\n"
1186   - " It rather implements an experimental simple online compression for\n"
1187   - " a call from VESA. For -ls 3, the available bandwidth can be provided\n"
1188   - " with the -m command line argument. -m 100 specifies 100%% bandwidth,\n"
1189   - " i.e. all data is transmitted. -m 25 is a 1:4 compression at 25%% bandwidth.\n"
  1185 + " Modes 3 and 4 are also available, but not JPEG LS conforming profiles.\n"
  1186 + " They rather implement an experimental simple online compression for\n"
  1187 + " a call from VESA, either using a wavelet or a Hadamard transformation.\n"
  1188 + " For both modes, the available bandwidth must be provided with the -m\n"
  1189 + " command line argument. -m 100 specifies 100%% bandwidth, i.e. all \n"
  1190 + " data is transmitted. -m 25 is a 1:4 compression at 25%% bandwidth.\n"
1190 1191 "-cls : Use a JPEG LS part-2 conforming pseudo-RCT color transformation.\n"
1191 1192 " Note that this transformation is only CONFORMING TO 14495-2\n"
1192 1193 " AND NOT CONFORMING TO 10918-1. Works for near-lossless JPEG LS\n"
4 codestream/Makefile
... ... @@ -1,5 +1,5 @@
1 1 ##
2   -## $Id: Makefile,v 1.34 2012-09-23 12:58:39 thor Exp $
  2 +## $Id: Makefile,v 1.35 2012-09-28 17:05:21 thor Exp $
3 3 ##
4 4 ## Makefile for the jpeg transcoder project,
5 5 ## THOR Software, May 20, 2012, Thomas Richter
@@ -14,7 +14,7 @@ FILES = encoder decoder tables image entropyparser rectanglerequest \
14 14 refinementscan acrefinementscan \
15 15 hiddenrefinementscan \
16 16 jpeglsscan singlecomponentlsscan lineinterleavedlsscan \
17   - sampleinterleavedlsscan vesascan
  17 + sampleinterleavedlsscan vesascan vesadctscan
18 18
19 19 DIRNAME = codestream
20 20 SUPER = ../
7 codestream/entropyparser.cpp
@@ -48,7 +48,7 @@ the committee itself.
48 48 ** This class represents the interface for parsing the
49 49 ** entropy coded data in JPEG as part of a single scan.
50 50 **
51   -** $Id: entropyparser.cpp,v 1.13 2012-09-22 20:51:40 thor Exp $
  51 +** $Id: entropyparser.cpp,v 1.14 2012-09-26 20:19:59 thor Exp $
52 52 **
53 53 */
54 54
@@ -179,8 +179,9 @@ void EntropyParser::ParseRestartMarker(class ByteStream *io)
179 179 return;
180 180 } else {
181 181 // Some garbadge data, or a 0xff00. Just eat it up, and continue
182   - // scanning.
183   - io->GetWord();
  182 + // scanning. Note that a single Get is used here to eventually
  183 + // skip over a "fill byte".
  184 + io->Get();
184 185 }
185 186 }
186 187 } while(true);
4 codestream/hiddenrefinementscan.hpp
@@ -48,7 +48,7 @@ the committee itself.
48 48 ** data goes into a special APP9 marker. It works otherwise like any other
49 49 ** refinement scan.
50 50 **
51   -** $Id: hiddenrefinementscan.hpp,v 1.3 2012-09-23 12:58:39 thor Exp $
  51 +** $Id: hiddenrefinementscan.hpp,v 1.4 2012-09-28 10:53:49 thor Exp $
52 52 **
53 53 */
54 54
@@ -74,6 +74,8 @@ class ByteStream;
74 74 class Frame;
75 75 class MemoryStream;
76 76 class ByteStream;
  77 +class Scan;
  78 +class ResidualMarker;
77 79 ///
78 80
79 81 /// class RefinementScan
8 codestream/jpeglsscan.hpp
@@ -47,7 +47,7 @@ the committee itself.
47 47 ** A JPEG LS scan. This is the base for all JPEG LS scan types, namely
48 48 ** separate, line interleaved and sample interleaved.
49 49 **
50   -** $Id: jpeglsscan.hpp,v 1.18 2012-09-22 20:51:40 thor Exp $
  50 +** $Id: jpeglsscan.hpp,v 1.19 2012-09-27 20:33:06 thor Exp $
51 51 **
52 52 */
53 53
@@ -371,7 +371,8 @@ class JPEGLSScan : public EntropyParser {
371 371 {
372 372 UBYTE k;
373 373
374   - for(k = 0;(m_lN[context] << k) < m_lA[context] && k < 32;k++);
  374 + for(k = 0;(m_lN[context] << k) < m_lA[context] && k < 32;k++) {
  375 + }
375 376
376 377 if (k == 32) {
377 378 JPG_WARN(MALFORMED_STREAM,"JPEGLSScan::GolombParameter",
@@ -588,7 +589,8 @@ class JPEGLSScan : public EntropyParser {
588 589 temp = m_lA[0];
589 590 }
590 591
591   - for(k = 0;(m_lN[rtype] << k) < temp;k++);
  592 + for(k = 0;(m_lN[rtype] << k) < temp;k++) {
  593 + }
592 594
593 595 return k;
594 596 }
10 codestream/tables.cpp
@@ -47,7 +47,7 @@ the committee itself.
47 47 ** This class keeps all the coding tables, huffman, AC table, quantization
48 48 ** and other side information.
49 49 **
50   -** $Id: tables.cpp,v 1.55 2012-09-23 12:58:39 thor Exp $
  50 +** $Id: tables.cpp,v 1.56 2012-10-07 15:58:08 thor Exp $
51 51 **
52 52 */
53 53
@@ -675,14 +675,14 @@ void Tables::ParseTables(class ByteStream *io)
675 675
676 676 /// Tables::FindDCHuffmanTable
677 677 // Find the DC huffman table of the indicated index.
678   -class HuffmanTemplate *Tables::FindDCHuffmanTable(UBYTE idx) const
  678 +class HuffmanTemplate *Tables::FindDCHuffmanTable(UBYTE idx,ScanType type,UBYTE depth,UBYTE hidden,bool residual) const
679 679 {
680 680 class HuffmanTemplate *t;
681 681
682 682 if (m_pHuffman == NULL)
683 683 JPG_THROW(OBJECT_DOESNT_EXIST,"Tables::FindDCHuffmanTable","DHT marker missing for huffman encoded scan");
684 684
685   - t = m_pHuffman->DCTemplateOf(idx);
  685 + t = m_pHuffman->DCTemplateOf(idx,type,depth,hidden,residual);
686 686 if (t == NULL)
687 687 JPG_THROW(OBJECT_DOESNT_EXIST,"Tables::FindDCHuffmanTable","requested DC huffman coding table not defined");
688 688 return t;
@@ -691,14 +691,14 @@ class HuffmanTemplate *Tables::FindDCHuffmanTable(UBYTE idx) const
691 691
692 692 /// Tables::FindACHuffmanTable
693 693 // Find the AC huffman table of the indicated index.
694   -class HuffmanTemplate *Tables::FindACHuffmanTable(UBYTE idx) const
  694 +class HuffmanTemplate *Tables::FindACHuffmanTable(UBYTE idx,ScanType type,UBYTE depth,UBYTE hidden,bool residual) const
695 695 {
696 696 class HuffmanTemplate *t;
697 697
698 698 if (m_pHuffman == NULL)
699 699 JPG_THROW(OBJECT_DOESNT_EXIST,"Tables::FindACHuffmanTable","DHT marker missing for huffman encoded scan");
700 700
701   - t = m_pHuffman->ACTemplateOf(idx);
  701 + t = m_pHuffman->ACTemplateOf(idx,type,depth,hidden,residual);
702 702 if (t == NULL)
703 703 JPG_THROW(OBJECT_DOESNT_EXIST,"Tables::FindACHuffmanTable","requested AC huffman coding table not defined");
704 704 return t;
7 codestream/tables.hpp
@@ -47,7 +47,7 @@ the committee itself.
47 47 ** This class keeps all the coding tables, huffman, AC table, quantization
48 48 ** and other side information.
49 49 **
50   -** $Id: tables.hpp,v 1.30 2012-09-15 17:27:27 thor Exp $
  50 +** $Id: tables.hpp,v 1.31 2012-10-07 15:58:08 thor Exp $
51 51 **
52 52 */
53 53
@@ -57,6 +57,7 @@ the committee itself.
57 57 /// Include
58 58 #include "interface/types.hpp"
59 59 #include "tools/environment.hpp"
  60 +#include "marker/scantypes.hpp"
60 61 ///
61 62
62 63 /// Forwards
@@ -167,10 +168,10 @@ class Tables: public JKeeper {
167 168 void InstallDefaultTables(const struct JPG_TagItem *tags);
168 169 //
169 170 // Find the DC huffman table of the indicated index.
170   - class HuffmanTemplate *FindDCHuffmanTable(UBYTE idx) const;
  171 + class HuffmanTemplate *FindDCHuffmanTable(UBYTE idx,ScanType type,UBYTE depth,UBYTE hidden,bool residual) const;
171 172 //
172 173 // Find the AC huffman table of the indicated index.
173   - class HuffmanTemplate *FindACHuffmanTable(UBYTE idx) const;
  174 + class HuffmanTemplate *FindACHuffmanTable(UBYTE idx,ScanType type,UBYTE depth,UBYTE hidden,bool residual) const;
174 175 //
175 176 // Find the AC conditioner table for the indicated index
176 177 // and the DC band.
521 codestream/vesadctscan.cpp
... ... @@ -0,0 +1,521 @@
  1 +/*************************************************************************
  2 +** Copyright (c) 2011-2012 Accusoft **
  3 +** This program is free software, licensed under the GPLv3 **
  4 +** see README.license for details **
  5 +** **
  6 +** For obtaining other licenses, contact the author at **
  7 +** thor@math.tu-berlin.de **
  8 +** **
  9 +** Written by Thomas Richter (THOR Software) **
  10 +** Sponsored by Accusoft, Tampa, FL and **
  11 +** the Computing Center of the University of Stuttgart **
  12 +**************************************************************************
  13 +
  14 +This software is a complete implementation of ITU T.81 - ISO/IEC 10918,
  15 +also known as JPEG. It implements the standard in all its variations,
  16 +including lossless coding, hierarchical coding, arithmetic coding and
  17 +DNL, restart markers and 12bpp coding.
  18 +
  19 +In addition, it includes support for new proposed JPEG technologies that
  20 +are currently under discussion in the SC29/WG1 standardization group of
  21 +the ISO (also known as JPEG). These technologies include lossless coding
  22 +of JPEG backwards compatible to the DCT process, and various other
  23 +extensions.
  24 +
  25 +The author is a long-term member of the JPEG committee and it is hoped that
  26 +this implementation will trigger and facilitate the future development of
  27 +the JPEG standard, both for private use, industrial applications and within
  28 +the committee itself.
  29 +
  30 + Copyright (C) 2011-2012 Accusoft, Thomas Richter <thor@math.tu-berlin.de>
  31 +
  32 + This program is free software: you can redistribute it and/or modify
  33 + it under the terms of the GNU General Public License as published by
  34 + the Free Software Foundation, either version 3 of the License, or
  35 + (at your option) any later version.
  36 +
  37 + This program is distributed in the hope that it will be useful,
  38 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  39 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  40 + GNU General Public License for more details.
  41 +
  42 + You should have received a copy of the GNU General Public License
  43 + along with this program. If not, see <http://www.gnu.org/licenses/>.
  44 +
  45 +*************************************************************************/
  46 +/*
  47 +** A variant of JPEG LS for the proposed vesa compression. Experimental.
  48 +**
  49 +** $Id: vesadctscan.cpp,v 1.9 2012-10-06 17:50:42 thor Exp $
  50 +**
  51 +*/
  52 +
  53 +/// Includes
  54 +#include "codestream/jpeglsscan.hpp"
  55 +#include "codestream/vesadctscan.hpp"
  56 +///
  57 +
  58 +/// Scan pattern.
  59 +#define P(x,y) ((x) + ((y) << 2))
  60 +const int VesaDCTScan::Scan[16] = {
  61 + P(0,0),
  62 + P(1,0), P(0,1),
  63 + P(0,2), P(1,1), P(2,0),
  64 + P(3,0), P(2,1), P(1,2), P(0,3),
  65 + P(1,3), P(2,2), P(3,1),
  66 + P(3,2), P(2,3),
  67 + P(3,3)
  68 +};
  69 +#undef P
  70 +
  71 +const int VesaDCTScan::XPos[16] = {0,
  72 + 1,0,
  73 + 0,1,2,
  74 + 3,2,1,0,
  75 + 1,2,3,
  76 + 3,2,
  77 + 3};
  78 +
  79 +const int VesaDCTScan::YPos[16] = {0,
  80 + 0,1,
  81 + 2,1,0,
  82 + 0,1,2,3,
  83 + 3,2,1,
  84 + 2,3,
  85 + 3};
  86 +///
  87 +
  88 +/// VesaDCTScan::VesaDCTScan
  89 +// Create a new scan. This is only the base type.
  90 +VesaDCTScan::VesaDCTScan(class Frame *frame,class Scan *scan,
  91 + UBYTE near,const UBYTE *mapping,UBYTE point)
  92 + : JPEGLSScan(frame,scan,near,mapping,point)
  93 +{
  94 + memset(m_plBuffer,0,sizeof(m_plBuffer));
  95 + memset(m_plDC ,0,sizeof(m_plDC));
  96 +
  97 + /*
  98 + m_iTotal = 0; // total number of samples.
  99 + m_iSignificant = 0; // significance coding
  100 + m_iGetsSignificant = 0; // becomes significant
  101 + m_iDCGetsSignificant = 0; // DC value gets significant
  102 + m_iGetsSignificantAfterSignificance = 0; // Gets significant after a significant coefficient
  103 + m_iZeroTree = 0; // is start of a ZTree.
  104 + m_iZeroTreeAfterSignificance = 0; // is IZ after significant pixel.
  105 + m_iZeroTreeAfterDC = 0;
  106 + m_iIsolatedZero = 0; // is an isolated zero.
  107 + m_iIsolatedZeroAfterSignificance = 0; // is IZ after significant pixel.
  108 + m_iIsolatedZeroAfterDC = 0;
  109 + m_iDCStartsZeroTree = 0;
  110 + */
  111 +}
  112 +///
  113 +
  114 +/// VesaDCTScan::~VesaDCTScan
  115 +// Dispose a scan.
  116 +VesaDCTScan::~VesaDCTScan(void)
  117 +{
  118 + int i,j;
  119 +
  120 + for(i = 0;i < 4;i++) {
  121 + for(j = 0;j < 4;j++) {
  122 + if (m_plBuffer[i][j])
  123 + m_pEnviron->FreeMem(m_plBuffer[i][j],((m_ulWidth[i] + 3) & -4) * sizeof(LONG));
  124 + }
  125 + if (m_plDC[i])
  126 + m_pEnviron->FreeMem(m_plDC[i],((m_ulWidth[i] + 3) >> 2) * sizeof(LONG));
  127 + }
  128 +
  129 + /*
  130 + printf("Total symbols coded: %d\n",m_iTotal);
  131 + printf("Percentage of significant symbols: %g\n",m_iSignificant * 100.0 / m_iTotal);
  132 + printf("Percentage of symbols becoming significant: %g\n",m_iGetsSignificant * 100.0 / m_iTotal);
  133 + printf("Percentage of DC symbols becoming significant: %g\n",m_iDCGetsSignificant * 100.0 / m_iTotal);
  134 + printf("Percentage of symbols becomming significant behind significant symbols: %g\n",m_iGetsSignificantAfterSignificance * 100.0 / m_iTotal);
  135 + printf("Percentage of Zero tree coefficients: %g\n",m_iZeroTree * 100.0 / m_iTotal);
  136 + printf("Percentage of DC coefficients starting a ZT: %g\n",m_iDCStartsZeroTree * 100.0 / m_iTotal);
  137 + printf("Percentage of Zero tree coefficients behind significant symbols: %g\n",m_iZeroTreeAfterSignificance * 100.0 / m_iTotal);
  138 + printf("Percentage of zero tree coefficients behind significant DC symbols: %g\n",m_iZeroTreeAfterDC * 100.0 /m_iTotal);
  139 + printf("Percentage of isolated zeros: %g\n",m_iIsolatedZero * 100.0 / m_iTotal);
  140 + printf("Percentage of isolated zeros behind significant symbols: %g\n",m_iIsolatedZeroAfterSignificance * 100.0 / m_iTotal);
  141 + printf("Percentage of isolated zeros behind significant DC symbols: %g\n",m_iIsolatedZeroAfterDC * 100.0 / m_iTotal);
  142 + */
  143 +}
  144 +///
  145 +
  146 +
  147 +/// VesaDCTScan::FindComponentDimensions
  148 +// Collect component information and install the component dimensions.
  149 +// Also called (indirectly) to start writing or parsing a new scan.
  150 +void VesaDCTScan::FindComponentDimensions(void)
  151 +{
  152 + UBYTE cx;
  153 + ULONG y;
  154 +
  155 + JPEGLSScan::FindComponentDimensions();
  156 +
  157 + UBYTE preshift = m_ucLowBit + FractionalColorBitsOf();
  158 + LONG max = ((m_lMaxVal + 1) << preshift) - 1;
  159 +
  160 + if (m_ucCount > 4)
  161 + JPG_THROW(OVERFLOW_PARAMETER,"VesaDCTScan::FindComponentDimensions",
  162 + "Vesa DCT scan does not support more than four components");
  163 +
  164 + //
  165 + // Check that all MCU dimensions are 1.
  166 + for(cx = 0;cx < m_ucCount;cx++) {
  167 + class Component *comp = ComponentOf(cx);
  168 + if (comp->MCUHeightOf() != 1 || comp->MCUWidthOf() != 1)
  169 + JPG_THROW(INVALID_PARAMETER,"VesaDCTScan::FindComponentDimensions",
  170 + "sample interleaved JPEG LS does not support subsampling");
  171 + m_ucDepth[cx] = comp->PrecisionOf();
  172 + for(y = 0;y < 4;y++) {
  173 + m_plBuffer[cx][y] = (LONG *)m_pEnviron->AllocMem(((m_ulWidth[cx] + 3) & -4) * sizeof(LONG));
  174 + }
  175 + m_plDC[cx] = (LONG *)m_pEnviron->AllocMem(((m_ulWidth[cx] + 3) >> 2) * sizeof(LONG));
  176 + for(y = 0;y < m_ulWidth[cx];y += 4) {
  177 + m_plDC[cx][y >> 2] = DCNeutralValue(max + 1);
  178 + }
  179 + }
  180 +
  181 + m_ulSamplesPerLine = 0;
  182 + m_ulMaxOvershoot = 0;
  183 + m_ulUsedBits = 0;
  184 + for(cx = 0;cx < m_ucCount;cx++) {
  185 + m_ulSamplesPerLine += m_ulWidth[cx];
  186 + if (m_ulWidth[cx] << 1 > m_ulMaxOvershoot)
  187 + m_ulMaxOvershoot = m_ulWidth[cx] << 1;
  188 + }
  189 + m_ulBandwidth = (8 * m_lNear * m_ulSamplesPerLine * 4) / 100;
  190 + m_ulBitBudget = m_ulBandwidth;
  191 +}
  192 +///
  193 +
  194 +/// VesaDCTScan::UpdateDC
  195 +// Update the DC value to what the decoder would reconstruct.
  196 +// Bitlevel is the last bitplane that has been coded.
  197 +void VesaDCTScan::UpdateDC(UBYTE cx,UBYTE bitlevel)
  198 +{
  199 + LONG x;
  200 +
  201 + for(x = 0;x < LONG(m_ulWidth[cx]);x+=4) {
  202 + LONG v = m_plBuffer[cx][0][x];
  203 + // Mask out all bitplanes below the coded bitplane.
  204 + v &= ~((1 << bitlevel) - 1);
  205 + // Include the 0.5 reconstruction point if v is nonzero.
  206 + if (v & ValueMask) {
  207 + v |= (1 << bitlevel) >> 1;
  208 + }
  209 + if (v & Signed) {
  210 + m_plDC[cx][x >> 2] -= (v & ValueMask);
  211 + } else {
  212 + m_plDC[cx][x >> 2] += (v & ValueMask);
  213 + }
  214 + /*
  215 + if (cx == 0 && x == 0)
  216 + printf("%d %d\n",x,m_plDC[cx][x >> 2]);
  217 + */
  218 + }
  219 + /*
  220 + if (cx == 0)
  221 + printf("\n");
  222 + */
  223 +}
  224 +///
  225 +
  226 +/// VesaDCTScan::ParseMCU
  227 +// Parse a single MCU in this scan. Return true if there are more
  228 +// MCUs in this row.
  229 +bool VesaDCTScan::ParseMCU(void)
  230 +{
  231 + int lines = m_ulRemaining[0]; // total number of MCU lines processed.
  232 + bool second = false;
  233 + UBYTE cx;
  234 + UBYTE bits[4];
  235 + UBYTE maxbits;
  236 + int x,y;
  237 +
  238 + //
  239 + // A "MCU" in respect to the code organization is eight lines.
  240 + if (lines > 8) {
  241 + lines = 8;
  242 + }
  243 + m_ulRemaining[0] -= lines;
  244 + assert(lines > 0);
  245 + assert(m_ucCount < 4);
  246 +
  247 + lines = (lines + 3) & -4;
  248 +
  249 + do {
  250 + // Get the max bit counter from the stream.
  251 + UBYTE m = 0;
  252 + maxbits = 0;
  253 + for(cx = 0;cx < m_ucCount;cx++) {
  254 + m = 0;
  255 + while((m_Stream.Get<1>()))
  256 + m++;
  257 + bits[cx] = m;
  258 + if (m > maxbits)
  259 + maxbits = m;
  260 + //
  261 + // Clear the data.
  262 + for(y = 0;y < 4;y++) {
  263 + memset(m_plBuffer[cx][y],0,((m_ulWidth[cx] + 3) & (-4)) * sizeof(LONG));
  264 + }
  265 + }
  266 + //
  267 + // Receive the bits.
  268 + {
  269 + bool abort = false;
  270 + UBYTE bitlevel;
  271 + assert(m_ucCount < 4);
  272 + //
  273 + bitlevel = maxbits;
  274 + while(bitlevel && abort == false) {
  275 + ULONG level = 0; // Position within the DCT scan pattern.
  276 + for(cx = 0;cx < m_ucCount;cx++) {
  277 + for(y = 0;y < 4;y++) {
  278 + ClearEncodedFlags((ULONG *)(m_plBuffer[cx][y]),(m_ulWidth[cx] + 3) & -4);
  279 + }
  280 + }
  281 + bitlevel--;
  282 + do {
  283 + for(cx = 0;cx < m_ucCount;cx++) {
  284 + if (bitlevel < bits[cx]) {
  285 + // Enough data available?
  286 + if (m_ulUsedBits + (((m_ulWidth[cx] + 3) >> 2) << 2) >= m_ulBitBudget) {
  287 + abort = true;
  288 + break;
  289 + } else {
  290 + for(x = 0;x < LONG(m_ulWidth[cx]);x += 4) {
  291 + DecodeEZWLevel(cx,x,1UL << bitlevel,level);
  292 + //printf("%d:%d\n",x,m_ulUsedBits);
  293 + }
  294 + }
  295 + }
  296 + }
  297 + } while(abort == false && ++level < 16);
  298 + }
  299 + }
  300 + //
  301 + // Check how many bits are available for the next line.
  302 + if (m_ulUsedBits < m_ulBitBudget) {
  303 + m_ulBitBudget -= m_ulUsedBits;
  304 + } else {
  305 + m_ulBitBudget = 0;
  306 + }
  307 + m_ulBitBudget += m_ulBandwidth;
  308 + m_ulUsedBits = 0;
  309 + //
  310 + //
  311 + // Inverse transform the data.
  312 + for(cx = 0;cx < m_ucCount;cx++) {
  313 + struct Line *line = CurrentLine(cx);
  314 + //
  315 + // Convert from sign-magnitude to two's complement.
  316 + for(y = 0;y < 4;y++) {
  317 + for(x = 0;x < LONG((m_ulWidth[cx] + 3) & -4);x++) {
  318 + LONG &v = m_plBuffer[cx][y][x];
  319 + if (v & Signed) {
  320 + v = -(v & ValueMask);
  321 + } else {
  322 + v &= ValueMask;
  323 + }
  324 + }
  325 + }
  326 + //
  327 + for(x = 0;x < LONG(m_ulWidth[cx]);x+=4) {
  328 + // DC shift.
  329 + m_plBuffer[cx][0][x] += m_plDC[cx][x >> 2];
  330 + m_plDC[cx][x >> 2] = m_plBuffer[cx][0][x];
  331 + /*
  332 + if (cx == 0 && x == 0)
  333 + printf("%d %d\n",x,m_plDC[cx][x >> 2]);
  334 + */
  335 + BackwardDCT(m_plBuffer[cx][0]+x,m_plBuffer[cx][1]+x,
  336 + m_plBuffer[cx][2]+x,m_plBuffer[cx][3]+x);
  337 + }
  338 + /*
  339 + if (cx == 0)
  340 + printf("\n");
  341 + */
  342 + //
  343 + // Forward by four lines in the lower pair.
  344 + if (second) {
  345 + for(y = 0;y < 4;y++) {
  346 + if (line)
  347 + line = line->m_pNext;
  348 + }
  349 + }
  350 + //
  351 + // Copy the data out.
  352 + for(y = 0;y < 4;y++) {
  353 + if (line) {
  354 + memcpy(line->m_pData,m_plBuffer[cx][y],m_ulWidth[cx] * sizeof(LONG));
  355 + line = line->m_pNext;
  356 + }
  357 + }
  358 + }
  359 + //
  360 + // Go to the next line
  361 + lines -= 4;
  362 + second = true;
  363 + } while(lines);
  364 +
  365 + return false;
  366 +}
  367 +///
  368 +
  369 +/// VesaDCTScan::WriteMCU
  370 +// Write a single MCU in this scan.
  371 +bool VesaDCTScan::WriteMCU(void)
  372 +{
  373 + int lines = m_ulRemaining[0]; // total number of MCU lines processed.
  374 + bool second = false;
  375 + UBYTE cx;
  376 + UBYTE bits[4];
  377 + UBYTE maxbits;
  378 + int x,y;
  379 +
  380 + //
  381 + // A "MCU" in respect to the code organization is eight lines.
  382 + if (lines > 8) {
  383 + lines = 8;
  384 + }
  385 + m_ulRemaining[0] -= lines;
  386 + assert(lines > 0);
  387 + assert(m_ucCount < 4);
  388 +
  389 + lines = (lines + 3) & -4;
  390 +
  391 + do {
  392 + //
  393 + // Fill the line pointers.
  394 + for(cx = 0;cx < m_ucCount;cx++) {
  395 + struct Line *line = CurrentLine(cx);
  396 + if (second) {
  397 + for(y = 0;y < 4;y++) {
  398 + if (line->m_pNext)
  399 + line = line->m_pNext;
  400 + }
  401 + }
  402 + //
  403 + for(y = 0;y < 4;y++) {
  404 + LONG last;
  405 + memcpy(m_plBuffer[cx][y],line->m_pData,m_ulWidth[cx] * sizeof(LONG));
  406 + last = m_plBuffer[cx][y][m_ulWidth[cx] - 1];
  407 + switch(m_ulWidth[cx] & 3) {
  408 + case 1:
  409 + m_plBuffer[cx][y][m_ulWidth[cx]+2] = last;
  410 + case 2:
  411 + m_plBuffer[cx][y][m_ulWidth[cx]+1] = last;
  412 + case 3:
  413 + m_plBuffer[cx][y][m_ulWidth[cx]] = last;
  414 + case 0:
  415 + break;
  416 + }
  417 + if (line->m_pNext)
  418 + line = line->m_pNext;
  419 + }
  420 + for(x = 0;x < LONG(m_ulWidth[cx]);x+=4) {
  421 + ForwardDCT(m_plBuffer[cx][0]+x,m_plBuffer[cx][1]+x,
  422 + m_plBuffer[cx][2]+x,m_plBuffer[cx][3]+x);
  423 + // DC shift.
  424 + m_plBuffer[cx][0][x] -= m_plDC[cx][x >> 2];
  425 + }
  426 + }
  427 + //
  428 + // Find the maximum for each component and transmit.
  429 + maxbits = 0;
  430 + for(cx = 0;cx < m_ucCount;cx++) {
  431 + ULONG max = 0;
  432 + for(y = 0;y < 4;y++) {
  433 + for(x = 0;x < (LONG(m_ulWidth[cx] + 3) & -4);x++) {
  434 + LONG v = m_plBuffer[cx][y][x];
  435 + if (v < 0) {
  436 + v = -v;
  437 + m_plBuffer[cx][y][x] = v | Signed;
  438 + }
  439 + if (ULONG(v) > max) max = v;
  440 + }
  441 + }
  442 + bits[cx] = 0;
  443 + while(max) {
  444 + m_Stream.Put<1>(1);
  445 + max >>=1;
  446 + bits[cx]++;
  447 + if (bits[cx] > maxbits)
  448 + maxbits = bits[cx];
  449 + }
  450 + m_Stream.Put<1>(0);
  451 + }
  452 + //
  453 + // Transmit the bits.
  454 + {
  455 + bool abort = false;
  456 + UBYTE bitlevel;
  457 + assert(m_ucCount < 4);
  458 + //
  459 + bitlevel = maxbits;
  460 + while(bitlevel && abort == false) {
  461 + ULONG level = 0; // Position within the DCT scan pattern.
  462 + for(cx = 0;cx < m_ucCount;cx++) {
  463 + for(y = 0;y < 4;y++) {
  464 + ClearEncodedFlags((ULONG *)(m_plBuffer[cx][y]),(m_ulWidth[cx] + 3) & -4);
  465 + }
  466 + }
  467 + bitlevel--;
  468 + do {
  469 + for(cx = 0;cx < m_ucCount;cx++) {
  470 + if (bitlevel < bits[cx]) {
  471 + // Enough data available?
  472 + if (m_ulUsedBits + (((m_ulWidth[cx] + 3) >> 2) << 2) >= m_ulBitBudget) {
  473 + UBYTE c;
  474 + abort = true;
  475 + if (level) {
  476 + for(c = 0;c < m_ucCount;c++) {
  477 + UpdateDC(c,bitlevel);
  478 + }
  479 + } else {
  480 + for(c = 0;c < cx;c++) {
  481 + UpdateDC(c,bitlevel);
  482 + }
  483 + if (bitlevel + 1 < maxbits) {
  484 + for(c = cx;c < m_ucCount;c++) {
  485 + UpdateDC(c,bitlevel + 1);
  486 + }
  487 + }
  488 + }
  489 + break;
  490 + } else {
  491 + for(x = 0;x < LONG(m_ulWidth[cx]);x += 4) {
  492 + EncodeEZWLevel(cx,x,1UL << bitlevel,level);
  493 + //printf("%d:%d\n",x,m_ulUsedBits);
  494 + }
  495 + }
  496 + }
  497 + }
  498 + } while(abort == false && ++level < 16);
  499 + }
  500 + if (abort == false) {
  501 + for(cx = 0;cx < m_ucCount;cx++) {
  502 + UpdateDC(cx,0);
  503 + }
  504 + }
  505 + }
  506 + //
  507 + // Check how many bits are available for the next line.
  508 + if (m_ulUsedBits < m_ulBitBudget) {
  509 + m_ulBitBudget -= m_ulUsedBits;
  510 + } else {
  511 + m_ulBitBudget = 0;
  512 + }
  513 + m_ulBitBudget += m_ulBandwidth;
  514 + m_ulUsedBits = 0;
  515 + lines -= 4;
  516 + second = true;
  517 + } while(lines);
  518 +
  519 + return false;
  520 +}
  521 +///
350 codestream/vesadctscan.hpp
... ... @@ -0,0 +1,350 @@
  1 +/*************************************************************************
  2 +** Copyright (c) 2011-2012 Accusoft **
  3 +** This program is free software, licensed under the GPLv3 **
  4 +** see README.license for details **
  5 +** **
  6 +** For obtaining other licenses, contact the author at **
  7 +** thor@math.tu-berlin.de **
  8 +** **
  9 +** Written by Thomas Richter (THOR Software) **
  10 +** Sponsored by Accusoft, Tampa, FL and **
  11 +** the Computing Center of the University of Stuttgart **
  12 +**************************************************************************
  13 +
  14 +This software is a complete implementation of ITU T.81 - ISO/IEC 10918,
  15 +also known as JPEG. It implements the standard in all its variations,
  16 +including lossless coding, hierarchical coding, arithmetic coding and
  17 +DNL, restart markers and 12bpp coding.
  18 +
  19 +In addition, it includes support for new proposed JPEG technologies that
  20 +are currently under discussion in the SC29/WG1 standardization group of
  21 +the ISO (also known as JPEG). These technologies include lossless coding
  22 +of JPEG backwards compatible to the DCT process, and various other
  23 +extensions.
  24 +
  25 +The author is a long-term member of the JPEG committee and it is hoped that
  26 +this implementation will trigger and facilitate the future development of
  27 +the JPEG standard, both for private use, industrial applications and within
  28 +the committee itself.
  29 +
  30 + Copyright (C) 2011-2012 Accusoft, Thomas Richter <thor@math.tu-berlin.de>
  31 +
  32 + This program is free software: you can redistribute it and/or modify
  33 + it under the terms of the GNU General Public License as published by
  34 + the Free Software Foundation, either version 3 of the License, or
  35 + (at your option) any later version.
  36 +
  37 + This program is distributed in the hope that it will be useful,
  38 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  39 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  40 + GNU General Public License for more details.
  41 +
  42 + You should have received a copy of the GNU General Public License
  43 + along with this program. If not, see <http://www.gnu.org/licenses/>.
  44 +
  45 +*************************************************************************/
  46 +/*
  47 +** A variant of JPEG LS for the proposed vesa compression. Experimental.
  48 +**
  49 +** $Id: vesadctscan.hpp,v 1.7 2012-10-06 17:50:42 thor Exp $
  50 +**
  51 +*/
  52 +
  53 +#ifndef CODESTREAM_VESADCTSCAN_HPP
  54 +#define CODESTREAM_VESADCTSCAN_HPP
  55 +
  56 +/// Includes
  57 +#include "codestream/jpeglsscan.hpp"
  58 +///
  59 +
  60 +/// class VesaDCTScan
  61 +class VesaDCTScan : public JPEGLSScan {
  62 + //
  63 + // Bit precision of the components.
  64 + UBYTE m_ucDepth[4];
  65 + //
  66 + // Bit budget for a line.
  67 + ULONG m_ulBitBudget;
  68 + //
  69 + // Actually used number of bits per line.
  70 + ULONG m_ulUsedBits;
  71 + //
  72 + // Maximum number of bits an encoded line may generate
  73 + ULONG m_ulMaxOvershoot;
  74 + //
  75 + // Total number of samplesper line.
  76 + ULONG m_ulSamplesPerLine;
  77 + //
  78 + // Available bandwidth in average bits per line.
  79 + ULONG m_ulBandwidth;
  80 + //
  81 + // Lines - need to buffer four of them.
  82 + LONG *m_plBuffer[4][4];
  83 + //
  84 + // The DCT buffer for prediction.
  85 + LONG *m_plDC[4];
  86 + //
  87 + // Scan pattern.
  88 + static const int Scan[16];
  89 + //
  90 + static const int XPos[16],YPos[16];
  91 + //
  92 + // Masks for the EZW-encoding.
  93 + enum {
  94 + Signed = (1UL << 31),
  95 + Significant = (1UL << 30),
  96 + Encoded = (1UL << 29),
  97 + ValueMask = (1UL << 29) - 1
  98 + };
  99 + //
  100 + /*
  101 + // Relative frequencies
  102 + int m_iTotal; // total number of samples.
  103 + int m_iSignificant; // significance coding
  104 + int m_iGetsSignificant; // becomes significant
  105 + int m_iDCGetsSignificant; // DC value gets significant
  106 + int m_iGetsSignificantAfterSignificance; // Gets significant after a significant coefficient
  107 + int m_iZeroTree; // is start of a ZTree.
  108 + int m_iZeroTreeAfterSignificance; // is IZ after significant pixel.
  109 + int m_iZeroTreeAfterDC;
  110 + int m_iDCStartsZeroTree;
  111 + int m_iIsolatedZero; // is an isolated zero.
  112 + int m_iIsolatedZeroAfterSignificance; // is IZ after significant pixel.
  113 + int m_iIsolatedZeroAfterDC;
  114 + //
  115 + ZT more likely than IZ (by a factor of three)
  116 + but IZ more likely than ZT behind significant symbols.
  117 + completely zero blocks.
  118 +
  119 + block is completely zero: 0
  120 + DC becomes significant: 11
  121 + DC is isolated zero: 10
  122 +
  123 + Not-DC:
  124 + Isolated zero: 0
  125 + Zerotree: 10
  126 + Becomes significant: 11
  127 + */
  128 + //
  129 + // Backwards transform a single row.
  130 + static void BkwTransformRow(LONG *a,LONG *b,LONG *c,LONG *d)
  131 + {
  132 + LONG b1 = (*a + *c) >> 1;
  133 + LONG b2 = (*b + *d) >> 1;
  134 + LONG b3 = (*a - *c) >> 1;
  135 + LONG b4 = (*b - *d) >> 1;
  136 + // Inverse butterfly.
  137 + *a = (b1 + b2) >> 1;
  138 + *b = (b3 + b4) >> 1;
  139 + *c = (b3 - b4) >> 1;
  140 + *d = (b1 - b2) >> 1;
  141 + }
  142 + //
  143 + // Backwards transform a complete 4x4 block.
  144 + static void BackwardDCT(LONG *r1,LONG *r2,LONG *r3,LONG *r4)
  145 + {
  146 + // First horizontal.
  147 + BkwTransformRow(r1+0,r1+1,r1+2,r1+3);
  148 + BkwTransformRow(r2+0,r2+1,r2+2,r2+3);
  149 + BkwTransformRow(r3+0,r3+1,r3+2,r3+3);
  150 + BkwTransformRow(r4+0,r4+1,r4+2,r4+3);
  151 + // Then vertical.
  152 + BkwTransformRow(r1+0,r2+0,r3+0,r4+0);
  153 + BkwTransformRow(r1+1,r2+1,r3+1,r4+1);
  154 + BkwTransformRow(r1+2,r2+2,r3+2,r4+2);
  155 + BkwTransformRow(r1+3,r2+3,r3+3,r4+3);
  156 + }
  157 + //
  158 + // Forward transform an elementary row
  159 + static void FwdTransformRow(LONG *a,LONG *b,LONG *c,LONG *d)
  160 + {
  161 + // Step one: Forwards butterfly.
  162 + LONG b1 = *a + *d;
  163 + LONG b2 = *a - *d;
  164 + LONG b3 = *b + *c;
  165 + LONG b4 = *b - *c;
  166 + // DC and mid-AC coefficients.
  167 + *a = (b1 + b3);
  168 + *c = (b1 - b3);
  169 + // Lifting for the rotation.
  170 + *b = (b2 + b4);
  171 + *d = (b2 - b4);
  172 + }
  173 + //
  174 + // Return the neutral value of the DC band, initializes the DC offset
  175 + static LONG DCNeutralValue(LONG max)
  176 + {
  177 + return max << 3; // four times four times the DC value, halfed.
  178 + }
  179 + //
  180 + // Forward DCT on a 4x4 block
  181 + static void ForwardDCT(LONG *r1,LONG *r2,LONG *r3,LONG *r4)
  182 + {
  183 + // First vertical
  184 + FwdTransformRow(r1+0,r2+0,r3+0,r4+0);
  185 + FwdTransformRow(r1+1,r2+1,r3+1,r4+1);
  186 + FwdTransformRow(r1+2,r2+2,r3+2,r4+2);
  187 + FwdTransformRow(r1+3,r2+3,r3+3,r4+3);
  188 + // Then horizontal
  189 + FwdTransformRow(r1+0,r1+1,r1+2,r1+3);
  190 + FwdTransformRow(r2+0,r2+1,r2+2,r2+3);
  191 + FwdTransformRow(r3+0,r3+1,r3+2,r3+3);
  192 + FwdTransformRow(r4+0,r4+1,r4+2,r4+3);
  193 + }
  194 + //
  195 + //
  196 + // Update the DC value to what the decoder would reconstruct.
  197 + // Bitlevel is the last bitplane that has been coded.
  198 + void UpdateDC(UBYTE cx,UBYTE bitlevel);
  199 + //
  200 + // Decode a single level in a block.
  201 + void DecodeEZWLevel(UBYTE cx,ULONG x,ULONG bitmask,UBYTE freq)
  202 + {
  203 + LONG &v = m_plBuffer[cx][YPos[freq]][x + XPos[freq]];
  204 +
  205 + assert(freq <= 15);
  206 +
  207 + if (v & Significant) {
  208 + // Transmit the bit itself.
  209 + v &= ~bitmask;
  210 + if ((m_ulUsedBits++,m_Stream.Get<1>()))
  211 + v |= bitmask;
  212 + v |= bitmask >> 1;
  213 + } else if ((v & Encoded) == 0) {
  214 + if ((m_ulUsedBits++,m_Stream.Get<1>())) {
  215 + // Either IZ for freq = 0, or ZT for later
  216 + // symbols, or significant
  217 + if (freq < 15 && (m_ulUsedBits++,m_Stream.Get<1>()) == 0) {
  218 + // Is either IZ if freq != 0, or ZT otherwise.
  219 + if (freq) {
  220 + UBYTE i = freq + 1;
  221 + // Zerotree.
  222 + do {
  223 + m_plBuffer[cx][YPos[i]][x + XPos[i]] |= Encoded;
  224 + } while(++i < 16);
  225 + }
  226 + return;
  227 + }
  228 + // Becomes significant. Get the sign bit.
  229 + if ((m_ulUsedBits++,m_Stream.Get<1>())) {
  230 + v = Signed | Significant | bitmask | (bitmask >> 1);
  231 + } else {
  232 + v = Significant | bitmask | (bitmask >> 1);
  233 + }
  234 + } else if (freq == 0) {
  235 + UBYTE i = freq + 1;
  236 + // Is either IZ or ZT. Is ZT for DC == 0
  237 + do {
  238 + m_plBuffer[cx][YPos[i]][x + XPos[i]] |= Encoded;
  239 + } while(++i < 16);
  240 + }
  241 + }
  242 + }
  243 + //
  244 + // Encode a single level in a block.
  245 + void EncodeEZWLevel(UBYTE cx,ULONG x,ULONG bitmask,UBYTE freq)
  246 + {
  247 + LONG &v = m_plBuffer[cx][YPos[freq]][x + XPos[freq]];
  248 +
  249 + assert(freq <= 15);
  250 +
  251 + if (v & Significant) {
  252 + // Transmit the bit itself.
  253 + m_Stream.Put<1>((v & bitmask)?(1):(0));m_ulUsedBits++;
  254 + } else if ((v & Encoded) == 0) {
  255 + if (v & bitmask) {
  256 + // Was not significant but became significant.
  257 + if (freq < 15) { // has children.
  258 + // Is always 11.
  259 + m_Stream.Put<2>(3);m_ulUsedBits += 2;
  260 + } else {
  261 + m_Stream.Put<1>(1);m_ulUsedBits += 1;
  262 + }
  263 + // Encode the sign.
  264 + m_Stream.Put<1>((v & Signed)?1:0);m_ulUsedBits++;
  265 + // Becomes significant.
  266 + v |= Significant;
  267 + //
  268 + } else {
  269 + // Insignificant, and remains insignificant.
  270 + if (freq >= 15) {
  271 + // If no children, a single bit is enough
  272 + // and no further questions necessary.
  273 + m_Stream.Put<1>(0);m_ulUsedBits++;
  274 + } else {
  275 + UBYTE i = freq + 1;
  276 + bool ztree = true;
  277 + // Check whether this is a zero-tree, i.e. all
  278 + // children are either significant or insignificant
  279 + do {
  280 + LONG w = m_plBuffer[cx][YPos[i]][x + XPos[i]];
  281 + if ((w & Significant) == 0 && (w & bitmask)) {
  282 + ztree = false;
  283 + break;
  284 + }
  285 + } while(++i < 16);
  286 + //
  287 + if (ztree) {
  288 + // Is a zero-tree. Set all the children to encoded.
  289 + if (freq == 0) {
  290 + m_Stream.Put<1>(0);m_ulUsedBits++; // Encode as ZTree.
  291 + } else {
  292 + m_Stream.Put<2>(2);m_ulUsedBits+=2; // Encode as ZTree.
  293 + }
  294 + i = freq + 1;
  295 + do {
  296 + m_plBuffer[cx][YPos[i]][x + XPos[i]] |= Encoded;
  297 + } while(++i < 16);
  298 + } else {
  299 + // Not a zero-tree.
  300 + if (freq == 0) {
  301 + m_Stream.Put<2>(2);m_ulUsedBits+=2;
  302 + } else {
  303 + m_Stream.Put<1>(0);m_ulUsedBits++; // Encode as ZTree.
  304 + }
  305 + }
  306 + }
  307 + }
  308 + }
  309 + }
  310 + //
  311 + // Collect component information and install the component dimensions.
  312 + virtual void FindComponentDimensions(void);
  313 + //
  314 + // Remove all the encoded flags as we move to the next level.
  315 + static void ClearEncodedFlags(ULONG *data,ULONG width)
  316 + {
  317 + do {
  318 + *data++ &= ~Encoded;
  319 + } while(--width);
  320 + }
  321 + //
  322 + // Clear the data completely.
  323 + static void ClearData(ULONG *data,ULONG width)
  324 + {
  325 + do {
  326 + *data++ = 0;
  327 + } while(--width);
  328 + }
  329 + //
  330 + //
  331 +public:
  332 + // Create a new scan. This is only the base type.
  333 + VesaDCTScan(class Frame *frame,class Scan *scan,
  334 + UBYTE near,const UBYTE *mapping,UBYTE point);
  335 + //
  336 + virtual ~VesaDCTScan(void);
  337 + //
  338 + // Parse a single MCU in this scan. Return true if there are more
  339 + // MCUs in this row.
  340 + virtual bool ParseMCU(void);
  341 + //
  342 + // Write a single MCU in this scan.
  343 + virtual bool WriteMCU(void);
  344 +};
  345 +///
  346 +
  347 +
  348 +///
  349 +#endif
  350 +
52 codestream/vesascan.hpp
@@ -46,7 +46,7 @@ the committee itself.
46 46 /*
47 47 ** A variant of JPEG LS for the proposed vesa compression. Experimental.
48 48 **
49   -** $Id: vesascan.hpp,v 1.17 2012-09-13 19:28:57 thor Exp $
  49 +** $Id: vesascan.hpp,v 1.19 2012-09-26 13:48:18 thor Exp $
50 50 **
51 51 */
52 52
@@ -127,7 +127,7 @@ class VesaScan : public JPEGLSScan {
127 127 } else if (b < minac) {
128 128 return (b + minac) >> 1;
129 129 } else {
130   - return b; // works better than a mid-point prediction.
  130 + return (a + (b << 1) + c) >> 2; // works better than a mid-point prediction.
131 131 }
132 132 }
133 133 //
@@ -332,6 +332,18 @@ class VesaScan : public JPEGLSScan {
332 332 data[x] |= Encoded;
333 333 }
334 334 //
  335 + // Check whether a coefficient has children.
  336 + bool static hasChildren(ULONG x,UBYTE inc,bool lowpass)
  337 + {
  338 + ULONG increment = 1UL << inc;
  339 +
  340 + if ((lowpass && ((x >> inc) & 1)) || (!lowpass && increment > 2)) {
  341 + return true;
  342 + } else {
  343 + return false;
  344 + }
  345 + }
  346 + //
335 347 // Encode a bitplane level with the EZW
336 348 void EncodeEZWLevel(ULONG *data,ULONG width,UBYTE inc,ULONG bitmask,bool lowpass)
337 349 {
@@ -345,25 +357,30 @@ class VesaScan : public JPEGLSScan {
345 357 } else if ((data[x] & Encoded) == 0) {
346 358 if (data[x] & bitmask) {
347 359 // Not a zero-tree, becomes significant.
348   - m_Stream.Put<1>(1);m_ulUsedBits++;
  360 + if (hasChildren(x,inc,lowpass)) {
  361 + m_Stream.Put<2>(3);m_ulUsedBits+=2;
  362 + } else {
  363 + m_Stream.Put<1>(1);m_ulUsedBits++;
  364 + }
349 365 // Sign-coding.
350 366 m_Stream.Put<1>((data[x] & Signed)?(true):(false));m_ulUsedBits++;
351 367 // Becomes significant.