New upstream version 3.5.99.27

This commit is contained in:
geos_one
2025-08-08 20:00:36 +02:00
commit bc8d10cc33
4267 changed files with 1757978 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#include <zlib.h>
#include "Compext.h"
#include "Alpha.h"
#include "Z.h"
#define PANIC
#define WARNING
#undef TEST
#undef DEBUG
#define ALPHA_COMPRESSION_LEVEL 1
#define ALPHA_COMPRESSION_THRESHOLD 32
#define ALPHA_COMPRESSION_STRATEGY Z_RLE
static int alphaCompressionLevel = ALPHA_COMPRESSION_LEVEL;
static int alphaCompressionThreshold = ALPHA_COMPRESSION_THRESHOLD;
static int alphaCompressionStrategy = ALPHA_COMPRESSION_STRATEGY;
char *AlphaCompressData(const char *data, unsigned int size, unsigned int *compressed_size)
{
return ZCompressData(data, size, alphaCompressionThreshold, alphaCompressionLevel,
alphaCompressionStrategy, compressed_size);
}

View File

@@ -0,0 +1,45 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#ifndef Alpha_H
#define Alpha_H
#ifdef __cplusplus
extern "C" {
#endif
extern char *AlphaCompressData(
#if NeedFunctionPrototypes
const char* /* data */,
unsigned int /* size */,
unsigned int* /* compressed_size */
#endif
);
#ifdef __cplusplus
}
#endif
#endif /* Alpha_H */

View File

@@ -0,0 +1,120 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "Compext.h"
#include "Bitmap.h"
#define PANIC
#define WARNING
#undef TEST
#undef DEBUG
char *BitmapCompressData(XImage *image, unsigned int *size)
{
if (image -> bits_per_pixel != 32)
{
#ifdef TEST
fprintf(stderr, "******BitmapCompressData: Nothing to do with image of [%d] bpp and size [%d].\n",
image -> bits_per_pixel, image -> bytes_per_line * image -> height);
#endif
*size = image -> bytes_per_line * image -> height;
return image -> data;
}
else
{
/*
* Remove the 4th byte from the bitmap.
*/
char *data;
char *next_src;
char *next_dst;
#ifdef TEST
if (image -> bytes_per_line != 4 * image -> width)
{
fprintf(stderr, "******BitmapCompressData: PANIC! Image as [%d] bytes per line with expected [%d].\n",
image -> bytes_per_line, 4 * image -> width);
return NULL;
}
#endif
*size = image -> width * image -> height * 3;
data = malloc(*size);
if (data == NULL)
{
#ifdef PANIC
fprintf(stderr, "******BitmapCompressData: PANIC! Failed to allocate [%d] bytes for the destination.\n",
*size);
#endif
*size = image -> bytes_per_line * image -> height;
return image -> data;
}
next_src = image -> data;
next_dst = data;
if (image -> byte_order == LSBFirst)
{
while (next_src < image -> data +
image -> bytes_per_line * image -> height)
{
*next_dst++ = *next_src++;
*next_dst++ = *next_src++;
*next_dst++ = *next_src++;
next_src++;
}
}
else
{
while (next_src < image -> data +
image -> bytes_per_line * image -> height)
{
next_src++;
*next_dst++ = *next_src++;
*next_dst++ = *next_src++;
*next_dst++ = *next_src++;
}
}
return data;
}
}

View File

@@ -0,0 +1,44 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#ifndef Bitmap_H
#define Bitmap_H
#ifdef __cplusplus
extern "C" {
#endif
extern char *BitmapCompressData(
#if NeedFunctionPrototypes
XImage* /* image */,
unsigned int* /* compressed_size */
#endif
);
#ifdef __cplusplus
}
#endif
#endif /* Bitmap_H */

View File

@@ -0,0 +1,341 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#include <stdio.h>
#include <signal.h>
#include "os.h"
#include "Compext.h"
#include "Clean.h"
#define PANIC
#define WARNING
#undef TEST
#undef DEBUG
int CleanXYImage(XImage *image)
{
int i, j, k, plane;
int bitsToClean = (image -> bytes_per_line << 3) - image -> width - image -> xoffset;
unsigned int bytesToClean = bitsToClean >> 3;
bitsToClean &= 7;
for (k = 0; k < image -> depth; k++)
{
plane = k * (image -> bytes_per_line * image -> height);
for (i = 1; i <= image -> height; i++)
{
if (image -> byte_order == image -> bitmap_bit_order)
{
for (j = 1; j <= bytesToClean; j++)
{
image -> data[plane + i * (image -> bytes_per_line) - j] = 0x00;
}
}
else
{
for (j = bytesToClean; j >= 1; j--)
{
image -> data[plane + i * (image -> bytes_per_line) - j] = 0x00;
}
}
if (image -> bitmap_bit_order == MSBFirst)
{
image -> data[plane + i * (image -> bytes_per_line) - j] &= 0xff << bitsToClean;
}
else
{
image -> data[plane + i * (image -> bytes_per_line) - j] &= 0xff >> bitsToClean;
}
}
}
return 1;
}
int CleanZImage(XImage *image)
{
unsigned int bytesToClean;
unsigned int imageLength;
#ifdef TEST
fprintf(stderr, "*****CleanZImage: Going to clean image of [%d] bits per pixel.\n",
image -> bits_per_pixel);
#endif
switch (image -> bits_per_pixel)
{
case 32:
{
/*
* The caller should pay attention at extracting
* the alpha channel prior to cleaning the image.
* Cleaning an image which is carrying the alpha
* channel will result in the image being treated
* as fully transparent.
*/
bytesToClean = image -> bytes_per_line * image -> height;
#ifdef DEBUG
fprintf(stderr, "*****CleanZImage: Cleaning [%d] bytes with bits per pixel [%d] "
"width [%d] bytes per line [%d] height [%d].\n", bytesToClean,
image -> bits_per_pixel, image -> width, image ->
bytes_per_line, image -> height);
#endif
if (image -> byte_order == LSBFirst)
{
for (int i = 3; i < bytesToClean; i += 4)
{
((unsigned char *) image -> data)[i] = 0x00;
}
}
else
{
for (int i = 0; i < bytesToClean; i += 4)
{
((unsigned char *) image -> data)[i] = 0x00;
}
}
break;
}
case 24:
case 15:
case 16:
case 8:
{
bytesToClean = image -> bytes_per_line -
((image -> width * image -> bits_per_pixel) >> 3);
for (int i = 1; i <= image -> height; i++)
{
for (int j = bytesToClean; j > 0; j--)
{
((unsigned char *) image -> data)[(i * image -> bytes_per_line) - j] = 0x00;
}
}
break;
}
default:
{
#ifdef PANIC
fprintf(stderr, "*****CleanZImage: PANIC! Cannot clean image with [%d] bits per pixel.\n",
image -> bits_per_pixel);
#endif
}
}
/*
* Clean the padding bytes at the real
* end of the buffer.
*/
imageLength = image -> bytes_per_line * image -> height;
bytesToClean = imageLength % 4;
for (int j = 0; j < bytesToClean; j++)
{
((unsigned char *)image -> data)[(imageLength + j)] = 0x00;
}
return 1;
}
/*
* Copy a clean version of src_image into dst_image.
* This code is not taking care of the image format.
* The agent doesn't use it and you have to consider
* it unsupported.
*/
int CopyAndCleanImage(XImage *src_image, XImage *dst_image)
{
register long data_size;
data_size = (src_image -> bytes_per_line * src_image -> height) >> 2;
#ifdef WARNING
fprintf(stderr, "******CleanImage: WARNING! Function called with image of [%d] bits per pixel.\n",
src_image -> bits_per_pixel);
#endif
switch (src_image -> bits_per_pixel)
{
case 32:
{
unsigned int mask;
if (src_image -> byte_order == MSBFirst)
{
mask = 0xffffff00;
}
else
{
mask = 0x00ffffff;
}
for (int i = 0; i < data_size; i++)
{
((unsigned int *)dst_image -> data)[i] = ((unsigned int *)src_image -> data)[i] & mask;
}
break;
}
case 24:
{
unsigned int bytes_to_clean;
for (int i = 0; i < data_size; i++)
{
((unsigned int *)dst_image -> data)[i] = ((unsigned int *)src_image -> data)[i];
}
bytes_to_clean = dst_image -> bytes_per_line - ((dst_image -> width *
dst_image -> bits_per_pixel) >> 3);
if (bytes_to_clean)
{
register unsigned int mask = 0xffffffff;
register int line_size;
line_size = dst_image -> bytes_per_line >> 2;
if (dst_image -> byte_order == MSBFirst)
{
mask = mask << (bytes_to_clean << 3);
}
else
{
mask = mask >> (bytes_to_clean << 3);
}
for (int i = 0; i < dst_image -> height;)
{
((unsigned char *)dst_image -> data)[(++i * line_size) -1] &= mask;
}
}
break;
}
case 15:
case 16:
{
for (int i = 0; i < data_size; i++)
{
((unsigned int *) dst_image -> data)[i] = ((unsigned int *) src_image -> data)[i];
}
if (src_image -> width & 0x00000001)
{
int card32_per_line = dst_image -> bytes_per_line >> 2;
for (int i = 0; i < dst_image -> height;)
{
((unsigned int *) dst_image -> data)[(++i * card32_per_line) -1] &= 0x0000ffff;
}
}
break;
}
case 8:
{
unsigned int mask = 0x00000000;
switch (dst_image -> width % 4)
{
case 3:
{
mask = 0x00ffffff;
break;
}
case 2:
{
mask = 0x0000ffff;
break;
}
case 1:
{
mask = 0x000000ff;
break;
}
default:
{
/*
* Nothing to clean.
*/
break;
}
}
for (int i = 0; i < data_size; i++)
{
((unsigned int *) dst_image -> data)[i] = ((unsigned int *) src_image -> data)[i];
}
if (mask)
{
int card32_per_line;
card32_per_line = dst_image -> bytes_per_line >> 2;
for (int i = 0; i < dst_image -> height; i++)
{
((unsigned int *) dst_image -> data)[(++i * card32_per_line) -1] &= mask;
}
}
break;
}
default:
{
#ifdef PANIC
fprintf(stderr, "******CleanImage: PANIC! Cannot clean image of [%d] bits per pixel.\n",
src_image -> bits_per_pixel);
#endif
return 0;
}
}
return 1;
}

View File

@@ -0,0 +1,44 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#ifndef Clean_H
#define Clean_H
#ifdef __cplusplus
extern "C" {
#endif
#include <nx-X11/Xlib.h>
int CleanXYImage(XImage *image);
int CleanZImage(XImage *image);
int CopyAndCleanImage(XImage *src_image, XImage *dst_image);
#ifdef __cplusplus
}
#endif
#endif /* Clean_H */

View File

@@ -0,0 +1,50 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#include <zlib.h>
#include "Compext.h"
#include "Colormap.h"
#include "Z.h"
#define PANIC
#define WARNING
#undef TEST
#undef DEBUG
#define COLORMAP_COMPRESSION_LEVEL 4
#define COLORMAP_COMPRESSION_THRESHOLD 32
#define COLORMAP_COMPRESSION_STRATEGY Z_DEFAULT_STRATEGY
static int colormapCompressionLevel = COLORMAP_COMPRESSION_LEVEL;
static int colormapCompressionThreshold = COLORMAP_COMPRESSION_THRESHOLD;
static int colormapCompressionStrategy = COLORMAP_COMPRESSION_STRATEGY;
char *ColormapCompressData(const char *data, unsigned int size, unsigned int *compressed_size)
{
return ZCompressData(data, size, colormapCompressionThreshold, colormapCompressionLevel,
colormapCompressionStrategy, compressed_size);
}

View File

@@ -0,0 +1,45 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#ifndef ColormapComp_H
#define ColormapComp_H
#ifdef __cplusplus
extern "C" {
#endif
extern char *ColormapCompressData(
#if NeedFunctionPrototypes
const char* /* data */,
unsigned int /* size */,
unsigned int* /* compressed_size */
#endif
);
#ifdef __cplusplus
}
#endif
#endif /* ColormapComp_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,917 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#ifndef NXlib_H
#define NXlib_H
#ifdef __cplusplus
extern "C" {
#endif
#include <nx-X11/X.h>
#include <nx-X11/Xlib.h>
#include <nx/NX.h>
#include <nx/NXpack.h>
#include <nx/NXproto.h>
#include <nx/NXvars.h>
/*
* Maximum number of supported pack methods.
*/
#define NXNumberOfPackMethods 128
/*
* Assume this as the limit of resources that
* can be provided to the split and unpack
* requests.
*/
#define NXNumberOfResources 256
#define NXNoResource 256 + 1
#define NXAnyResource 256 + 2
/*
* Initialize the internal structures used by
* the library. Should be executed again after
* having reopened the display.
*/
extern int NXInitDisplay(
#if NeedFunctionPrototypes
Display* /* display */
#endif
);
/*
* Reset all the internal structures. Should be
* executed after closing the display.
*/
extern int NXResetDisplay(
#if NeedFunctionPrototypes
Display* /* display */
#endif
);
/*
* Set the NX display flush policy. The policy can
* be either NXFlushDeferred or NXFlushImmediate.
*/
extern int NXSetDisplayPolicy(
#if NeedFunctionPrototypes
Display* /* display */,
int /* policy */
#endif
);
/*
* Set the display output buffer size.
*/
extern int NXSetDisplayBuffer(
#if NeedFunctionPrototypes
Display* /* display */,
int /* size */
#endif
);
/*
* If set, the Popen() function in the X server
* will remove the LD_LIBRARY_PATH variable from
* the environment before calling the execl()
* function on the child process. The function
* returns the previous value.
*/
extern int NXUnsetLibraryPath(
#if NeedFunctionPrototypes
int /* value */
#endif
);
/*
* If the parameter is true, the Xlib I/O error
* handler will return, instead of quitting the
* program. The function returns the previous
* value.
*/
extern int NXHandleDisplayError(
#if NeedFunctionPrototypes
int /* value */
#endif
);
/*
* Shutdown the display descriptor and force Xlib
* to set the I/O error flag.
*/
extern Bool NXForceDisplayError(
#if NeedFunctionPrototypes
Display* /* display */
#endif
);
/*
* Check the value of the XlibDisplayIOError flag.
* If not set, try to call the display error hand-
* ler to give to the application a chance to see
* whether it needs to close the connection.
*/
extern int NXDisplayError(
#if NeedFunctionPrototypes
Display* /* display */
#endif
);
/*
* Query the number of bytes readable from the
* display connection.
*/
extern int NXDisplayReadable(
#if NeedFunctionPrototypes
Display* /* display */
#endif
);
/*
* Query the number of the outstanding bytes to
* flush to the display connection.
*/
extern int NXDisplayFlushable(
#if NeedFunctionPrototypes
Display* /* display */
#endif
);
/*
* Return a value between 0 and 9 indicating the
* congestion level of the NX transport based on
* the tokens remaining. A value of 9 means that
* the link is congested and no further data can
* be sent.
*/
extern int NXDisplayCongestion(
#if NeedFunctionPrototypes
Display* /* display */
#endif
);
/*
* Flush the Xlib display buffer and/or the
* outstanding data accumulated by the NX
* transport.
*/
extern int NXFlushDisplay(
#if NeedFunctionPrototypes
Display* /* display */,
int /* what */
#endif
);
/*
* Public interfaces used to set the handlers.
* They all return the previous handler.
*/
extern NXDisplayErrorPredicate NXSetDisplayErrorPredicate(
#if NeedFunctionPrototypes
NXDisplayErrorPredicate /* predicate */
#endif
);
/*
* Called when the display blocks waiting to read or
* write more data.
*/
extern NXDisplayBlockHandler NXSetDisplayBlockHandler(
#if NeedFunctionPrototypes
NXDisplayBlockHandler /* handler */
#endif
);
/*
* Called after more data is written to the display.
* When the NX transport is running, data may be queued
* until an explicit flush.
*/
extern NXDisplayWriteHandler NXSetDisplayWriteHandler(
#if NeedFunctionPrototypes
NXDisplayWriteHandler /* handler */
#endif
);
/*
* Called after more data is sent to the remote proxy.
*
* Here the display pointer is passed as the second
* parameter to make clear that the function does not
* tie the callback to the display, but, similarly to
* all the Xlib error handlers, to a global variable
* shared by all the Xlib functions. The display
* pointer will be passed back by nxcomp at the time
* it will call the handler. This is because nxcomp
* doesn't have access to the display structure.
*/
extern NXDisplayFlushHandler NXSetDisplayFlushHandler(
#if NeedFunctionPrototypes
NXDisplayFlushHandler /* handler */,
Display* /* display */
#endif
);
/*
* Get an arbitrary null terminated buffer to be added
* to the NX statistics.
*/
extern NXDisplayStatisticsHandler NXSetDisplayStatisticsHandler(
#if NeedFunctionPrototypes
NXDisplayStatisticsHandler /* handler */,
char ** /* buffer */
#endif
);
/*
* Redefine the function called by Xlib in the case of
* an out-of-order sequence number received in the X
* protocol stream.
*/
extern NXLostSequenceHandler NXSetLostSequenceHandler(
#if NeedFunctionPrototypes
NXLostSequenceHandler /* handler */
#endif
);
/*
* The agent should get the NX parameters at startup, just after
* having opened the display. If the agent is not able to satisfy
* the pack method set by user (because a method is not applica-
* ble, it is not supported by the remote or it simply requires a
* screen depth greater than the depth available), it should fall
* back to the nearest method of the same type.
*/
extern Status NXGetControlParameters(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int* /* link_type */,
unsigned int* /* local_major */,
unsigned int* /* local_minor */,
unsigned int* /* local_patch */,
unsigned int* /* remote_major */,
unsigned int* /* remote_minor */,
unsigned int* /* remote_patch */,
int* /* frame_timeout */,
int* /* ping_timeout */,
int* /* split_mode */,
int* /* split_size */,
unsigned int* /* pack_method */,
unsigned int* /* pack_quality */,
int* /* data_level */,
int* /* stream_level */,
int* /* delta_level */,
unsigned int* /* load_cache */,
unsigned int* /* save_cache */,
unsigned int* /* startup_cache */
#endif
);
/*
* Which unpack methods are supported by the remote proxy?
*/
extern Status NXGetUnpackParameters(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int* /* entries */,
unsigned char[] /* supported_methods */
#endif
);
/*
* Query and enable shared memory support on path agent to X
* client proxy and X server proxy to real X server. At the
* moment only the path proxy to real X server is implemented.
* On return flags will say if support has been successfully
* activated. Segments will contain the XID associated to the
* shared memory blocks. A MIT-SHM compliant protocol is used
* between proxy and the real server, while a simplified
* version is used between the agent and the client proxy to
* accommodate both packed images and plain X bitmaps.
*/
extern Status NXGetShmemParameters(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int* /* enable_client */,
unsigned int* /* enable_server */,
unsigned int* /* client_segment */,
unsigned int* /* server_segment */,
unsigned int* /* client_size */,
unsigned int* /* server_size */
#endif
);
/*
* Get the path to the font server that can be used by the X
* server to tunnel the font connections across the NX link.
* The path actually represents the TCP port where the proxy
* on the NX client side is listening. The agent can tempora-
* rily enable the tunneling when it needs a font that is not
* available on the client, for example when the session is
* migrated from a different X server.
*/
extern Status NXGetFontParameters(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* path_length */,
char[] /* path_data */
#endif
);
/*
* This set of functions is used to leverage the image stream-
* ing capabilities built in nxcomp. An image can be streamed
* by sending a start-split message, followed by the X messages
* that will have to be split by the proxy, followed by an end-
* split closure. Usually, in the middle of a start-split/end-
* split sequence there will be a single PutImage() or PutPack-
* edImage(), that, in turn, can generate multiple partial
* requests, like a SetUnpackColormap() and SetUnpackAlpha()
* that will be later used to decompress the image to its ori-
* ginal form. Multiple requests may be also generated because
* of the maximum size of a X request being exceeded, so that
* Xlib has to divide the single image in multiple sub-image re-
* quests. The agent doesn't need to take care of these details
* but will rather have to track the result of the split opera-
* tion. By monitoring the notify events sent by the proxy, the
* agent will have to implement its own strategy to deal with
* the resources. For example, it will be able to:
*
* - Mark a drawable as dirty, if the image was not sent
* synchronously, in the main X oputput stream.
*
* - Choose to commit or discard the original image, at the
* time it will be recomposed at the remote side. This may
* include all the messages that were part of the split
* (the colormap, the alpha channel, etc.)
*
* - Mark the drawable as clean again, if the image was
* committed and the drawable didn't change in the mean-
* while.
*
* At the time the proxy receives the end-split, it reports the
* result of the operation to the agent. The agent will be able
* to identify the original split operation (the one referenced
* in the start-split/end-split sequence) by the small integer
* number (0-255) named 'resource' sent in the events.
*
* One of the following cases may be encountered:
*
*
* NXNoSplitNotify All messages were sent in the main out-
* put stream, so that no split actually
* took place.
*
* NXStartSplitNotify One or more messages were split, so,
* at discrection of the agent, the client
* may be suspended until the transferral
* is completed.
*
* NXCommitSplitNotify One of the requests that made up the
* split was recomposed. The agent should
* either commit the given request or tell
* the proxy to discard it.
*
* NXEndSplitNotify The split was duly completed. The agent
* can restart the client.
*
* NXEmptySplitNotify No more split operation are pending.
* The agent can use this information to
* implement specific strategies requiring
* that all messages have been recomposed
* at the remote end, like updating the
* drawables that were not synchronized
* because of the lazy encoding.
*
* The 'mode' field that is sent by the agent in the start-split
* request, determines the strategy that the proxy will adopt to
* deal with the image. If set to 'eager', the proxy will only
* split the messages whose size exceeds the split threshold (the
* current threshold can be found in the NXGetControlParameters()
* reply). If the mode is set to lazy, the proxy will split any
* image that would have generated an actual transfer of the data
* part (in practice all images that are not found in the cache).
* This second strategy can be leveraged by an agent to further
* reduce the bandwidth requirements. For example, by setting the
* mode to lazy and by monitoring the result, an agent can easi-
* ly verify if the drawable was successfully updated, mark the
* drawable if not, and synchronize it at later time.
*
* See NXproto.h for the definition of the available modes.
*/
extern unsigned int NXAllocSplit(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */
#endif
);
extern int NXStartSplit(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */,
unsigned int /* mode */
#endif
);
extern int NXEndSplit(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */
#endif
);
extern int NXCommitSplit(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */,
unsigned int /* propagate */,
unsigned char /* request */,
unsigned int /* position */
#endif
);
extern int NXAbortSplit(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */
#endif
);
extern int NXFinishSplit(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */
#endif
);
extern int NXFreeSplit(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */
#endif
);
extern int NXSetExposeParameters(
#if NeedFunctionPrototypes
Display* /* display */,
int /* expose */,
int /* graphics_expose */,
int /* no_expose */
#endif
);
extern int NXSetCacheParameters(
#if NeedFunctionPrototypes
Display* /* display */,
int /* enable_cache */,
int /* enable_split */,
int /* enable_save */,
int /* enable_load */
#endif
);
extern unsigned int NXAllocUnpack(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */
#endif
);
extern int NXSetUnpackGeometry(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */,
Visual* /* visual */
#endif
);
extern int NXSetUnpackColormap(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */,
unsigned int /* method */,
unsigned int /* entries */,
const char* /* data */,
unsigned int /* data_length */
#endif
);
extern int NXSetUnpackAlpha(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */,
unsigned int /* method */,
unsigned int /* entries */,
const char* /* data */,
unsigned int /* data_length */
#endif
);
extern int NXSetUnpackColormapCompat(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */,
unsigned int /* entries */,
const char* /* data */
#endif
);
extern int NXSetUnpackAlphaCompat(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */,
unsigned int /* entries */,
const char* /* data */
#endif
);
extern int NXFreeUnpack(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */
#endif
);
/*
* A packed image is a XImage but with
* offset field containing total amount
* of packed image data.
*/
typedef XImage NXPackedImage;
NXPackedImage *NXCreatePackedImage(
#if NeedFunctionPrototypes
Display* /* display */,
Visual* /* visual */,
unsigned int /* method */,
unsigned int /* depth */,
int /* format */,
char* /* data */,
int /* data_length */,
unsigned int /* width */,
unsigned int /* height */,
int /* bitmap_pad */,
int /* bytes_per_line */
#endif
);
extern int NXDestroyPackedImage(
#if NeedFunctionPrototypes
NXPackedImage* /* image */
#endif
);
NXPackedImage *NXPackImage(
#if NeedFunctionPrototypes
Display* /* display */,
XImage* /* src_image */,
unsigned int /* method */
#endif
);
NXPackedImage *NXInPlacePackImage(
#if NeedFunctionPrototypes
Display* /* display */,
XImage* /* src_image */,
unsigned int /* method */
#endif
);
/*
* GC is declared void * to get rid of mess
* with different GC definitions in some X
* server code (like in nxagent).
*/
extern int NXPutPackedImage(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */,
Drawable /* drawable */,
void* /* gc */,
NXPackedImage* /* image */,
unsigned int /* method */,
unsigned int /* depth */,
int /* src_x */,
int /* src_y */,
int /* dst_x */,
int /* dst_y */,
unsigned int /* width */,
unsigned int /* height */
#endif
);
/*
* Get multiple colors with a single call by
* pipelining X_AllocColor requests/replies.
*/
extern int NXAllocColors(
#if NeedFunctionPrototypes
Display* /* display */,
Colormap /* colormap */,
unsigned int /* entries */,
XColor[] /* screens_in_out */,
Bool [] /* flags allocation errors */
#endif
);
/*
* Encode the data in the given format.
*/
extern char *NXEncodeColormap(
#if NeedFunctionPrototypes
const char* /* src_data */,
unsigned int /* src_size */,
unsigned int* /* dst_size */
#endif
);
extern char *NXEncodeAlpha(
#if NeedFunctionPrototypes
const char* /* src_data */,
unsigned int /* src_size */,
unsigned int* /* dst_size */
#endif
);
extern NXPackedImage *NXEncodeRgb(
#if NeedFunctionPrototypes
XImage* /* src_image */,
unsigned int /* method */,
unsigned int /* quality */
#endif
);
extern NXPackedImage *NXEncodeRle(
#if NeedFunctionPrototypes
XImage* /* src_image */,
unsigned int /* method */,
unsigned int /* quality */
#endif
);
extern NXPackedImage *NXEncodeJpeg(
#if NeedFunctionPrototypes
XImage* /* src_image */,
unsigned int /* method */,
unsigned int /* quality */
#endif
);
typedef struct
{
long pixel;
int found;
} NXColorTable;
extern int NXEncodeColors(
#if NeedFunctionPrototypes
XImage* /* src_image */,
NXColorTable* /* color_table */,
int /* nb_max */
#endif
);
extern NXPackedImage *NXEncodePng(
#if NeedFunctionPrototypes
XImage* /* src_image */,
unsigned int /* method */,
unsigned int /* quality */
#endif
);
extern NXPackedImage *NXEncodeBitmap(
#if NeedFunctionPrototypes
XImage* /* src_image */,
unsigned int /* method */,
unsigned int /* quality */
#endif
);
extern int NXCleanImage(
#if NeedFunctionPrototypes
XImage*
#endif
);
extern void NXMaskImage(
#if NeedFunctionPrototypes
XImage* /* pointer to image to mask */ ,
unsigned int /* method */
#endif
);
extern int NXImageCacheSize;
extern void NXInitCache(
#if NeedFunctionPrototypes
Display* /* display */,
int /* entries in image cache */
#endif
);
extern void NXFreeCache(
#if NeedFunctionPrototypes
Display* /* display */
#endif
);
extern XImage *NXCacheFindImage(
#if NeedFunctionPrototypes
NXPackedImage* /* packed image to find */,
unsigned int* /* pointer to the pack method if found */,
unsigned char** /* pointer to the calculated MD5 if found */
#endif
);
extern int NXCacheAddImage(
#if NeedFunctionPrototypes
NXPackedImage* /* packed image to be added to the cache */,
unsigned int /* pack method of the image to add */,
unsigned char* /* pointer to MD5 of the original unpacked image */
#endif
);
extern int NXGetCollectImageResource(
#if NeedFunctionPrototypes
Display* /* display */
#endif
);
extern int NXCollectImage(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */,
Drawable /* drawable */,
int /* src_x */,
int /* src_y */,
unsigned int /* width */,
unsigned int /* height */,
unsigned long /* plane_mask */,
int /* format */
#endif
);
extern int NXGetCollectedImage(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */,
XImage** /* image */
#endif
);
extern int NXGetCollectPropertyResource(
#if NeedFunctionPrototypes
Display* /* display */
#endif
);
extern int NXCollectProperty(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */,
Window /* window */,
#ifdef XlibAtom
XlibAtom /* property */,
#else
Atom /* property */,
#endif
long /* long_offset */,
long /* long_length */,
Bool /* delete */,
#ifdef XlibAtom
XlibAtom /* req_type */
#else
Atom /* req_type */
#endif
#endif
);
extern int NXGetCollectedProperty(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */,
#ifdef XlibAtom
XlibAtom* /* actual_type_return */,
#else
Atom* /* actual_type_return */,
#endif
int* /* actual_format_return */,
unsigned long* /* nitems_return */,
unsigned long* /* bytes_after_return */,
unsigned char** /* data */
#endif
);
extern int NXGetCollectGrabPointerResource(
#if NeedFunctionPrototypes
Display* /* display */
#endif
);
extern int NXCollectGrabPointer(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */,
Window /* grab_window */,
Bool /* owner_events */,
unsigned int /* event_mask */,
int /* pointer_mode */,
int /* keyboard_mode */,
Window /* confine_to */,
Cursor /* cursor */,
Time /* time */
#endif
);
extern int NXGetCollectedGrabPointer(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */,
int* /* status */
#endif
);
extern int NXGetCollectInputFocusResource(
#if NeedFunctionPrototypes
Display* /* display */
#endif
);
extern int NXCollectInputFocus(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */
#endif
);
extern int NXGetCollectedInputFocus(
#if NeedFunctionPrototypes
Display* /* display */,
unsigned int /* resource */,
Window* /* focus_return */,
int* /* revert_to_return */
#endif
);
#ifdef __cplusplus
}
#endif
#endif /* NXlib_H */

View File

@@ -0,0 +1,49 @@
NULL =
#include <Server.tmpl>
SRCS = \
Alpha.c \
Bitmap.c \
Clean.c \
Colormap.c \
Compext.c \
Jpeg.c \
Mask.c \
Png.c \
Rgb.c \
Rle.c \
Z.c \
$(NULL)
OBJS = \
Alpha.o \
Bitmap.o \
Clean.o \
Colormap.o \
Compext.o \
Jpeg.o \
Mask.o \
Png.o \
Rgb.o \
Rle.o \
Z.o \
$(NULL)
INCLUDES = -I$(SERVERSRC)/include \
-I$(XBUILDINCDIR) \
-I../../../../../lib/include/X11 \
`pkg-config --cflags-only-I pixman-1` \
$$(pkg-config --exists 'zlib' >/dev/null 2>&1 && pkg-config --cflags-only-I 'zlib') \
`pkg-config --cflags-only-I libpng` \
$(NULL)
LINTLIBS = $(SERVERSRC)/dix/llib-ldix.ln \
$(NULL)
NormalLibraryObjectRule()
NormalLibraryTarget(compext,$(OBJS))
LintLibraryTarget(compext,$(SRCS))
NormalLintTarget($(SRCS))
DependTarget()

View File

@@ -0,0 +1,482 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <nx-X11/X.h>
#include <nx-X11/Xlib.h>
#include <nx-X11/Xmd.h>
#include <jpeglib.h>
#include "Compext.h"
#include "Mask.h"
#include "Jpeg.h"
#include "../Utils.h"
#define PANIC
#define WARNING
#undef TEST
#undef DEBUG
#define JPEG_DEST_SIZE(width, height) ((width) * 3 * (height) + 1024)
/*
* Local function prototypes.
*/
static void PrepareRowForJpeg(CARD8 *dst, int y, int count);
static void PrepareRowForJpeg24(CARD8 *dst, int y, int count);
static void PrepareRowForJpeg16(CARD8 *dst, int y, int count);
static void PrepareRowForJpeg32(CARD8 *dst, int y, int count);
static int JpegEmptyOutputBuffer(j_compress_ptr cinfo);
static void JpegInitDestination(j_compress_ptr cinfo);
static void JpegTermDestination(j_compress_ptr cinfo);
static void JpegSetDstManager(j_compress_ptr cinfo);
/*
* Quality levels.
*/
static int jpegQuality[10] = {20, 30, 40, 50, 55, 60, 65, 70, 75, 80};
/*
* Image characteristics.
*/
static int bytesPerLine;
static CARD8 bitsPerPixel;
static CARD16 redMax, greenMax, blueMax;
static CARD8 redShift, greenShift, blueShift;
static int byteOrder;
/*
* Other variables used for the Jpeg
* encoding.
*/
static char *jpegBeforeBuf = NULL;
static char *jpegCompBuf;
static int jpegCompBufSize;
static int jpegError;
static int jpegDstDataLen;
static struct jpeg_destination_mgr jpegDstManager;
/*
* Just for debugging purpose.
*/
#ifdef DEBUG
static int jpegId;
static char jpegName[10];
static FILE *jpegFile;
#endif
/*
* Function declarations
*/
char *JpegCompressData(XImage *image, int level, int *compressed_size)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
CARD8 *srcBuf;
JSAMPROW rowPointer[1];
int dy, w, h;
*compressed_size = 0;
/*
* Initialize the image stuff
*/
bitsPerPixel = image -> bits_per_pixel;
bytesPerLine = image -> bytes_per_line;
byteOrder = image -> byte_order;
#ifdef TEST
fprintf(stderr, "******JpegCompressData: Image byte order [%d] bitmap bit order [%d].\n",
image -> byte_order, image -> bitmap_bit_order);
fprintf(stderr, "******JpegCompressData: Bits per pixel [%d] bytes per line [%d].\n",
bitsPerPixel, bytesPerLine);
#endif
redShift = FindLSB(image -> red_mask) - 1;
greenShift = FindLSB(image -> green_mask) - 1;
blueShift = FindLSB(image -> blue_mask) - 1;
#ifdef TEST
fprintf(stderr, "******JpegCompressData: Red mask [0x%lx] green mask [0x%lx] blue mask [0x%lx].\n",
image -> red_mask, image -> green_mask, image -> blue_mask);
fprintf(stderr, "******JpegCompressData: Red shift [%d] green shift [%d] blue shift [%d].\n",
redShift, greenShift, blueShift);
#endif
redMax = image -> red_mask >> redShift;
greenMax = image -> green_mask >> greenShift;
blueMax = image -> blue_mask >> blueShift;
#ifdef TEST
fprintf(stderr, "******JpegCompressData: Red max [0x%x] green max [0x%x] blue max [0x%x].\n",
redMax, greenMax, blueMax);
#endif
w = image -> width;
h = image -> height;
jpegBeforeBuf = image -> data;
#ifdef DEBUG
fprintf(stderr, "******JpegCompressData: Width [%d] height [%d] level [%d].\n",
w, h, level);
#endif
if (bitsPerPixel == 1 ||
bitsPerPixel == 8)
{
#ifdef PANIC
fprintf(stderr, "******JpegCompressData: PANIC! Invalid bits per pixel [%d].\n",
bitsPerPixel);
#endif
return NULL;
}
/*
* Allocate space for one line of the
* resulting image, 3 bytes per pixel.
*/
#ifdef DEBUG
fprintf(stderr, "******JpegCompressData: Allocating [%d] bytes for the scanline.\n",
w * 3);
#endif
srcBuf = (CARD8 *) malloc(w * 3);
if (srcBuf == NULL)
{
#ifdef PANIC
fprintf(stderr, "******JpegCompressData: PANIC! Cannot allocate [%d] bytes.\n",
w * 3);
#endif
return NULL;
}
rowPointer[0] = srcBuf;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
cinfo.image_width = w;
cinfo.image_height = h;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, jpegQuality[level], 1);
/*
* Allocate memory for the destination
* buffer.
*/
jpegCompBufSize = JPEG_DEST_SIZE(w, h);
#ifdef TEST
fprintf(stderr, "******JpegCompressData: Allocating [%d] bytes for the destination data.\n",
jpegCompBufSize);
#endif
jpegCompBuf = malloc(jpegCompBufSize);
if (jpegCompBuf == NULL)
{
#ifdef PANIC
fprintf(stderr, "******JpegCompressData: PANIC! Error allocating [%d] bytes for the Jpeg data.\n",
jpegCompBufSize);
#endif
return NULL;
}
JpegSetDstManager(&cinfo);
jpeg_start_compress(&cinfo, 1);
#ifdef DEBUG
fprintf(stderr, "******JpegCompressedData: Initialization finished.\n");
#endif
for (dy = 0; dy < h; dy++)
{
PrepareRowForJpeg(srcBuf, dy, w);
jpeg_write_scanlines(&cinfo, rowPointer, 1);
if (jpegError != 0)
{
break;
}
}
#ifdef DEBUG
fprintf(stderr, "******JpegCompressedData: Compression finished. Lines handled [%d,%d]. Error is [%d].\n",
dy, h, jpegError);
#endif
if (jpegError == 0)
{
jpeg_finish_compress(&cinfo);
}
jpeg_destroy_compress(&cinfo);
free((char *) srcBuf);
if (jpegError != 0)
{
#ifdef PANIC
fprintf(stderr, "******JpegCompressedData: PANIC! Compression failed. Error is [%d].\n",
jpegError);
#endif
SAFE_free(jpegCompBuf);
return NULL;
}
/*
* Check the size of the resulting data.
*/
if (jpegDstDataLen > 0)
{
/*
* Save the image on disk to help with
* the debug.
*/
#ifdef DEBUG
int i = 0;
fprintf(stderr, "******JpegCompressedData: Compressed size [%d].\n",
jpegDstDataLen);
jpegId++;
sprintf(jpegName, "jpeg%d", jpegId);
jpegFile = fopen(jpegName, "w");
for (i = 0; i < jpegDstDataLen; i++)
{
fprintf(jpegFile, "%c", *(jpegCompBuf + i));
}
fclose(jpegFile);
#endif
*compressed_size = jpegDstDataLen;
return jpegCompBuf;
}
else
{
#ifdef PANIC
fprintf(stderr, "******JpegCompressedData: PANIC! Invalid size of the compressed data [%d].\n",
jpegDstDataLen);
#endif
SAFE_free(jpegCompBuf);
return NULL;
}
}
void PrepareRowForJpeg(CARD8 *dst, int y, int count)
{
if (bitsPerPixel == 32)
{
if (redMax == 0xff &&
greenMax == 0xff &&
blueMax == 0xff)
{
PrepareRowForJpeg24(dst, y, count);
}
else
{
PrepareRowForJpeg32(dst, y, count);
}
}
else if (bitsPerPixel == 24)
{
memcpy(dst, jpegBeforeBuf + y * bytesPerLine, count * 3);
}
else
{
/*
* 16 bpp assumed.
*/
PrepareRowForJpeg16(dst, y, count);
}
}
void PrepareRowForJpeg24(CARD8 *dst, int y, int count)
{
CARD8 *fbptr;
CARD32 pix;
fbptr = (CARD8 *) (jpegBeforeBuf + y * bytesPerLine);
while (count--)
{
if (byteOrder == LSBFirst)
{
pix = (CARD32) *(fbptr + 2);
pix = (pix << 8) | (CARD32) *(fbptr+1);
pix = (pix << 8) | (CARD32) *fbptr;
}
else
{
pix = (CARD32) *(fbptr + 1);
pix = (pix << 8) | (CARD32) *(fbptr + 2);
pix = (pix << 8) | (CARD32) *(fbptr + 3);
}
*dst++ = (CARD8)(pix >> redShift);
*dst++ = (CARD8)(pix >> greenShift);
*dst++ = (CARD8)(pix >> blueShift);
fbptr+=4;
}
}
#define DEFINE_JPEG_GET_ROW_FUNCTION(bpp) \
\
void PrepareRowForJpeg##bpp(CARD8 *dst, int y, int count) \
{ \
CARD8 *fbptr; \
CARD##bpp pix; \
int inRed, inGreen, inBlue; \
int i; \
\
fbptr = (CARD8 *) (jpegBeforeBuf + y * bytesPerLine); \
\
while (count--) \
{ \
pix = 0; \
\
if (byteOrder == LSBFirst) \
{ \
for (i = (bpp >> 3) - 1; i >= 0; i--) \
{ \
pix = (pix << 8) | (CARD32) *(fbptr + i); \
} \
} \
else \
{ \
for (i = 0; i < (bpp >> 3); i++) \
{ \
pix = (pix << 8) | (CARD32) *(fbptr + i); \
} \
} \
\
fbptr += bpp >> 3; \
\
inRed = (int) \
(pix >> redShift & redMax); \
inGreen = (int) \
(pix >> greenShift & greenMax); \
inBlue = (int) \
(pix >> blueShift & blueMax); \
\
*dst++ = (CARD8)((inRed * 255 + redMax / 2) / \
redMax); \
*dst++ = (CARD8)((inGreen * 255 + greenMax / 2) / \
greenMax); \
*dst++ = (CARD8)((inBlue * 255 + blueMax / 2) / \
blueMax); \
} \
}
DEFINE_JPEG_GET_ROW_FUNCTION(16)
DEFINE_JPEG_GET_ROW_FUNCTION(32)
/*
* Destination manager implementation for JPEG library.
*/
void JpegInitDestination(j_compress_ptr cinfo)
{
jpegError = 0;
jpegDstManager.next_output_byte = (JOCTET *) jpegCompBuf;
jpegDstManager.free_in_buffer = (size_t) jpegCompBufSize;
}
int JpegEmptyOutputBuffer(j_compress_ptr cinfo)
{
jpegError = 1;
jpegDstManager.next_output_byte = (JOCTET *) jpegCompBuf;
jpegDstManager.free_in_buffer = (size_t) jpegCompBufSize;
return 1;
}
void JpegTermDestination(j_compress_ptr cinfo)
{
jpegDstDataLen = jpegCompBufSize - jpegDstManager.free_in_buffer;
}
void JpegSetDstManager(j_compress_ptr cinfo)
{
jpegDstManager.init_destination = JpegInitDestination;
jpegDstManager.empty_output_buffer = JpegEmptyOutputBuffer;
jpegDstManager.term_destination = JpegTermDestination;
cinfo -> dest = &jpegDstManager;
}

View File

@@ -0,0 +1,46 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#ifndef Jpeg_H
#define Jpeg_H
#ifdef __cplusplus
extern "C" {
#endif
extern char *JpegCompressData(
#if NeedFunctionPrototypes
XImage* /* image */,
int /* level */,
int* /* compressed_size */
#endif
);
#ifdef __cplusplus
}
#endif
#endif /* Jpeg_H */

View File

@@ -0,0 +1,802 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#include <stdio.h>
#include <nx-X11/Xlib.h>
#include <nx/NXpack.h>
#include "Mask.h"
#define PANIC
#define WARNING
#undef TEST
#undef DEBUG
/*
* Try first to reduce to a white or black
* pixel. If not possible, apply the mask.
* Note that correction is applied at the
* time pixel is unpacked.
*/
#define MaskPixel(red, green, blue, mask) \
\
if (red > mask -> white_threshold && \
green > mask -> white_threshold && \
blue > mask -> white_threshold) \
{ \
red = green = blue = 0xff; \
} \
else if (red < mask -> black_threshold && \
green < mask -> black_threshold && \
blue < mask -> black_threshold) \
{ \
red = green = blue = 0x00; \
} \
else \
{ \
red = red & mask -> color_mask; \
green = green & mask -> color_mask; \
blue = blue & mask -> color_mask; \
}
int MaskImage(const ColorMask *mask, XImage *src_image, XImage *dst_image)
{
unsigned long pixel;
register unsigned int red;
register unsigned int green;
register unsigned int blue;
register unsigned long data_size;
register unsigned int i;
data_size = (src_image -> bytes_per_line * src_image -> height) >> 2;
#ifdef TEST
fprintf(stderr, "******MaskImage: Going to mask image with [%d] bits per pixel.\n",
src_image -> bits_per_pixel);
#endif
if (src_image -> bits_per_pixel == 24 || src_image -> bits_per_pixel == 32)
{
register unsigned char *pixel_addr;
for (i = 0; i < data_size; i++)
{
pixel = ((unsigned long *) src_image -> data)[i];
pixel_addr = (unsigned char *) &pixel;
red = pixel_addr[2];
green = pixel_addr[1];
blue = pixel_addr[0];
#ifdef DEBUG
fprintf(stderr, "******MaskImage: 24/32 bits original R [%d] G [%d] B [%d] A [%d].\n",
red, green, blue, pixel_addr[3]);
#endif
MaskPixel(red, green, blue, mask);
#ifdef DEBUG
fprintf(stderr, "******MaskImage: 24/32 bits masked R [%d] G [%d] B [%d] A [%d].\n",
red, green, blue, pixel_addr[3]);
#endif
#ifdef DEBUG
fprintf(stderr, "******MaskImage: 24/32 bits pixel 0x%lx", pixel);
#endif
pixel_addr[2] = red;
pixel_addr[1] = green;
pixel_addr[0] = blue;
((unsigned long*)dst_image -> data)[i] = pixel;
#ifdef DEBUG
fprintf(stderr, " -> 0x%lx\n", pixel);
#endif
}
return 1;
}
else if (src_image -> bits_per_pixel == 16)
{
/*
* FIXME: Masking doesn't work in 16 bpp.
*
unsigned long src_addr, *dst_addr;
unsigned short *src_pixels_addr, *dst_pixels_addr;
for (i = 0; i < data_size; i++)
{
src_addr = ((unsigned long *)src_image -> data)[i];
dst_addr = (unsigned long *)((unsigned long *)dst_image -> data + i);
src_pixels_addr = ((unsigned short *) &src_addr);
dst_pixels_addr = ((unsigned short *) dst_addr);
red = (src_pixels_addr[0] & src_image -> red_mask) >> 8;
green = (src_pixels_addr[0] & src_image -> green_mask) >> 3;
blue = (src_pixels_addr[0] & src_image -> blue_mask) << 3;
#ifdef DEBUG
fprintf(stderr, "******MaskImage: 16 bits original R [%d] G [%d] B [%d].\n",
red, green, blue);
#endif
MaskPixel(red, green, blue, mask);
#ifdef DEBUG
fprintf(stderr, "******MaskImage: 16 bits masked R [%d] G [%d] B [%d].\n",
red, green, blue);
#endif
dst_pixels_addr[0] = ((red << 8) & src_image -> red_mask) |
((green << 3) & src_image -> green_mask) |
((blue >> 3) & src_image -> blue_mask);
#ifdef DEBUG
fprintf(stderr, "******MaskImage: 16 bits pixel 0x%x", dst_pixels_addr[0]);
#endif
red = (src_pixels_addr[1] & src_image -> red_mask) >> 8;
green = (src_pixels_addr[1] & src_image -> green_mask) >> 3;
blue = (src_pixels_addr[1] & src_image -> blue_mask) << 3;
#ifdef DEBUG
fprintf(stderr, "******MaskImage: 16 bits original R [%d] G [%d] B [%d].\n",
red, green, blue);
#endif
MaskPixel(red, green, blue, mask);
#ifdef DEBUG
fprintf(stderr, "******MaskImage: 16 bits masked R [%d] G [%d] B [%d].\n",
red, green, blue);
#endif
dst_pixels_addr[1] = ((red << 8) & src_image -> red_mask) |
((green << 3) & src_image -> green_mask) |
((blue >> 3) & src_image -> blue_mask);
#ifdef DEBUG
fprintf(stderr, "******MaskImage: 16 bits pixel 0x%x", dst_pixels_addr[0]);
#endif
}
if (dst_image -> width & 0x00000001)
{
int card32_per_line;
int i;
card32_per_line = dst_image -> bytes_per_line >> 2;
for (i = 0; i < dst_image -> height;)
{
((CARD32 *) dst_image -> data)[(++i * card32_per_line) - 1] &= 0x0000ffff;
}
}
*
* End of FIXME.
*/
}
else
{
#ifdef TEST
fprintf(stderr, "******MaskImage: PANIC! Cannot apply mask with [%d] bits per pixel.\n",
src_image -> bits_per_pixel);
#endif
return 0;
}
return 1;
}
int MaskInPlaceImage(const ColorMask *mask, XImage *image)
{
unsigned long pixel;
register unsigned int red;
register unsigned int green;
register unsigned int blue;
register unsigned int i;
register unsigned long data_size;
data_size = (image -> bytes_per_line * image -> height)>>2;
#ifdef TEST
fprintf(stderr, "******MaskInPlaceImage: Going to mask image with [%d] bits per pixel.\n",
image -> bits_per_pixel);
#endif
if (image -> bits_per_pixel == 24 || image -> bits_per_pixel == 32)
{
register unsigned char *pixel_addr;
for (i = 0; i < data_size; i++)
{
pixel = ((unsigned long *) image -> data)[i];
pixel_addr = (unsigned char *) &pixel;
red = pixel_addr[2];
green = pixel_addr[1];
blue = pixel_addr[0];
#ifdef DEBUG
fprintf(stderr, "******MaskInPlaceImage: 24/32 bits original R [%d] G [%d] B [%d] A [%d].\n",
red, green, blue, pixel_addr[3]);
#endif
MaskPixel(red, green, blue, mask);
#ifdef DEBUG
fprintf(stderr, "******MaskInPlaceImage: 24/32 bits masked R [%d] G [%d] B [%d] A [%d].\n",
red, green, blue, pixel_addr[3]);
#endif
#ifdef DEBUG
fprintf(stderr, "******MaskInPlaceImage: 24/32 bits pixel 0x%lx", pixel);
#endif
pixel_addr[2] = red;
pixel_addr[1] = green;
pixel_addr[0] = blue;
((unsigned long *) image -> data)[i] = pixel;
#ifdef DEBUG
fprintf(stderr, " -> 0x%lx\n", pixel);
#endif
}
return 1;
}
else if (image -> bits_per_pixel == 16)
{
/*
* FIXME: Mask doesn't still work for 16 bits.
*
unsigned long addr;
register unsigned short *pixels_addr;
for (i = 0; i < data_size; i++)
{
addr = ((unsigned long *) image -> data)[i];
pixels_addr = ((unsigned short *) &addr);
red = (pixels_addr[0] & image -> red_mask) >> 8;
green = (pixels_addr[0] & image -> green_mask) >> 3;
blue = (pixels_addr[0] & image -> blue_mask) << 3;
#ifdef DEBUG
fprintf(stderr, "******MaskInPlaceImage: 16 bits original R [%d] G [%d] B [%d].\n",
red, green, blue);
#endif
MaskPixel(red, green, blue, mask);
#ifdef DEBUG
fprintf(stderr, "******MaskInPlaceImage: 16 bits masked R [%d] G [%d] B [%d].\n",
red, green, blue);
#endif
pixels_addr[0] = ((red << 8) & image -> red_mask) |
((green << 3) & image -> green_mask) |
((blue >> 3) & image -> blue_mask);
#ifdef DEBUG
fprintf(stderr, "******MaskInPlaceImage: 16 bits pixel 0x%x", pixels_addr[0]);
#endif
red = (pixels_addr[1] & image -> red_mask) >> 8;
green = (pixels_addr[1] & image -> green_mask) >> 3;
blue = (pixels_addr[1] & image -> blue_mask) << 3;
#ifdef DEBUG
fprintf(stderr, "******MaskInPlaceImage: 16 bits original R [%d] G [%d] B [%d].\n",
red, green, blue);
#endif
MaskPixel(red, green, blue, mask);
#ifdef DEBUG
fprintf(stderr, "******MaskInPlaceImage: 16 bits masked R [%d] G [%d] B [%d].\n",
red, green, blue);
#endif
pixels_addr[1] = ((red << 8) & image -> red_mask) |
((green << 3) & image -> green_mask) |
((blue >> 3) & image -> blue_mask);
#ifdef DEBUG
fprintf(stderr, "******MaskInPlaceImage: 16 bits pixel 0x%x", pixels_addr[1]);
#endif
}
if (image -> width & 0x00000001)
{
int card32_per_line;
int i;
card32_per_line = image -> bytes_per_line >> 2;
for (i = 0; i < image -> height;)
{
((CARD32 *) image -> data)[(++i * card32_per_line) - 1] &= 0x0000ffff;
}
}
*
* End of FIXME.
*/
}
else
{
#ifdef TEST
fprintf(stderr, "******MaskImage: PANIC! Cannot apply mask with [%d] bits per pixel.\n",
image -> bits_per_pixel);
#endif
return 0;
}
return 1;
}
static int Pack16To8(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
{
unsigned short *src_pixel = (unsigned short *) src_image -> data;
unsigned char *dst_pixel = (unsigned char *) dst_image -> data;
#ifdef DEBUG
unsigned int counter = 0;
#endif
while (src_pixel < ((unsigned short *) (src_image -> data + src_data_size)))
{
#ifdef DEBUG
fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
counter, *src_pixel, (*src_pixel & 0xc000) >> 8,
((*src_pixel & 0x600) >> 3), (*src_pixel & 0x18) << 3);
#endif
if (*src_pixel == 0x0)
{
*dst_pixel = 0x0;
}
else if (*src_pixel == 0xffff)
{
*dst_pixel = 0xff;
}
else
{
*dst_pixel = ((*src_pixel & 0xc000) >> 10) |
((*src_pixel & 0x600) >> 7) |
((*src_pixel & 0x18) >> 3);
}
#ifdef DEBUG
fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n",
counter++, *dst_pixel);
#endif
src_pixel++;
dst_pixel++;
}
return 1;
}
static int Pack24To8(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
{
unsigned char *src_pixel = (unsigned char *) src_image -> data;
unsigned char *dst_pixel = (unsigned char *) dst_image -> data;
int i;
unsigned int bytes_per_line = src_image -> bytes_per_line;
unsigned char *end_of_line = (unsigned char *) (src_pixel + bytes_per_line);
#ifdef DEBUG
unsigned int counter = 0;
#endif
for (i = 0; i < src_image -> height; i++ )
{
#ifdef DEBUG
fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x%x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
counter, src_pixel[0], src_pixel[1], src_pixel[2], src_pixel[0] & 0xc0,
src_pixel[1] & 0xc0, src_pixel[2] & 0xc0);
#endif
while(src_pixel < end_of_line - 2)
{
if (src_pixel[0] == 0x00 &&
src_pixel[1] == 0x00 &&
src_pixel[2] == 0x00)
{
*dst_pixel = 0x0;
}
else if (src_pixel[0] == 0xff &&
src_pixel[1] == 0xff &&
src_pixel[2] == 0xff)
{
*dst_pixel = 0xff;
}
else
{
/*
* Pixel layout:
*
* 24 bit RRRRR000 GGGGG000 BBBBB000 -> 8 bit 00RRGGBB
*/
*dst_pixel = (src_pixel[0] & 0xc0) >> 2 |
((src_pixel[1] & 0xc0) >> 4) |
((src_pixel[2] & 0xc0) >> 6);
}
#ifdef DEBUG
fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n",
counter++, *dst_pixel);
#endif
src_pixel += 3;
dst_pixel += 1;
}
src_pixel = end_of_line;
end_of_line += bytes_per_line;
}
return 1;
}
static int Pack24To16(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
{
unsigned char *src_pixel = (unsigned char *) src_image -> data;
unsigned short *dst_pixel = (unsigned short *) dst_image -> data;
int i;
unsigned int bytes_per_line = src_image -> bytes_per_line;
unsigned char *end_of_line = (unsigned char *) (src_pixel + bytes_per_line);
#ifdef DEBUG
unsigned int counter = 0;
#endif
for (i = 0; i < src_image -> height; i++ )
{
while(src_pixel < end_of_line - 2)
{
#ifdef DEBUG
fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x%x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
counter, src_pixel[0], src_pixel[1], src_pixel[2], src_pixel[0] & 0xf8,
src_pixel[1] & 0xf8, src_pixel[2] & 0xf8);
#endif
if (src_pixel[0] == 0x00 &&
src_pixel[1] == 0x00 &&
src_pixel[2] == 0x00)
{
*dst_pixel = 0x0;
}
else if (src_pixel[0] == 0xff &&
src_pixel[1] == 0xff &&
src_pixel[2] == 0xff)
{
*dst_pixel = 0xffff;
}
else
{
/*
* Pixel layout:
*
* 24 bit RRRRR000 GGGGG000 BBBBB000 -> 16 bit 0RRRRRGG GGGBBBBB
*/
*dst_pixel = ((src_pixel[0] & 0xf8) << 7) |
((src_pixel[1] & 0xf8) << 2) |
((src_pixel[2] & 0xf8) >> 3);
}
#ifdef DEBUG
fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n",
counter++, *dst_pixel);
#endif
src_pixel += 3;
dst_pixel += 1;
}
src_pixel = end_of_line;
end_of_line += bytes_per_line;
}
return 1;
}
static int Pack32To8(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
{
unsigned int *src_pixel = (unsigned int *) src_image -> data;
unsigned char *dst_pixel = (unsigned char *) dst_image -> data;
#ifdef DEBUG
unsigned int counter = 0;
#endif
while (src_pixel < ((unsigned int *) (src_image -> data + src_data_size)))
{
#ifdef DEBUG
fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
counter, *src_pixel, (*src_pixel & 0xc00000),
(*src_pixel & 0xc000), (*src_pixel & 0xc0));
#endif
if (*src_pixel == 0x0)
{
*dst_pixel = 0x0;
}
else if (*src_pixel == 0xffffff)
{
*dst_pixel = 0xff;
}
else
{
*dst_pixel = ((*src_pixel & 0xc00000) >> 18) |
((*src_pixel & 0xc000) >> 12) |
((*src_pixel & 0xc0) >> 6);
}
#ifdef DEBUG
fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n",
counter++, *dst_pixel);
#endif
src_pixel++;
dst_pixel++;
}
return 1;
}
static int Pack32To16(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
{
unsigned int *src_pixel = (unsigned int *) src_image -> data;
unsigned short *dst_pixel = (unsigned short *) dst_image -> data;
#ifdef DEBUG
unsigned int counter = 0;
#endif
while (src_pixel < ((unsigned int *) (src_image -> data + src_data_size)))
{
#ifdef DEBUG
fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
counter, *src_pixel, (*src_pixel & 0xf80000),
(*src_pixel & 0xf800), (*src_pixel & 0xf8));
#endif
if (*src_pixel == 0x0)
{
*dst_pixel = 0x0;
}
else if (*src_pixel == 0xffffff)
{
*dst_pixel = 0xffff;
}
else
{
*dst_pixel = ((*src_pixel & 0xf80000) >> 9) |
((*src_pixel & 0xf800) >> 6) |
((*src_pixel & 0xf8) >> 3);
}
#ifdef DEBUG
fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n",
counter++, *dst_pixel);
#endif
src_pixel++;
dst_pixel++;
}
return 1;
}
static int Pack32To24(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
{
unsigned int *src_pixel = (unsigned int *) src_image -> data;
unsigned char *dst_pixel = (unsigned char *) dst_image -> data;
#ifdef DEBUG
unsigned int counter = 0;
#endif
while (src_pixel < ((unsigned int *) (src_image -> data + src_data_size)))
{
#ifdef DEBUG
fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
counter, *src_pixel, ((*src_pixel & 0xff0000) >> 16),
((*src_pixel & 0x00ff00) >> 8), (*src_pixel & 0xff));
#endif
if (*src_pixel == 0x0)
{
dst_pixel[0] = dst_pixel[1] = dst_pixel[2] = 0x0;
}
else if (*src_pixel == 0xffffff)
{
dst_pixel[0] = dst_pixel[1] = dst_pixel[2] = 0xff;
}
else
{
dst_pixel[0] = (*src_pixel & 0xff0000) >> 16;
dst_pixel[1] = (*src_pixel & 0x00ff00) >> 8;
dst_pixel[2] = (*src_pixel & 0x0000ff);
}
#ifdef DEBUG
fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x], [0x%x], [0x%x].\n",
counter++, dst_pixel[0], dst_pixel[1], dst_pixel[2]);
#endif
src_pixel += 1;
dst_pixel += 3;
}
return 1;
}
int PackImage(unsigned int method, unsigned int src_data_size, XImage *src_image,
unsigned int dst_data_size, XImage *dst_image)
{
unsigned int src_bits_per_pixel;
unsigned int dst_bits_per_pixel;
src_bits_per_pixel = src_image -> bits_per_pixel;
dst_bits_per_pixel = MethodBitsPerPixel(method);
#ifdef TEST
fprintf(stderr, "******PackImage: Source bits per pixel [%d], destination bits per pixel [%d].\n",
src_bits_per_pixel, dst_bits_per_pixel);
fprintf(stderr, "******PackImage: Source data size [%d], destination data size [%d].\n",
src_data_size, dst_data_size);
#endif
if (dst_bits_per_pixel >= src_bits_per_pixel)
{
#ifdef PANIC
fprintf(stderr, "******PackImage: PANIC! Cannot pack image from [%d] to [%d] bytes per pixel.\n",
src_bits_per_pixel, dst_bits_per_pixel);
#endif
return 0;
}
switch (src_bits_per_pixel)
{
case 16:
{
switch (dst_bits_per_pixel)
{
case 8:
{
return Pack16To8(src_data_size, src_image, dst_image);
}
default:
{
return 0;
}
}
}
case 24:
{
switch (dst_bits_per_pixel)
{
case 8:
{
return Pack24To8(src_data_size, src_image, dst_image);
}
case 16:
{
return Pack24To16(src_data_size, src_image, dst_image);
}
default:
{
return 0;
}
}
}
case 32:
{
switch (dst_bits_per_pixel)
{
case 8:
{
return Pack32To8(src_data_size, src_image, dst_image);
}
case 16:
{
return Pack32To16(src_data_size, src_image, dst_image);
}
case 24:
{
return Pack32To24(src_data_size, src_image, dst_image);
}
default:
{
return 0;
}
}
}
default:
{
return 0;
}
}
}
/*
* Replace the ffs() call that may be not
* present on some systems.
*/
int FindLSB(int word)
{
int t = word;
int m = 1;
int i = 0;
for (; i < sizeof(word) << 3; i++, m <<= 1)
{
if (t & m)
{
return i + 1;
}
}
return 0;
}

View File

@@ -0,0 +1,48 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#ifndef Mask_H
#define Mask_H
#ifdef __cplusplus
extern "C" {
#endif
#include "Xlib.h"
extern int MaskImage(const ColorMask *mask, XImage *src_image, XImage *dst_image);
extern int MaskInPlaceImage(const ColorMask *mask, XImage *image);
extern int PackImage(unsigned int method, unsigned int src_data_size, XImage *src_image,
unsigned int dst_data_size, XImage *dst_image);
int FindLSB(int word);
#ifdef __cplusplus
}
#endif
#endif /* Mask_H */

View File

@@ -0,0 +1,725 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <nx-X11/Xutil.h>
#include "Compext.h"
#include "Mask.h"
#include "Png.h"
#include "../Utils.h"
#define PANIC
#define WARNING
#undef TEST
#undef DEBUG
/*
* Selected ZLIB compression level.
*/
#define PNG_Z_LEVEL 4
/*
* Local function prototypes.
*/
static void PrepareRowForPng(CARD8 *dst, int y, int count);
static void PrepareRowForPng24(CARD8 *dst, int y, int count);
static void PrepareRowForPng16(CARD8 *dst, int y, int count);
static void PrepareRowForPng32(CARD8 *dst, int y, int count);
static void PngWriteData(png_structp png_ptr, png_bytep data, png_size_t length);
static void PngFlushData(png_structp png_ptr);
/*
* Image characteristics.
*/
static int bytesPerLine;
static int byteOrder;
static CARD8 bitsPerPixel;
static CARD16 redMax, greenMax, blueMax;
static CARD8 redShift, greenShift, blueShift;
/*
* Other variables used for the Png
* encoding.
*/
png_byte color_type;
png_structp png_ptr;
png_infop info_ptr;
png_colorp palette;
static char *pngCompBuf;
static int pngDataLen;
static char *pngBeforeBuf = NULL;
/*
* Allocate data for the compressed image.
* We need to ensure that there is enough
* space to include the palette and the
* header.
*/
#define PNG_DEST_SIZE(width, height) ((width) * 3 * (height) + 1024 + 256)
/*
* Just for debug purposes.
*/
#ifdef DEBUG
static int pngId;
static char pngName[10];
static FILE *pngFile;
#endif
int PngCompareColorTable(NXColorTable *c1, NXColorTable *c2)
{
return (c1 -> pixel - c2 -> pixel);
}
#define NB_COLOR_MAX 256
int NXCreatePalette32(XImage *src_image, NXColorTable *color_table, CARD8 *image_index, int nb_max)
{
int x, y, t, p;
CARD8 *fbptr;
CARD32 pixel;
fbptr = (CARD8 *) (src_image -> data);
/*
* TODO: Find a more intelligent way to
* estimate the number of colors.
*/
memset(color_table, 0, nb_max * sizeof(NXColorTable));
for (x = 0, p = 0; x < src_image -> height; x++)
{
for (y = 0; y < src_image -> width; y++)
{
if (byteOrder == LSBFirst)
{
pixel = (CARD32) *(fbptr + 3);
pixel = (pixel << 8) | (CARD32) *(fbptr + 2);
pixel = (pixel << 8) | (CARD32) *(fbptr + 1);
pixel = (pixel << 8) | (CARD32) *fbptr;
}
else
{
pixel = (CARD32) *fbptr;
pixel = (pixel << 8) | (CARD32) *(fbptr + 1);
pixel = (pixel << 8) | (CARD32) *(fbptr + 2);
pixel = (pixel << 8) | (CARD32) *(fbptr + 3);
}
fbptr += 4;
for (t = 0; t < nb_max; t++)
{
if (color_table[t].found == 0)
{
color_table[t].pixel = pixel;
color_table[t].found = 1;
p++;
image_index[((x * src_image -> width) + y)] = t;
break;
}
else if ((CARD32)(color_table[t].pixel) == pixel)
{
image_index[((x * src_image -> width) + y)] = t;
break;
}
}
if (p == nb_max)
{
return nb_max + 1;
}
}
}
return p;
}
int NXCreatePalette16(XImage *src_image, NXColorTable *color_table, CARD8 *image_index, int nb_max)
{
int x, y, t, p;
CARD8 *fbptr;
CARD16 pixel;
fbptr = (CARD8 *) (src_image -> data);
/*
* TODO: Find a more intelligent way to
* estimate the number of colors.
*/
memset(color_table, 0, nb_max * sizeof(NXColorTable));
for (x = 0, p = 0; x < src_image -> height; x++)
{
for (y = 0; y < src_image -> width; y++)
{
if (byteOrder == LSBFirst)
{
pixel = (CARD16) *(fbptr + 1);
pixel = (pixel << 8) | (CARD16) *fbptr;
}
else
{
pixel = (CARD16) *fbptr;
pixel = (pixel << 8) | (CARD16) *(fbptr + 1);
}
fbptr += 2;
for (t = 0; t < nb_max; t++)
{
if (color_table[t].found == 0)
{
color_table[t].pixel = pixel;
color_table[t].found = 1;
p++;
image_index[((x * src_image -> width) + y)] = t;
break;
}
else if ((color_table[t].pixel) == pixel)
{
image_index[((x * src_image -> width) + y)] = t;
break;
}
}
/*
* In case the number of 16bit words is not even
* we have 2 padding bytes that we have to skip.
*/
if ((y == src_image -> width - 1) && (src_image -> width % 2 == 1)) fbptr += 2;
if (p == nb_max)
{
return nb_max + 1;
}
}
}
return p;
}
char *PngCompressData(XImage *image, int *compressed_size)
{
unsigned int num = 0;
CARD8 *srcBuf;
int dy, w, h;
int nb_colors;
NXColorTable color_table[NB_COLOR_MAX];
CARD8 *image_index;
*compressed_size = 0;
pngDataLen = 0;
/*
* Initialize the image stuff.
*/
bitsPerPixel = image -> bits_per_pixel;
bytesPerLine = image -> bytes_per_line;
byteOrder = image -> byte_order;
if (bitsPerPixel < 15)
{
#ifdef PANIC
fprintf(stderr, "******PngCompressData: PANIC! Can't compress images with [%d] bits per pixel.\n",
bitsPerPixel);
#endif
return NULL;
}
redShift = FindLSB(image -> red_mask) - 1;
greenShift = FindLSB(image -> green_mask) - 1;
blueShift = FindLSB(image -> blue_mask) - 1;
redMax = image -> red_mask >> redShift;
greenMax = image -> green_mask >> greenShift;
blueMax = image -> blue_mask >> blueShift;
w = image -> width;
h = image -> height;
pngBeforeBuf = image -> data;
#ifdef DEBUG
fprintf(stderr, "******PngCompressData: Compressing image with width [%d] height [%d].\n",
w, h );
#endif
/*
* Initialize the PNG stuff.
*/
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL)
{
#ifdef PANIC
fprintf(stderr, "******PngCompressData: PANIC! Failed creating the png_create_write_struct.\n");
#endif
return NULL;
}
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL)
{
#ifdef PANIC
fprintf(stderr, "******PngCompressData: PANIC! Failed creating the png_create_info_struct.\n");
#endif
png_destroy_write_struct(&png_ptr, NULL);
return NULL;
}
if (setjmp(png_jmpbuf(png_ptr)))
{
#ifdef PANIC
fprintf(stderr, "******PngCompressData: PANIC! Error during compression initialization.\n");
#endif
png_destroy_write_struct(&png_ptr, &info_ptr);
return NULL;
}
/*
* Be sure we allocate enough data.
*/
#ifdef TEST
fprintf(stderr, "******PngCompressData: Allocating [%d] bytes for the destination data.\n",
PNG_DEST_SIZE(w, h));
#endif
pngCompBuf = malloc(PNG_DEST_SIZE(w, h));
if (pngCompBuf == NULL)
{
#ifdef PANIC
fprintf(stderr, "******PngCompressData: PANIC! Error allocating [%d] bytes for the Png data.\n",
PNG_DEST_SIZE(w, h));
#endif
return NULL;
}
png_set_write_fn(png_ptr, (void *) pngCompBuf, PngWriteData, PngFlushData);
if (setjmp(png_jmpbuf(png_ptr)))
{
#ifdef PANIC
fprintf(stderr, "******PngCompressData: PANIC! Error writing the header.\n");
#endif
png_destroy_write_struct(&png_ptr, &info_ptr);
SAFE_free(pngCompBuf);
return NULL;
}
image_index = (CARD8 *) calloc(1, (image -> height) * (image -> width) * sizeof(CARD8));
if (image_index == NULL)
{
#ifdef PANIC
fprintf(stderr, "******PngCompressData: PANIC! Could not alloc image_index.\n");
#endif
SAFE_free(pngCompBuf);
return NULL;
}
/*
* TODO: Be sure the padded bytes are cleaned.
* It would be better to set to zero the bytes
* that are not aligned to the word boundary
* at the end of the procedure.
*/
png_set_compression_level(png_ptr, PNG_Z_LEVEL);
if (bitsPerPixel == 16)
{
nb_colors = NXCreatePalette16(image, color_table, image_index, NB_COLOR_MAX);
}
else
{
nb_colors = NXCreatePalette32(image, color_table, image_index, NB_COLOR_MAX);
}
if (nb_colors <= NB_COLOR_MAX)
{
color_type = PNG_COLOR_TYPE_PALETTE;
}
else
{
color_type = PNG_COLOR_TYPE_RGB;
}
png_set_IHDR(png_ptr, info_ptr, w, h,
8, color_type, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
if (color_type == PNG_COLOR_TYPE_PALETTE)
{
palette = png_malloc(png_ptr, sizeof(*palette) * 256);
/*
* TODO: Do we need to clean these bytes?
*
* memset(palette, 0, sizeof(*palette) * 256);
*/
for (num = 0; num < 256 && color_table[num].found != 0; num++)
{
if (bitsPerPixel == 24)
{
palette[num].red = (color_table[num].pixel >> redShift) & redMax;
palette[num].green = (color_table[num].pixel >> greenShift) & greenMax;
palette[num].blue = color_table[num].pixel >> blueShift & blueMax;
}
else
{
int inRed, inGreen, inBlue;
inRed = (color_table[num].pixel >> redShift) & redMax;
inGreen = (color_table[num].pixel >> greenShift) & greenMax;
inBlue = color_table[num].pixel >> blueShift & blueMax;
palette[num].red = (CARD8)((inRed * 255 + redMax / 2) / redMax);
palette[num].green = (CARD8)((inGreen * 255 + greenMax / 2) / greenMax);
palette[num].blue = (CARD8)((inBlue * 255 + blueMax / 2) / blueMax);
}
#ifdef DEBUG
fprintf(stderr, "******PngCompressData: pixel[%d] r[%d] g[%d] b[%d].\n",
(int) color_table[num].pixel,palette[num].red,palette[num].green,palette[num].blue);
#endif
}
png_set_PLTE(png_ptr, info_ptr, palette, num);
#ifdef DEBUG
fprintf(stderr, "******PngCompressedData: Setting palette.\n");
#endif
}
/*
* End of palette.
*/
png_write_info(png_ptr, info_ptr);
/*
* Allocate space for one line of
* the image, 3 bytes per pixel.
*/
#ifdef DEBUG
fprintf(stderr, "******PngCompressedData: Initialization finished.\n");
#endif
if (setjmp(png_jmpbuf(png_ptr)))
{
#ifdef PANIC
fprintf(stderr, "******PngCompressData: PANIC! Error while writing the image rows.\n");
#endif
png_destroy_write_struct(&png_ptr, &info_ptr);
SAFE_free(pngCompBuf);
SAFE_free(image_index);
return NULL;
}
int count;
if (color_type == PNG_COLOR_TYPE_PALETTE)
{
count = w;
}
else
{
count = 3 * w;
}
srcBuf = (CARD8 *) calloc(count, sizeof(CARD8));
if (srcBuf == NULL)
{
#ifdef PANIC
fprintf(stderr, "******PngCompressData: PANIC! Cannot allocate [%d] bytes.\n",
(int) (count * sizeof(CARD8)));
#endif
SAFE_free(pngCompBuf);
SAFE_free(image_index);
return NULL;
}
/*
* TODO: Be sure the padded bytes are cleaned.
* It would be better to set to zero the bytes
* that are not aligned to the word boundary
* at the end of the procedure.
*/
for (dy = 0; dy < h; dy++)
{
if (color_type == PNG_COLOR_TYPE_RGB)
{
PrepareRowForPng(srcBuf, dy, w);
}
else
{
memcpy(srcBuf, image_index + (dy * w), w);
}
png_write_row(png_ptr, srcBuf);
}
#ifdef DEBUG
fprintf(stderr, "******PngCompressedData: Compression finished. Lines handled [%d,%d].\n",
dy, h);
#endif
SAFE_free(srcBuf);
SAFE_free(image_index);
if (setjmp(png_jmpbuf(png_ptr)))
{
#ifdef PANIC
fprintf(stderr, "******PngCompressData: PANIC! error during end of write.\n");
#endif
png_destroy_write_struct(&png_ptr, &info_ptr);
SAFE_free(pngCompBuf);
return NULL;
}
png_write_end(png_ptr, NULL);
if (color_type == PNG_COLOR_TYPE_PALETTE)
{
png_free(png_ptr, palette);
}
png_destroy_write_struct(&png_ptr, &info_ptr);
/*
* Check the size of the resulting data.
*/
if (pngDataLen > 0)
{
#ifdef DEBUG
int i = 0;
fprintf(stderr, "******PngCompressedData: Compressed size [%d].\n",
pngDataLen);
pngId++;
sprintf(pngName, "png%d", pngId);
pngFile = fopen(pngName, "w");
for (i = 0; i < pngDataLen; i++)
{
fprintf(pngFile, "%c", *(pngCompBuf + i));
}
fclose(pngFile);
#endif
*compressed_size = pngDataLen;
return pngCompBuf;
}
else
{
#ifdef DEBUG
fprintf(stderr, "******PngCompressedData: PANIC! Invalid size of the compressed data [%d].\n",
pngDataLen);
#endif
SAFE_free(pngCompBuf);
return NULL;
}
}
static void PngWriteData(png_structp _png_ptr, png_bytep data, png_size_t length)
{
memcpy(((char *) png_get_io_ptr(_png_ptr) + pngDataLen), data, length);
pngDataLen += length;
}
static void PngFlushData(png_structp _png_ptr)
{
}
void PrepareRowForPng(CARD8 *dst, int y, int count)
{
if (bitsPerPixel == 32)
{
if (redMax == 0xff &&
greenMax == 0xff &&
blueMax == 0xff)
{
PrepareRowForPng24(dst, y, count);
}
else
{
PrepareRowForPng32(dst, y, count);
}
}
else if (bitsPerPixel == 24)
{
memcpy(dst, pngBeforeBuf + y * bytesPerLine, count * 3);
}
else
{
/*
* 16 bpp assumed.
*/
PrepareRowForPng16(dst, y, count);
}
}
void PrepareRowForPng24(CARD8 *dst, int y, int count)
{
CARD8 *fbptr;
CARD32 pix;
fbptr = (CARD8 *) (pngBeforeBuf + y * bytesPerLine);
while (count--)
{
if (byteOrder == LSBFirst)
{
pix = (CARD32) *(fbptr + 2);
pix = (pix << 8) | (CARD32) *(fbptr+1);
pix = (pix << 8) | (CARD32) *fbptr;
}
else
{
pix = (CARD32) *(fbptr + 1);
pix = (pix << 8) | (CARD32) *(fbptr + 2);
pix = (pix << 8) | (CARD32) *(fbptr + 3);
}
*dst++ = (CARD8)(pix >> redShift);
*dst++ = (CARD8)(pix >> greenShift);
*dst++ = (CARD8)(pix >> blueShift);
fbptr+=4;
}
}
#define DEFINE_PNG_GET_ROW_FUNCTION(bpp) \
\
void PrepareRowForPng##bpp(CARD8 *dst, int y, int count) \
{ \
CARD8 *fbptr; \
CARD##bpp pix; \
int inRed, inGreen, inBlue; \
int i; \
\
fbptr = (CARD8 *) (pngBeforeBuf + y * bytesPerLine); \
\
while (count--) \
{ \
pix = 0; \
\
if (byteOrder == LSBFirst) \
{ \
for (i = (bpp >> 3) - 1; i >= 0; i--) \
{ \
pix = (pix << 8) | (CARD32) *(fbptr + i); \
} \
} \
else \
{ \
for (i = 0; i < (bpp >> 3); i++) \
{ \
pix = (pix << 8) | (CARD32) *(fbptr + i); \
} \
} \
\
fbptr += (bpp >> 3); \
\
inRed = (int) \
(pix >> redShift & redMax); \
inGreen = (int) \
(pix >> greenShift & greenMax); \
inBlue = (int) \
(pix >> blueShift & blueMax); \
*dst++ = (CARD8)((inRed * 255 + redMax / 2) / \
redMax); \
*dst++ = (CARD8)((inGreen * 255 + greenMax / 2) / \
greenMax); \
*dst++ = (CARD8)((inBlue * 255 + blueMax / 2) / \
blueMax); \
} \
}
DEFINE_PNG_GET_ROW_FUNCTION(16)
DEFINE_PNG_GET_ROW_FUNCTION(32)

View File

@@ -0,0 +1,76 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#ifndef Png_H
#define Png_H
#ifdef __cplusplus
extern "C" {
#endif
#include <nx-X11/X.h>
#include <nx-X11/Xlib.h>
#include <nx-X11/Xmd.h>
#include <png.h>
extern int PngCompareColorTable(
#if NeedFunctionPrototypes
NXColorTable* /* color_table_1 */,
NXColorTable* /* color_table_2 */
#endif
);
extern char *PngCompressData(
#if NeedFunctionPrototypes
XImage* /* image */,
int* /* compressed_size */
#endif
);
int NXCreatePalette16(
#if NeedFunctionPrototypes
XImage* /* src_image */,
NXColorTable* /* color_table */,
CARD8* /* image_index */,
int /* nb_max */
#endif
);
int NXCreatePalette32(
#if NeedFunctionPrototypes
XImage* /* src_image */,
NXColorTable* /* color_table */,
CARD8* /* image_index */,
int /* nb_max */
#endif
);
#ifdef __cplusplus
}
#endif
#endif /* Png_H */

View File

@@ -0,0 +1,51 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#include <zlib.h>
#include "Compext.h"
#include "Rgb.h"
#include "Z.h"
#define PANIC
#define WARNING
#undef TEST
#undef DEBUG
#define RGB_COMPRESSION_LEVEL 4
#define RGB_COMPRESSION_THRESHOLD 32
#define RGB_COMPRESSION_STRATEGY Z_DEFAULT_STRATEGY
static int rgbCompressionLevel = RGB_COMPRESSION_LEVEL;
static int rgbCompressionThreshold = RGB_COMPRESSION_THRESHOLD;
static int rgbCompressionStrategy = RGB_COMPRESSION_STRATEGY;
char *RgbCompressData(XImage *image, unsigned int *size)
{
return ZCompressData(image -> data, image -> bytes_per_line * image -> height,
rgbCompressionThreshold, rgbCompressionLevel,
rgbCompressionStrategy, size);
}

View File

@@ -0,0 +1,44 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#ifndef Rgb_H
#define Rgb_H
#ifdef __cplusplus
extern "C" {
#endif
extern char *RgbCompressData(
#if NeedFunctionPrototypes
XImage* /* image */,
unsigned int* /* compressed_size */
#endif
);
#ifdef __cplusplus
}
#endif
#endif /* Rgb_H */

View File

@@ -0,0 +1,51 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#include <zlib.h>
#include "Compext.h"
#include "Rle.h"
#include "Z.h"
#define PANIC
#define WARNING
#undef TEST
#undef DEBUG
#define RLE_COMPRESSION_LEVEL 1
#define RLE_COMPRESSION_THRESHOLD 32
#define RLE_COMPRESSION_STRATEGY Z_RLE
static int rleCompressionLevel = RLE_COMPRESSION_LEVEL;
static int rleCompressionThreshold = RLE_COMPRESSION_THRESHOLD;
static int rleCompressionStrategy = RLE_COMPRESSION_STRATEGY;
char *RleCompressData(XImage *image, unsigned int *size)
{
return ZCompressData(image -> data, image -> bytes_per_line * image -> height,
rleCompressionThreshold, rleCompressionLevel,
rleCompressionStrategy, size);
}

View File

@@ -0,0 +1,44 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#ifndef Rle_H
#define Rle_H
#ifdef __cplusplus
extern "C" {
#endif
extern char *RleCompressData(
#if NeedFunctionPrototypes
XImage* /* image */,
unsigned int* /* compressed_size */
#endif
);
#ifdef __cplusplus
}
#endif
#endif /* Rle_H */

View File

@@ -0,0 +1,311 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
#include "Compext.h"
#include "Z.h"
#include "../Utils.h"
#define PANIC
#define WARNING
#undef TEST
#undef DEBUG
#define Z_COMPRESSION_LEVEL 4
#define Z_COMPRESSION_THRESHOLD 32
#define Z_COMPRESSION_STRATEGY Z_DEFAULT_STRATEGY
static int zCompressionLevel = Z_COMPRESSION_LEVEL;
static int zCompressionStrategy = Z_COMPRESSION_STRATEGY;
static z_stream *zStream;
static int zInitialized;
static int ZConfigure(int level, int strategy);
static int ZDeflate(char *dest, unsigned int *destLen,
const char *source, unsigned int sourceLen);
char *ZCompressData(const char *plainData, unsigned int plainSize, int threshold,
int level, int strategy, unsigned int *compressedSize)
{
char *compressedData;
/*
* Determine the size of the source image
* data and make sure there is enough
* space in the destination buffer.
*/
*compressedSize = plainSize + (plainSize / 1000) + 12 + 1;
compressedData = malloc(*compressedSize);
if (compressedData == NULL)
{
#ifdef PANIC
fprintf(stderr, "******ZCompressData: PANIC! Failed to allocate [%d] bytes for the destination.\n",
*compressedSize);
#endif
*compressedSize = 0;
return NULL;
}
if (level == Z_NO_COMPRESSION || plainSize < threshold)
{
#ifdef TEST
fprintf(stderr, "******ZCompressData: Not compressing [%d] bytes with level [%d] and "
"threshold [%d].\n", plainSize, level, threshold);
#endif
/*
* Tell in the first byte of the buffer
* if the remaining data is compressed
* or not. This same byte can be used
* in future to store some other flag.
*/
*compressedData = 0;
memcpy(compressedData + 1, plainData, plainSize);
*compressedSize = plainSize + 1;
return compressedData;
}
else
{
int result;
/*
* Reconfigure the stream if needed.
*/
if (zCompressionLevel != level ||
zCompressionStrategy != strategy)
{
ZConfigure(level, strategy);
zCompressionLevel = level;
zCompressionStrategy = strategy;
}
result = ZDeflate(compressedData + 1, compressedSize, plainData, plainSize);
if (result != Z_OK)
{
#ifdef PANIC
fprintf(stderr, "******ZCompressData: PANIC! Failed to compress [%d] bytes with error [%s].\n",
plainSize, zError(result));
#endif
SAFE_free(compressedData);
*compressedSize = 0;
return NULL;
}
#ifdef TEST
fprintf(stderr, "******ZCompressData: Source data of [%d] bytes compressed to [%d].\n",
plainSize, *compressedSize);
#endif
*compressedData = 1;
*compressedSize = *compressedSize + 1;
return compressedData;
}
}
int ZConfigure(int level, int strategy)
{
/*
* ZLIB wants the avail_out to be
* non zero, even if the stream was
* already flushed.
*/
unsigned char dest[1];
zStream -> next_out = dest;
zStream -> avail_out = 1;
if (deflateParams(zStream, level, strategy) != Z_OK)
{
#ifdef PANIC
fprintf(stderr, "******ZConfigure: PANIC! Failed to set level to [%d] and strategy to [%d].\n",
level, strategy);
#endif
return -1;
}
#ifdef TEST
else
{
fprintf(stderr, "******ZConfigure: Reconfigured the stream with level [%d] and strategy [%d].\n",
level, strategy);
}
#endif
return 1;
}
int ZDeflate(char *dest, unsigned int *destLen, const char *source, unsigned int sourceLen)
{
int saveOut;
int result;
/*
* Deal with the possible overflow.
*/
if (zStream -> total_out & 0x80000000)
{
#ifdef TEST
fprintf(stderr, "******ZDeflate: Reset Z stream counters with total in [%ld] total out [%ld].\n",
zStream -> total_in, zStream -> total_out);
#endif
zStream -> total_in = 0;
zStream -> total_out = 0;
}
saveOut = zStream -> total_out;
zStream -> next_in = (Bytef *) source;
zStream -> avail_in = (uInt) sourceLen;
#ifdef MAXSEG_64K
/*
* Check if the source is greater
* than 64K on a 16-bit machine.
*/
if ((uLong) zStream -> avail_in != sourceLen) return Z_BUF_ERROR;
#endif
zStream -> next_out = (unsigned char *) dest;
zStream -> avail_out = (uInt) *destLen;
if ((uLong) zStream -> avail_out != *destLen) return Z_BUF_ERROR;
result = deflate(zStream, Z_FINISH);
if (result != Z_STREAM_END)
{
deflateReset(zStream);
return (result == Z_OK ? Z_BUF_ERROR : result);
}
*destLen = zStream -> total_out - saveOut;
result = deflateReset(zStream);
return result;
}
int ZInitEncoder(void)
{
if (zInitialized == 0)
{
int result;
zStream = malloc(sizeof(z_stream));
if (zStream == NULL)
{
#ifdef PANIC
fprintf(stderr, "******ZInitEncoder: PANIC! Failed to allocate memory for the stream.\n");
#endif
return -1;
}
zStream -> zalloc = (alloc_func) 0;
zStream -> zfree = (free_func) 0;
zStream -> opaque = (voidpf) 0;
#ifdef TEST
fprintf(stderr, "******ZInitEncoder: Initializing compressor with level [%d] and strategy [%d].\n",
zCompressionLevel, zCompressionStrategy);
#endif
result = deflateInit2(zStream, zCompressionLevel, Z_DEFLATED,
15, 9, zCompressionStrategy);
if (result != Z_OK)
{
#ifdef PANIC
fprintf(stderr, "******ZInitEncoder: Failed to initialize the compressor with error [%s].\n",
zError(result));
#endif
return -1;
}
zInitialized = 1;
}
return zInitialized;
}
int ZResetEncoder(void)
{
int result;
if (zInitialized == 1)
{
result = deflateEnd(zStream);
if (result != Z_OK)
{
#ifdef WARNING
fprintf(stderr, "******ZResetEncoder: WARNING! Failed to deinitialize the compressor with error [%s].\n",
zError(result));
#endif
}
SAFE_free(zStream);
}
zInitialized = 0;
return 1;
}

View File

@@ -0,0 +1,60 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
#ifndef Z_H
#define Z_H
#ifdef __cplusplus
extern "C" {
#endif
int ZInitEncoder(
#if NeedFunctionPrototypes
void
#endif
);
int ZResetEncoder(
#if NeedFunctionPrototypes
void
#endif
);
extern char *ZCompressData(
#if NeedFunctionPrototypes
const char* /* data */,
unsigned int /* size */,
int /* threshold */,
int /* level */,
int /* strategy */,
unsigned int* /* compressed_size */
#endif
);
#ifdef __cplusplus
}
#endif
#endif /* Z_H */