summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordscho <dscho>2008-02-04 17:57:39 +0000
committerdscho <dscho>2008-02-04 17:57:39 +0000
commitbefcb6fc14942f3c954586edabf9afa79f696dd3 (patch)
tree3b53ea6aa33e5a3c2884dfc4257f936726f522f0
parent8bb827161524ac9239b9170577f2f5c31405906f (diff)
downloadlibtdevnc-befcb6fc.tar.gz
libtdevnc-befcb6fc.zip
Fix ZYWRLE en/decoding for width != scanline (thanks Noriaki Yamazaki)
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
-rw-r--r--ChangeLog4
-rw-r--r--libvncserver/zywrletemplate.c297
2 files changed, 156 insertions, 145 deletions
diff --git a/ChangeLog b/ChangeLog
index 0651240..39d2e96 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2008-02-04 Noriaki Yamazaki <micro-vnc@ias.hitachi-system.co.jp>
+ * libvncserver/zywrletemplate.c: Fix mis encode/decode when
+ width != scanline
+
2008-02-02 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
* client_examples/SDLvncviewer.c: fix buttons (2 & 3 were switched),
fix Tab key, and fix Ctrl+<letter>
diff --git a/libvncserver/zywrletemplate.c b/libvncserver/zywrletemplate.c
index 0e77474..52b2b0b 100644
--- a/libvncserver/zywrletemplate.c
+++ b/libvncserver/zywrletemplate.c
@@ -41,16 +41,23 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
********************************************************************/
+/* Change Log:
+ V0.02 : 2008/02/04 : Fix mis encode/decode when width != scanline
+ (Thanks Johannes Schindelin, author of LibVNC
+ Server/Client)
+ V0.01 : 2007/02/06 : Initial release
+*/
+
/* #define ZYWRLE_ENCODE */
/* #define ZYWRLE_DECODE */
#define ZYWRLE_QUANTIZE
/*
- [References]
- PLHarr:
- Senecal, J. G., P. Lindstrom, M. A. Duchaineau, and K. I. Joy, "An Improved N-Bit to N-Bit Reversible Haar-Like Transform," Pacific Graphics 2004, October 2004, pp. 371-380.
- EZW:
- Shapiro, JM: Embedded Image Coding Using Zerotrees of Wavelet Coefficients, IEEE Trans. Signal. Process., Vol.41, pp.3445-3462 (1993).
+[References]
+ PLHarr:
+ Senecal, J. G., P. Lindstrom, M. A. Duchaineau, and K. I. Joy, "An Improved N-Bit to N-Bit Reversible Haar-Like Transform," Pacific Graphics 2004, October 2004, pp. 371-380.
+ EZW:
+ Shapiro, JM: Embedded Image Coding Using Zerotrees of Wavelet Coefficients, IEEE Trans. Signal. Process., Vol.41, pp.3445-3462 (1993).
*/
@@ -67,8 +74,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define ZYWRLE_LOAD_PIXEL __RFB_CONCAT2E(ZYWRLE_LOAD_PIXEL,BPP)
#define ZYWRLE_SAVE_PIXEL __RFB_CONCAT2E(ZYWRLE_SAVE_PIXEL,BPP)
-/* Packing/Unpacking pixel stuffs. */
-/* Endian conversion stuffs. */
+/* Packing/Unpacking pixel stuffs.
+ Endian conversion stuffs. */
#undef S_0
#undef S_1
#undef L_0
@@ -147,11 +154,9 @@ const static unsigned int zywrleParam[3][3]={
{0x0000F000,0x00000000,0x00000000},
{0x0000C000,0x00F0F0F0,0x00000000},
{0x0000C000,0x00C0C0C0,0x00F0F0F0},
-/*
- {0x0000FF00,0x00000000,0x00000000},
+/* {0x0000FF00,0x00000000,0x00000000},
{0x0000FF00,0x00FFFFFF,0x00000000},
- {0x0000FF00,0x00FFFFFF,0x00FFFFFF},
-*/
+ {0x0000FF00,0x00FFFFFF,0x00FFFFFF}, */
};
# else
/* Type B:Non liner quantization filter. */
@@ -305,8 +310,8 @@ static InlineX void Harr(signed char* pX0, signed char* pX1)
{
/* Piecewise-Linear Harr(PLHarr) */
int X0 = (int)*pX0, X1 = (int)*pX1;
- int orgX0=X0, orgX1=X1;
- if ((X0^X1) & 0x80) {
+ int orgX0 = X0, orgX1 = X1;
+ if ((X0 ^ X1) & 0x80) {
/* differ sign */
X1 += X0;
if (((X1^orgX1)&0x80)==0) {
@@ -316,7 +321,7 @@ static InlineX void Harr(signed char* pX0, signed char* pX1)
} else {
/* same sign */
X0 -= X1;
- if (((X0^orgX0) & 0x80) == 0) {
+ if (((X0 ^ orgX0) & 0x80) == 0) {
/* |X0| > |X1| */
X1 += X0; /* L = A */
}
@@ -325,27 +330,26 @@ static InlineX void Harr(signed char* pX0, signed char* pX1)
*pX1 = (signed char)X0;
}
/*
- 1D-Wavelet transform.
+ 1D-Wavelet transform.
- In coefficients array, the famous 'pyramid' decomposition is well used.
+ In coefficients array, the famous 'pyramid' decomposition is well used.
- 1D Model:
- |L0L0L0L0|L0L0L0L0|H0H0H0H0|H0H0H0H0| : level 0
- |L1L1L1L1|H1H1H1H1|H0H0H0H0|H0H0H0H0| : level 1
+ 1D Model:
+ |L0L0L0L0|L0L0L0L0|H0H0H0H0|H0H0H0H0| : level 0
+ |L1L1L1L1|H1H1H1H1|H0H0H0H0|H0H0H0H0| : level 1
- But this method needs line buffer because H/L is different position from X0/X1.
- So, I used 'interleave' decomposition instead of it.
+ But this method needs line buffer because H/L is different position from X0/X1.
+ So, I used 'interleave' decomposition instead of it.
- 1D Model:
- |L0H0L0H0|L0H0L0H0|L0H0L0H0|L0H0L0H0| : level 0
- |L1H0H1H0|L1H0H1H0|L1H0H1H0|L1H0H1H0| : level 1
+ 1D Model:
+ |L0H0L0H0|L0H0L0H0|L0H0L0H0|L0H0L0H0| : level 0
+ |L1H0H1H0|L1H0H1H0|L1H0H1H0|L1H0H1H0| : level 1
- In this method, H/L and X0/X1 is always same position.
- This lead us to more speed and less memory.
- Of cause, the result of both method is quite same
- because it's only difference that coefficient position.
+ In this method, H/L and X0/X1 is always same position.
+ This lead us to more speed and less memory.
+ Of cause, the result of both method is quite same
+ because it's only difference that coefficient position.
*/
-
static InlineX void WaveletLevel(int* data, int size, int l, int SkipPixel)
{
int s, ofs;
@@ -389,11 +393,11 @@ static InlineX void FilterWaveletSquare(int* pBuf, int width, int height, int le
for (y = 0; y < height / s; y++) {
for (x = 0; x < width / s; x++) {
/*
- these are same following code.
- pH[x] = pH[x] / (~pM[x]+1) * (~pM[x]+1);
- ( round pH[x] with pM[x] bit )
- '&' operator isn't 'round' but is 'floor'.
- So, we must offset when pH[x] is negative.
+ these are same following code.
+ pH[x] = pH[x] / (~pM[x]+1) * (~pM[x]+1);
+ ( round pH[x] with pM[x] bit )
+ '&' operator isn't 'round' but is 'floor'.
+ So, we must offset when pH[x] is negative.
*/
if (((signed char*)pH)[0] & 0x80)
((signed char*)pH)[0] += ~((signed char*)pM)[0];
@@ -410,36 +414,35 @@ static InlineX void FilterWaveletSquare(int* pBuf, int width, int height, int le
}
# else
/*
- Type B:Non liner quantization filter.
-
- Coefficients have Gaussian curve and smaller value which is
- large part of coefficients isn't more important than larger value.
- So, I use filter of Non liner quantize/dequantize table.
- In general, Non liner quantize formula is explained as following.
-
- y=f(x) = sign(x)*round( ((abs(x)/(2^7))^ r )* 2^(bo-1) )*2^(8-bo)
- x=f-1(y) = sign(y)*round( ((abs(y)/(2^7))^(1/r))* 2^(bi-1) )*2^(8-bi)
- ( r:power coefficient bi:effective MSB in input bo:effective MSB in output )
-
- r < 1.0 : Smaller value is more important than larger value.
- r > 1.0 : Larger value is more important than smaller value.
- r = 1.0 : Liner quantization which is same with EZW style.
-
- r = 0.75 is famous non liner quantization used in MP3 audio codec.
- In contrast to audio data, larger value is important in wavelet coefficients.
- So, I select r = 2.0 table( quantize is x^2, dequantize sqrt(x) ).
-
- As compared with EZW style liner quantization, this filter tended to be
- more sharp edge and be more compression rate but be more blocking noise and be less quality.
- Especially, the surface of graphic objects has distinguishable noise in middle quality mode.
-
- We need only quantized-dequantized(filtered) value rather than quantized value itself
- because all values are packed or palette-lized in later ZRLE section.
- This lead us not to need to modify client decoder when we change
- the filtering procedure in future.
- Client only decodes coefficients given by encoder.
+ Type B:Non liner quantization filter.
+
+ Coefficients have Gaussian curve and smaller value which is
+ large part of coefficients isn't more important than larger value.
+ So, I use filter of Non liner quantize/dequantize table.
+ In general, Non liner quantize formula is explained as following.
+
+ y=f(x) = sign(x)*round( ((abs(x)/(2^7))^ r )* 2^(bo-1) )*2^(8-bo)
+ x=f-1(y) = sign(y)*round( ((abs(y)/(2^7))^(1/r))* 2^(bi-1) )*2^(8-bi)
+ ( r:power coefficient bi:effective MSB in input bo:effective MSB in output )
+
+ r < 1.0 : Smaller value is more important than larger value.
+ r > 1.0 : Larger value is more important than smaller value.
+ r = 1.0 : Liner quantization which is same with EZW style.
+
+ r = 0.75 is famous non liner quantization used in MP3 audio codec.
+ In contrast to audio data, larger value is important in wavelet coefficients.
+ So, I select r = 2.0 table( quantize is x^2, dequantize sqrt(x) ).
+
+ As compared with EZW style liner quantization, this filter tended to be
+ more sharp edge and be more compression rate but be more blocking noise and be less quality.
+ Especially, the surface of graphic objects has distinguishable noise in middle quality mode.
+
+ We need only quantized-dequantized(filtered) value rather than quantized value itself
+ because all values are packed or palette-lized in later ZRLE section.
+ This lead us not to need to modify client decoder when we change
+ the filtering procedure in future.
+ Client only decodes coefficients given by encoder.
*/
-
static InlineX void FilterWaveletSquare(int* pBuf, int width, int height, int level, int l)
{
int r, s;
@@ -485,7 +488,7 @@ static InlineX void Wavelet(int* pBuf, int width, int height, int level)
pTop = pBuf;
pEnd = pBuf+width;
s = 1<<l;
- while(pTop < pEnd) {
+ while (pTop < pEnd) {
WaveletLevel(pTop, height,l, width);
pTop += s;
}
@@ -494,12 +497,13 @@ static InlineX void Wavelet(int* pBuf, int width, int height, int level)
}
#endif
#ifdef ZYWRLE_DECODE
-static InlineX void InvWavelet(int* pBuf, int width, int height, int level) {
+static InlineX void InvWavelet(int* pBuf, int width, int height, int level)
+{
int l, s;
int* pTop;
int* pEnd;
- for (l = level-1; l >= 0; l--) {
+ for (l = level - 1; l >= 0; l--) {
pTop = pBuf;
pEnd = pBuf+width;
s = 1<<l;
@@ -518,8 +522,8 @@ static InlineX void InvWavelet(int* pBuf, int width, int height, int level) {
}
#endif
-/* Load/Save coefficients stuffs. */
-/* Coefficients manages as 24 bits little-endian pixel. */
+/* Load/Save coefficients stuffs.
+ Coefficients manages as 24 bits little-endian pixel. */
#define ZYWRLE_LOAD_COEFF(pSrc,R,G,B) { \
R = ((signed char*)pSrc)[2]; \
G = ((signed char*)pSrc)[1]; \
@@ -532,25 +536,22 @@ static InlineX void InvWavelet(int* pBuf, int width, int height, int level) {
}
/*
- RGB <=> YUV conversion stuffs.
- YUV coversion is explained as following formula in strict meaning:
- Y = 0.299R + 0.587G + 0.114B ( 0<=Y<=255)
- U = -0.169R - 0.331G + 0.500B (-128<=U<=127)
- V = 0.500R - 0.419G - 0.081B (-128<=V<=127)
-
- I use simple conversion RCT(reversible color transform) which is described
- in JPEG-2000 specification.
- Y = (R + 2G + B)/4 ( 0<=Y<=255)
- U = B-G (-256<=U<=255)
- V = R-G (-256<=V<=255)
+ RGB <=> YUV conversion stuffs.
+ YUV coversion is explained as following formula in strict meaning:
+ Y = 0.299R + 0.587G + 0.114B ( 0<=Y<=255)
+ U = -0.169R - 0.331G + 0.500B (-128<=U<=127)
+ V = 0.500R - 0.419G - 0.081B (-128<=V<=127)
+
+ I use simple conversion RCT(reversible color transform) which is described
+ in JPEG-2000 specification.
+ Y = (R + 2G + B)/4 ( 0<=Y<=255)
+ U = B-G (-256<=U<=255)
+ V = R-G (-256<=V<=255)
*/
-
#define ROUND(x) (((x)<0)?0:(((x)>255)?255:(x)))
- /*
- RCT is N-bit RGB to N-bit Y and N+1-bit UV.
- For make Same N-bit, UV is lossy.
- More exact PLHarr, we reduce to odd range(-127<=x<=127).
- */
+ /* RCT is N-bit RGB to N-bit Y and N+1-bit UV.
+ For make Same N-bit, UV is lossy.
+ More exact PLHarr, we reduce to odd range(-127<=x<=127). */
#define ZYWRLE_RGBYUV1(R,G,B,Y,U,V,ymask,uvmask) { \
Y = (R+(G<<1)+B)>>2; \
U = B-G; \
@@ -581,71 +582,77 @@ static InlineX void InvWavelet(int* pBuf, int width, int height, int level) {
}
/*
- coefficient packing/unpacking stuffs.
- Wavelet transform makes 4 sub coefficient image from 1 original image.
-
- model with pyramid decomposition:
- +------+------+
- | | |
- | L | Hx |
- | | |
- +------+------+
- | | |
- | H | Hxy |
- | | |
- +------+------+
-
- So, we must transfer each sub images individually in strict meaning.
- But at least ZRLE meaning, following one decompositon image is same as
- avobe individual sub image. I use this format.
- (Strictly saying, transfer order is reverse(Hxy->Hy->Hx->L)
- for simplified procedure for any wavelet level.)
-
- +------+------+
- | L |
- +------+------+
- | Hx |
- +------+------+
- | Hy |
- +------+------+
- | Hxy |
- +------+------+
+ coefficient packing/unpacking stuffs.
+ Wavelet transform makes 4 sub coefficient image from 1 original image.
+
+ model with pyramid decomposition:
+ +------+------+
+ | | |
+ | L | Hx |
+ | | |
+ +------+------+
+ | | |
+ | H | Hxy |
+ | | |
+ +------+------+
+
+ So, we must transfer each sub images individually in strict meaning.
+ But at least ZRLE meaning, following one decompositon image is same as
+ avobe individual sub image. I use this format.
+ (Strictly saying, transfer order is reverse(Hxy->Hy->Hx->L)
+ for simplified procedure for any wavelet level.)
+
+ +------+------+
+ | L |
+ +------+------+
+ | Hx |
+ +------+------+
+ | Hy |
+ +------+------+
+ | Hxy |
+ +------+------+
*/
+#define INC_PTR(data) \
+ data++; \
+ if( data-pData >= (w+uw) ){ \
+ data += scanline-(w+uw); \
+ pData = data; \
+ }
-#define ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,level,TRANS) \
+#define ZYWRLE_TRANSFER_COEFF(pBuf,data,r,w,h,scanline,level,TRANS) \
pH = pBuf; \
s = 2<<level; \
if (r & 0x01) \
pH += s>>1; \
if (r & 0x02) \
- pH += (s>>1)*width; \
- pEnd = pH+height*width; \
+ pH += (s>>1)*w; \
+ pEnd = pH+h*w; \
while (pH < pEnd) { \
- pLine = pH+width; \
+ pLine = pH+w; \
while (pH < pLine) { \
TRANS \
- data++; \
+ INC_PTR(data) \
pH += s; \
} \
- pH += (s-1)*width; \
+ pH += (s-1)*w; \
}
-#define ZYWRLE_PACK_COEFF(pBuf,data,r,width,height,level) \
- ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,level,ZYWRLE_LOAD_COEFF(pH,R,G,B);ZYWRLE_SAVE_PIXEL(data,R,G,B);)
+#define ZYWRLE_PACK_COEFF(pBuf,data,r,width,height,scanline,level) \
+ ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,scanline,level,ZYWRLE_LOAD_COEFF(pH,R,G,B);ZYWRLE_SAVE_PIXEL(data,R,G,B);)
-#define ZYWRLE_UNPACK_COEFF(pBuf,data,r,width,height,level) \
- ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,level,ZYWRLE_LOAD_PIXEL(data,R,G,B);ZYWRLE_SAVE_COEFF(pH,R,G,B);)
+#define ZYWRLE_UNPACK_COEFF(pBuf,data,r,width,height,scanline,level) \
+ ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,scanline,level,ZYWRLE_LOAD_PIXEL(data,R,G,B);ZYWRLE_SAVE_COEFF(pH,R,G,B);)
#define ZYWRLE_SAVE_UNALIGN(data,TRANS) \
pTop = pBuf+w*h; \
- pEnd = pTop + (w+uw)*(h+uh)-w*h; \
+ pEnd = pBuf + (w+uw)*(h+uh); \
while (pTop < pEnd) { \
TRANS \
- data++; \
+ INC_PTR(data) \
pTop++; \
}
-#define ZYWRLE_LOAD_UNALIGN(data,pData,TRANS) \
+#define ZYWRLE_LOAD_UNALIGN(data,TRANS) \
pTop = pBuf+w*h; \
if (uw) { \
pData= data + w; \
@@ -718,8 +725,7 @@ static InlineX void ZYWRLE_RGBYUV(int* pBuf, PIXEL_T* data, int width, int heigh
}
#endif
#ifdef ZYWRLE_DECODE
-static InlineX void ZYWRLE_YUVRGB(int* pBuf, PIXEL_T* data, int width, int height, int scanline)
-{
+static InlineX void ZYWRLE_YUVRGB(int* pBuf, PIXEL_T* data, int width, int height, int scanline) {
int R, G, B;
int Y, U, V;
int* pLine;
@@ -740,15 +746,14 @@ static InlineX void ZYWRLE_YUVRGB(int* pBuf, PIXEL_T* data, int width, int heigh
#endif
#ifdef ZYWRLE_ENCODE
-PIXEL_T* ZYWRLE_ANALYZE (PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanline, int level, int* pBuf)
-{
+PIXEL_T* ZYWRLE_ANALYZE(PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanline, int level, int* pBuf) {
int l;
int uw = w;
int uh = h;
int* pTop;
int* pEnd;
int* pLine;
- PIXEL_T* pSrc;
+ PIXEL_T* pData;
int R, G, B;
int s;
int* pH;
@@ -759,15 +764,16 @@ PIXEL_T* ZYWRLE_ANALYZE (PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanline,
uw -= w;
uh -= h;
- ZYWRLE_LOAD_UNALIGN(src,pSrc,*(PIXEL_T*)pTop=*pSrc;)
+ pData = dst;
+ ZYWRLE_LOAD_UNALIGN(src,*(PIXEL_T*)pTop=*pData;)
ZYWRLE_RGBYUV(pBuf, src, w, h, scanline);
Wavelet(pBuf, w, h, level);
for (l = 0; l < level; l++) {
- ZYWRLE_PACK_COEFF(pBuf, dst, 3, w, h, l);
- ZYWRLE_PACK_COEFF(pBuf, dst, 2, w, h, l);
- ZYWRLE_PACK_COEFF(pBuf, dst, 1, w, h, l);
- if (l == level-1) {
- ZYWRLE_PACK_COEFF(pBuf, dst, 0, w, h, l);
+ ZYWRLE_PACK_COEFF(pBuf, dst, 3, w, h, scanline, l);
+ ZYWRLE_PACK_COEFF(pBuf, dst, 2, w, h, scanline, l);
+ ZYWRLE_PACK_COEFF(pBuf, dst, 1, w, h, scanline, l);
+ if (l == level - 1) {
+ ZYWRLE_PACK_COEFF(pBuf, dst, 0, w, h, scanline, l);
}
}
ZYWRLE_SAVE_UNALIGN(dst,*dst=*(PIXEL_T*)pTop;)
@@ -783,7 +789,7 @@ PIXEL_T* ZYWRLE_SYNTHESIZE(PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanlin
int* pTop;
int* pEnd;
int* pLine;
- PIXEL_T* pDst;
+ PIXEL_T* pData;
int R, G, B;
int s;
int* pH;
@@ -794,18 +800,19 @@ PIXEL_T* ZYWRLE_SYNTHESIZE(PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanlin
uw -= w;
uh -= h;
+ pData = src;
for (l = 0; l < level; l++) {
- ZYWRLE_UNPACK_COEFF(pBuf, src, 3, w, h, l);
- ZYWRLE_UNPACK_COEFF(pBuf, src, 2, w, h, l);
- ZYWRLE_UNPACK_COEFF(pBuf, src, 1, w, h, l);
- if (l == level-1) {
- ZYWRLE_UNPACK_COEFF(pBuf, src, 0, w, h, l);
+ ZYWRLE_UNPACK_COEFF(pBuf, src, 3, w, h, scanline, l);
+ ZYWRLE_UNPACK_COEFF(pBuf, src, 2, w, h, scanline, l);
+ ZYWRLE_UNPACK_COEFF(pBuf, src, 1, w, h, scanline, l);
+ if (l == level - 1) {
+ ZYWRLE_UNPACK_COEFF(pBuf, src, 0, w, h, scanline, l);
}
}
ZYWRLE_SAVE_UNALIGN(src,*(PIXEL_T*)pTop=*src;)
InvWavelet(pBuf, w, h, level);
ZYWRLE_YUVRGB(pBuf, dst, w, h, scanline);
- ZYWRLE_LOAD_UNALIGN(dst,pDst,*pDst=*(PIXEL_T*)pTop;)
+ ZYWRLE_LOAD_UNALIGN(dst,*pData=*(PIXEL_T*)pTop;)
return src;
}
#endif