93 |
93 |
|
94 |
94 |
static bool tight_can_send_png_rect(VncState *vs, int w, int h)
|
95 |
95 |
{
|
96 |
|
if (vs->tight_type != VNC_ENCODING_TIGHT_PNG) {
|
|
96 |
if (vs->tight.type != VNC_ENCODING_TIGHT_PNG) {
|
97 |
97 |
return false;
|
98 |
98 |
}
|
99 |
99 |
|
... | ... | |
121 |
121 |
int pixels = 0;
|
122 |
122 |
int pix, left[3];
|
123 |
123 |
uint errors;
|
124 |
|
unsigned char *buf = vs->tight.buffer;
|
|
124 |
unsigned char *buf = vs->tight.tight.buffer;
|
125 |
125 |
|
126 |
126 |
/*
|
127 |
127 |
* If client is big-endian, color samples begin from the second
|
... | ... | |
188 |
188 |
int pixels = 0; \
|
189 |
189 |
int sample, sum, left[3]; \
|
190 |
190 |
uint errors; \
|
191 |
|
unsigned char *buf = vs->tight.buffer; \
|
|
191 |
unsigned char *buf = vs->tight.tight.buffer; \
|
192 |
192 |
\
|
193 |
193 |
endian = ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) != \
|
194 |
194 |
(vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)); \
|
... | ... | |
268 |
268 |
tight_detect_smooth_image(VncState *vs, int w, int h)
|
269 |
269 |
{
|
270 |
270 |
uint errors;
|
271 |
|
int compression = vs->tight_compression;
|
272 |
|
int quality = vs->tight_quality;
|
|
271 |
int compression = vs->tight.compression;
|
|
272 |
int quality = vs->tight.quality;
|
273 |
273 |
|
274 |
274 |
if (!vs->vd->lossy) {
|
275 |
275 |
return 0;
|
... | ... | |
281 |
281 |
return 0;
|
282 |
282 |
}
|
283 |
283 |
|
284 |
|
if (vs->tight_quality != -1) {
|
|
284 |
if (vs->tight.quality != -1) {
|
285 |
285 |
if (w * h < VNC_TIGHT_JPEG_MIN_RECT_SIZE) {
|
286 |
286 |
return 0;
|
287 |
287 |
}
|
... | ... | |
292 |
292 |
}
|
293 |
293 |
|
294 |
294 |
if (vs->clientds.pf.bytes_per_pixel == 4) {
|
295 |
|
if (vs->tight_pixel24) {
|
|
295 |
if (vs->tight.pixel24) {
|
296 |
296 |
errors = tight_detect_smooth_image24(vs, w, h);
|
297 |
|
if (vs->tight_quality != -1) {
|
|
297 |
if (vs->tight.quality != -1) {
|
298 |
298 |
return (errors < tight_conf[quality].jpeg_threshold24);
|
299 |
299 |
}
|
300 |
300 |
return (errors < tight_conf[compression].gradient_threshold24);
|
... | ... | |
324 |
324 |
uint##bpp##_t c0, c1, ci; \
|
325 |
325 |
int i, n0, n1; \
|
326 |
326 |
\
|
327 |
|
data = (uint##bpp##_t *)vs->tight.buffer; \
|
|
327 |
data = (uint##bpp##_t *)vs->tight.tight.buffer; \
|
328 |
328 |
\
|
329 |
329 |
c0 = data[0]; \
|
330 |
330 |
i = 1; \
|
... | ... | |
395 |
395 |
{
|
396 |
396 |
int max;
|
397 |
397 |
|
398 |
|
max = count / tight_conf[vs->tight_compression].idx_max_colors_divisor;
|
|
398 |
max = count / tight_conf[vs->tight.compression].idx_max_colors_divisor;
|
399 |
399 |
if (max < 2 &&
|
400 |
|
count >= tight_conf[vs->tight_compression].mono_min_rect_size) {
|
|
400 |
count >= tight_conf[vs->tight.compression].mono_min_rect_size) {
|
401 |
401 |
max = 2;
|
402 |
402 |
}
|
403 |
403 |
if (max >= 256) {
|
... | ... | |
529 |
529 |
int x, y, c;
|
530 |
530 |
|
531 |
531 |
buf32 = (uint32_t *)buf;
|
532 |
|
memset(vs->tight_gradient.buffer, 0, w * 3 * sizeof(int));
|
|
532 |
memset(vs->tight.gradient.buffer, 0, w * 3 * sizeof(int));
|
533 |
533 |
|
534 |
534 |
if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
|
535 |
535 |
(vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)) {
|
... | ... | |
547 |
547 |
upper[c] = 0;
|
548 |
548 |
here[c] = 0;
|
549 |
549 |
}
|
550 |
|
prev = (int *)vs->tight_gradient.buffer;
|
|
550 |
prev = (int *)vs->tight.gradient.buffer;
|
551 |
551 |
for (x = 0; x < w; x++) {
|
552 |
552 |
pix32 = *buf32++;
|
553 |
553 |
for (c = 0; c < 3; c++) {
|
... | ... | |
587 |
587 |
int prediction; \
|
588 |
588 |
int x, y, c; \
|
589 |
589 |
\
|
590 |
|
memset (vs->tight_gradient.buffer, 0, w * 3 * sizeof(int)); \
|
|
590 |
memset (vs->tight.gradient.buffer, 0, w * 3 * sizeof(int)); \
|
591 |
591 |
\
|
592 |
592 |
endian = ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) != \
|
593 |
593 |
(vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)); \
|
... | ... | |
604 |
604 |
upper[c] = 0; \
|
605 |
605 |
here[c] = 0; \
|
606 |
606 |
} \
|
607 |
|
prev = (int *)vs->tight_gradient.buffer; \
|
|
607 |
prev = (int *)vs->tight.gradient.buffer; \
|
608 |
608 |
for (x = 0; x < w; x++) { \
|
609 |
609 |
pix = *buf; \
|
610 |
610 |
if (endian) { \
|
... | ... | |
774 |
774 |
static int tight_init_stream(VncState *vs, int stream_id,
|
775 |
775 |
int level, int strategy)
|
776 |
776 |
{
|
777 |
|
z_streamp zstream = &vs->tight_stream[stream_id];
|
|
777 |
z_streamp zstream = &vs->tight.stream[stream_id];
|
778 |
778 |
|
779 |
779 |
if (zstream->opaque == NULL) {
|
780 |
780 |
int err;
|
... | ... | |
792 |
792 |
return -1;
|
793 |
793 |
}
|
794 |
794 |
|
795 |
|
vs->tight_levels[stream_id] = level;
|
|
795 |
vs->tight.levels[stream_id] = level;
|
796 |
796 |
zstream->opaque = vs;
|
797 |
797 |
}
|
798 |
798 |
|
799 |
|
if (vs->tight_levels[stream_id] != level) {
|
|
799 |
if (vs->tight.levels[stream_id] != level) {
|
800 |
800 |
if (deflateParams(zstream, level, strategy) != Z_OK) {
|
801 |
801 |
return -1;
|
802 |
802 |
}
|
803 |
|
vs->tight_levels[stream_id] = level;
|
|
803 |
vs->tight.levels[stream_id] = level;
|
804 |
804 |
}
|
805 |
805 |
return 0;
|
806 |
806 |
}
|
... | ... | |
828 |
828 |
static int tight_compress_data(VncState *vs, int stream_id, size_t bytes,
|
829 |
829 |
int level, int strategy)
|
830 |
830 |
{
|
831 |
|
z_streamp zstream = &vs->tight_stream[stream_id];
|
|
831 |
z_streamp zstream = &vs->tight.stream[stream_id];
|
832 |
832 |
int previous_out;
|
833 |
833 |
|
834 |
834 |
if (bytes < VNC_TIGHT_MIN_TO_COMPRESS) {
|
835 |
|
vnc_write(vs, vs->tight.buffer, vs->tight.offset);
|
|
835 |
vnc_write(vs, vs->tight.tight.buffer, vs->tight.tight.offset);
|
836 |
836 |
return bytes;
|
837 |
837 |
}
|
838 |
838 |
|
... | ... | |
841 |
841 |
}
|
842 |
842 |
|
843 |
843 |
/* reserve memory in output buffer */
|
844 |
|
buffer_reserve(&vs->tight_zlib, bytes + 64);
|
|
844 |
buffer_reserve(&vs->tight.zlib, bytes + 64);
|
845 |
845 |
|
846 |
846 |
/* set pointers */
|
847 |
|
zstream->next_in = vs->tight.buffer;
|
848 |
|
zstream->avail_in = vs->tight.offset;
|
849 |
|
zstream->next_out = vs->tight_zlib.buffer + vs->tight_zlib.offset;
|
850 |
|
zstream->avail_out = vs->tight_zlib.capacity - vs->tight_zlib.offset;
|
|
847 |
zstream->next_in = vs->tight.tight.buffer;
|
|
848 |
zstream->avail_in = vs->tight.tight.offset;
|
|
849 |
zstream->next_out = vs->tight.zlib.buffer + vs->tight.zlib.offset;
|
|
850 |
zstream->avail_out = vs->tight.zlib.capacity - vs->tight.zlib.offset;
|
851 |
851 |
zstream->data_type = Z_BINARY;
|
852 |
852 |
previous_out = zstream->total_out;
|
853 |
853 |
|
... | ... | |
857 |
857 |
return -1;
|
858 |
858 |
}
|
859 |
859 |
|
860 |
|
vs->tight_zlib.offset = vs->tight_zlib.capacity - zstream->avail_out;
|
|
860 |
vs->tight.zlib.offset = vs->tight.zlib.capacity - zstream->avail_out;
|
861 |
861 |
bytes = zstream->total_out - previous_out;
|
862 |
862 |
|
863 |
863 |
tight_send_compact_size(vs, bytes);
|
864 |
|
vnc_write(vs, vs->tight_zlib.buffer, bytes);
|
|
864 |
vnc_write(vs, vs->tight.zlib.buffer, bytes);
|
865 |
865 |
|
866 |
|
buffer_reset(&vs->tight_zlib);
|
|
866 |
buffer_reset(&vs->tight.zlib);
|
867 |
867 |
|
868 |
868 |
return bytes;
|
869 |
869 |
}
|
... | ... | |
915 |
915 |
|
916 |
916 |
vnc_write_u8(vs, stream << 4); /* no flushing, no filter */
|
917 |
917 |
|
918 |
|
if (vs->tight_pixel24) {
|
919 |
|
tight_pack24(vs, vs->tight.buffer, w * h, &vs->tight.offset);
|
|
918 |
if (vs->tight.pixel24) {
|
|
919 |
tight_pack24(vs, vs->tight.tight.buffer, w * h, &vs->tight.tight.offset);
|
920 |
920 |
bytes = 3;
|
921 |
921 |
} else {
|
922 |
922 |
bytes = vs->clientds.pf.bytes_per_pixel;
|
923 |
923 |
}
|
924 |
924 |
|
925 |
925 |
bytes = tight_compress_data(vs, stream, w * h * bytes,
|
926 |
|
tight_conf[vs->tight_compression].raw_zlib_level,
|
|
926 |
tight_conf[vs->tight.compression].raw_zlib_level,
|
927 |
927 |
Z_DEFAULT_STRATEGY);
|
928 |
928 |
|
929 |
929 |
return (bytes >= 0);
|
... | ... | |
935 |
935 |
|
936 |
936 |
vnc_write_u8(vs, VNC_TIGHT_FILL << 4); /* no flushing, no filter */
|
937 |
937 |
|
938 |
|
if (vs->tight_pixel24) {
|
939 |
|
tight_pack24(vs, vs->tight.buffer, 1, &vs->tight.offset);
|
|
938 |
if (vs->tight.pixel24) {
|
|
939 |
tight_pack24(vs, vs->tight.tight.buffer, 1, &vs->tight.tight.offset);
|
940 |
940 |
bytes = 3;
|
941 |
941 |
} else {
|
942 |
942 |
bytes = vs->clientds.pf.bytes_per_pixel;
|
943 |
943 |
}
|
944 |
944 |
|
945 |
|
vnc_write(vs, vs->tight.buffer, bytes);
|
|
945 |
vnc_write(vs, vs->tight.tight.buffer, bytes);
|
946 |
946 |
return 1;
|
947 |
947 |
}
|
948 |
948 |
|
... | ... | |
951 |
951 |
{
|
952 |
952 |
size_t bytes;
|
953 |
953 |
int stream = 1;
|
954 |
|
int level = tight_conf[vs->tight_compression].mono_zlib_level;
|
|
954 |
int level = tight_conf[vs->tight.compression].mono_zlib_level;
|
955 |
955 |
|
956 |
956 |
#ifdef CONFIG_VNC_PNG
|
957 |
957 |
if (tight_can_send_png_rect(vs, w, h)) {
|
... | ... | |
979 |
979 |
uint32_t buf[2] = {bg, fg};
|
980 |
980 |
size_t ret = sizeof (buf);
|
981 |
981 |
|
982 |
|
if (vs->tight_pixel24) {
|
|
982 |
if (vs->tight.pixel24) {
|
983 |
983 |
tight_pack24(vs, (unsigned char*)buf, 2, &ret);
|
984 |
984 |
}
|
985 |
985 |
vnc_write(vs, buf, ret);
|
986 |
986 |
|
987 |
|
tight_encode_mono_rect32(vs->tight.buffer, w, h, bg, fg);
|
|
987 |
tight_encode_mono_rect32(vs->tight.tight.buffer, w, h, bg, fg);
|
988 |
988 |
break;
|
989 |
989 |
}
|
990 |
990 |
case 2:
|
991 |
991 |
vnc_write(vs, &bg, 2);
|
992 |
992 |
vnc_write(vs, &fg, 2);
|
993 |
|
tight_encode_mono_rect16(vs->tight.buffer, w, h, bg, fg);
|
|
993 |
tight_encode_mono_rect16(vs->tight.tight.buffer, w, h, bg, fg);
|
994 |
994 |
break;
|
995 |
995 |
default:
|
996 |
996 |
vnc_write_u8(vs, bg);
|
997 |
997 |
vnc_write_u8(vs, fg);
|
998 |
|
tight_encode_mono_rect8(vs->tight.buffer, w, h, bg, fg);
|
|
998 |
tight_encode_mono_rect8(vs->tight.tight.buffer, w, h, bg, fg);
|
999 |
999 |
break;
|
1000 |
1000 |
}
|
1001 |
|
vs->tight.offset = bytes;
|
|
1001 |
vs->tight.tight.offset = bytes;
|
1002 |
1002 |
|
1003 |
1003 |
bytes = tight_compress_data(vs, stream, bytes, level, Z_DEFAULT_STRATEGY);
|
1004 |
1004 |
return (bytes >= 0);
|
... | ... | |
1028 |
1028 |
static bool send_gradient_rect(VncState *vs, int x, int y, int w, int h)
|
1029 |
1029 |
{
|
1030 |
1030 |
int stream = 3;
|
1031 |
|
int level = tight_conf[vs->tight_compression].gradient_zlib_level;
|
|
1031 |
int level = tight_conf[vs->tight.compression].gradient_zlib_level;
|
1032 |
1032 |
size_t bytes;
|
1033 |
1033 |
|
1034 |
1034 |
if (vs->clientds.pf.bytes_per_pixel == 1)
|
... | ... | |
1037 |
1037 |
vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4);
|
1038 |
1038 |
vnc_write_u8(vs, VNC_TIGHT_FILTER_GRADIENT);
|
1039 |
1039 |
|
1040 |
|
buffer_reserve(&vs->tight_gradient, w * 3 * sizeof (int));
|
|
1040 |
buffer_reserve(&vs->tight.gradient, w * 3 * sizeof (int));
|
1041 |
1041 |
|
1042 |
|
if (vs->tight_pixel24) {
|
1043 |
|
tight_filter_gradient24(vs, vs->tight.buffer, w, h);
|
|
1042 |
if (vs->tight.pixel24) {
|
|
1043 |
tight_filter_gradient24(vs, vs->tight.tight.buffer, w, h);
|
1044 |
1044 |
bytes = 3;
|
1045 |
1045 |
} else if (vs->clientds.pf.bytes_per_pixel == 4) {
|
1046 |
|
tight_filter_gradient32(vs, (uint32_t *)vs->tight.buffer, w, h);
|
|
1046 |
tight_filter_gradient32(vs, (uint32_t *)vs->tight.tight.buffer, w, h);
|
1047 |
1047 |
bytes = 4;
|
1048 |
1048 |
} else {
|
1049 |
|
tight_filter_gradient16(vs, (uint16_t *)vs->tight.buffer, w, h);
|
|
1049 |
tight_filter_gradient16(vs, (uint16_t *)vs->tight.tight.buffer, w, h);
|
1050 |
1050 |
bytes = 2;
|
1051 |
1051 |
}
|
1052 |
1052 |
|
1053 |
|
buffer_reset(&vs->tight_gradient);
|
|
1053 |
buffer_reset(&vs->tight.gradient);
|
1054 |
1054 |
|
1055 |
1055 |
bytes = w * h * bytes;
|
1056 |
|
vs->tight.offset = bytes;
|
|
1056 |
vs->tight.tight.offset = bytes;
|
1057 |
1057 |
|
1058 |
1058 |
bytes = tight_compress_data(vs, stream, bytes,
|
1059 |
1059 |
level, Z_FILTERED);
|
... | ... | |
1064 |
1064 |
int w, int h, VncPalette *palette)
|
1065 |
1065 |
{
|
1066 |
1066 |
int stream = 2;
|
1067 |
|
int level = tight_conf[vs->tight_compression].idx_zlib_level;
|
|
1067 |
int level = tight_conf[vs->tight.compression].idx_zlib_level;
|
1068 |
1068 |
int colors;
|
1069 |
1069 |
size_t bytes;
|
1070 |
1070 |
|
... | ... | |
1091 |
1091 |
palette_iter(palette, write_palette, &priv);
|
1092 |
1092 |
vnc_write(vs, header, sizeof(header));
|
1093 |
1093 |
|
1094 |
|
if (vs->tight_pixel24) {
|
|
1094 |
if (vs->tight.pixel24) {
|
1095 |
1095 |
tight_pack24(vs, vs->output.buffer + old_offset, colors, &offset);
|
1096 |
1096 |
vs->output.offset = old_offset + offset;
|
1097 |
1097 |
}
|
1098 |
1098 |
|
1099 |
|
tight_encode_indexed_rect32(vs->tight.buffer, w * h, palette);
|
|
1099 |
tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette);
|
1100 |
1100 |
break;
|
1101 |
1101 |
}
|
1102 |
1102 |
case 2:
|
... | ... | |
1106 |
1106 |
|
1107 |
1107 |
palette_iter(palette, write_palette, &priv);
|
1108 |
1108 |
vnc_write(vs, header, sizeof(header));
|
1109 |
|
tight_encode_indexed_rect16(vs->tight.buffer, w * h, palette);
|
|
1109 |
tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette);
|
1110 |
1110 |
break;
|
1111 |
1111 |
}
|
1112 |
1112 |
default:
|
... | ... | |
1114 |
1114 |
break;
|
1115 |
1115 |
}
|
1116 |
1116 |
bytes = w * h;
|
1117 |
|
vs->tight.offset = bytes;
|
|
1117 |
vs->tight.tight.offset = bytes;
|
1118 |
1118 |
|
1119 |
1119 |
bytes = tight_compress_data(vs, stream, bytes,
|
1120 |
1120 |
level, Z_DEFAULT_STRATEGY);
|
... | ... | |
1180 |
1180 |
static void rgb_prepare_row(VncState *vs, uint8_t *dst, int x, int y,
|
1181 |
1181 |
int count)
|
1182 |
1182 |
{
|
1183 |
|
if (vs->tight_pixel24)
|
|
1183 |
if (vs->tight.pixel24)
|
1184 |
1184 |
rgb_prepare_row24(vs, dst, x, y, count);
|
1185 |
1185 |
else if (ds_get_bytes_per_pixel(vs->ds) == 4)
|
1186 |
1186 |
rgb_prepare_row32(vs, dst, x, y, count);
|
... | ... | |
1201 |
1201 |
static void jpeg_init_destination(j_compress_ptr cinfo)
|
1202 |
1202 |
{
|
1203 |
1203 |
VncState *vs = cinfo->client_data;
|
1204 |
|
Buffer *buffer = &vs->tight_jpeg;
|
|
1204 |
Buffer *buffer = &vs->tight.jpeg;
|
1205 |
1205 |
|
1206 |
1206 |
cinfo->dest->next_output_byte = (JOCTET *)buffer->buffer + buffer->offset;
|
1207 |
1207 |
cinfo->dest->free_in_buffer = (size_t)(buffer->capacity - buffer->offset);
|
... | ... | |
1211 |
1211 |
static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo)
|
1212 |
1212 |
{
|
1213 |
1213 |
VncState *vs = cinfo->client_data;
|
1214 |
|
Buffer *buffer = &vs->tight_jpeg;
|
|
1214 |
Buffer *buffer = &vs->tight.jpeg;
|
1215 |
1215 |
|
1216 |
1216 |
buffer->offset = buffer->capacity;
|
1217 |
1217 |
buffer_reserve(buffer, 2048);
|
... | ... | |
1223 |
1223 |
static void jpeg_term_destination(j_compress_ptr cinfo)
|
1224 |
1224 |
{
|
1225 |
1225 |
VncState *vs = cinfo->client_data;
|
1226 |
|
Buffer *buffer = &vs->tight_jpeg;
|
|
1226 |
Buffer *buffer = &vs->tight.jpeg;
|
1227 |
1227 |
|
1228 |
1228 |
buffer->offset = buffer->capacity - cinfo->dest->free_in_buffer;
|
1229 |
1229 |
}
|
... | ... | |
1240 |
1240 |
if (ds_get_bytes_per_pixel(vs->ds) == 1)
|
1241 |
1241 |
return send_full_color_rect(vs, x, y, w, h);
|
1242 |
1242 |
|
1243 |
|
buffer_reserve(&vs->tight_jpeg, 2048);
|
|
1243 |
buffer_reserve(&vs->tight.jpeg, 2048);
|
1244 |
1244 |
|
1245 |
1245 |
cinfo.err = jpeg_std_error(&jerr);
|
1246 |
1246 |
jpeg_create_compress(&cinfo);
|
... | ... | |
1274 |
1274 |
|
1275 |
1275 |
vnc_write_u8(vs, VNC_TIGHT_JPEG << 4);
|
1276 |
1276 |
|
1277 |
|
tight_send_compact_size(vs, vs->tight_jpeg.offset);
|
1278 |
|
vnc_write(vs, vs->tight_jpeg.buffer, vs->tight_jpeg.offset);
|
1279 |
|
buffer_reset(&vs->tight_jpeg);
|
|
1277 |
tight_send_compact_size(vs, vs->tight.jpeg.offset);
|
|
1278 |
vnc_write(vs, vs->tight.jpeg.buffer, vs->tight.jpeg.offset);
|
|
1279 |
buffer_reset(&vs->tight.jpeg);
|
1280 |
1280 |
|
1281 |
1281 |
return 1;
|
1282 |
1282 |
}
|
... | ... | |
1292 |
1292 |
VncState *vs = priv->vs;
|
1293 |
1293 |
png_colorp color = &priv->png_palette[idx];
|
1294 |
1294 |
|
1295 |
|
if (vs->tight_pixel24)
|
|
1295 |
if (vs->tight.pixel24)
|
1296 |
1296 |
{
|
1297 |
1297 |
color->red = (pix >> vs->clientds.pf.rshift) & vs->clientds.pf.rmax;
|
1298 |
1298 |
color->green = (pix >> vs->clientds.pf.gshift) & vs->clientds.pf.gmax;
|
... | ... | |
1319 |
1319 |
{
|
1320 |
1320 |
VncState *vs = png_get_io_ptr(png_ptr);
|
1321 |
1321 |
|
1322 |
|
buffer_reserve(&vs->tight_png, vs->tight_png.offset + length);
|
1323 |
|
memcpy(vs->tight_png.buffer + vs->tight_png.offset, data, length);
|
|
1322 |
buffer_reserve(&vs->tight.png, vs->tight.png.offset + length);
|
|
1323 |
memcpy(vs->tight.png.buffer + vs->tight.png.offset, data, length);
|
1324 |
1324 |
|
1325 |
|
vs->tight_png.offset += length;
|
|
1325 |
vs->tight.png.offset += length;
|
1326 |
1326 |
}
|
1327 |
1327 |
|
1328 |
1328 |
static void png_flush_data(png_structp png_ptr)
|
... | ... | |
1347 |
1347 |
png_infop info_ptr;
|
1348 |
1348 |
png_colorp png_palette = NULL;
|
1349 |
1349 |
size_t offset;
|
1350 |
|
int level = tight_png_conf[vs->tight_compression].png_zlib_level;
|
1351 |
|
int filters = tight_png_conf[vs->tight_compression].png_filters;
|
|
1350 |
int level = tight_png_conf[vs->tight.compression].png_zlib_level;
|
|
1351 |
int filters = tight_png_conf[vs->tight.compression].png_filters;
|
1352 |
1352 |
uint8_t *buf;
|
1353 |
1353 |
int dy;
|
1354 |
1354 |
|
... | ... | |
1391 |
1391 |
|
1392 |
1392 |
png_set_PLTE(png_ptr, info_ptr, png_palette, palette_size(palette));
|
1393 |
1393 |
|
1394 |
|
offset = vs->tight.offset;
|
|
1394 |
offset = vs->tight.tight.offset;
|
1395 |
1395 |
if (vs->clientds.pf.bytes_per_pixel == 4) {
|
1396 |
|
tight_encode_indexed_rect32(vs->tight.buffer, w * h, palette);
|
|
1396 |
tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette);
|
1397 |
1397 |
} else {
|
1398 |
|
tight_encode_indexed_rect16(vs->tight.buffer, w * h, palette);
|
|
1398 |
tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette);
|
1399 |
1399 |
}
|
1400 |
1400 |
}
|
1401 |
1401 |
|
1402 |
1402 |
png_write_info(png_ptr, info_ptr);
|
1403 |
1403 |
|
1404 |
|
buffer_reserve(&vs->tight_png, 2048);
|
|
1404 |
buffer_reserve(&vs->tight.png, 2048);
|
1405 |
1405 |
buf = qemu_malloc(w * 3);
|
1406 |
1406 |
for (dy = 0; dy < h; dy++)
|
1407 |
1407 |
{
|
1408 |
1408 |
if (color_type == PNG_COLOR_TYPE_PALETTE) {
|
1409 |
|
memcpy(buf, vs->tight.buffer + (dy * w), w);
|
|
1409 |
memcpy(buf, vs->tight.tight.buffer + (dy * w), w);
|
1410 |
1410 |
} else {
|
1411 |
1411 |
rgb_prepare_row(vs, buf, x, y + dy, w);
|
1412 |
1412 |
}
|
... | ... | |
1424 |
1424 |
|
1425 |
1425 |
vnc_write_u8(vs, VNC_TIGHT_PNG << 4);
|
1426 |
1426 |
|
1427 |
|
tight_send_compact_size(vs, vs->tight_png.offset);
|
1428 |
|
vnc_write(vs, vs->tight_png.buffer, vs->tight_png.offset);
|
1429 |
|
buffer_reset(&vs->tight_png);
|
|
1427 |
tight_send_compact_size(vs, vs->tight.png.offset);
|
|
1428 |
vnc_write(vs, vs->tight.png.buffer, vs->tight.png.offset);
|
|
1429 |
buffer_reset(&vs->tight.png);
|
1430 |
1430 |
return 1;
|
1431 |
1431 |
}
|
1432 |
1432 |
#endif /* CONFIG_VNC_PNG */
|
1433 |
1433 |
|
1434 |
1434 |
static void vnc_tight_start(VncState *vs)
|
1435 |
1435 |
{
|
1436 |
|
buffer_reset(&vs->tight);
|
|
1436 |
buffer_reset(&vs->tight.tight);
|
1437 |
1437 |
|
1438 |
1438 |
// make the output buffer be the zlib buffer, so we can compress it later
|
1439 |
|
vs->tight_tmp = vs->output;
|
1440 |
|
vs->output = vs->tight;
|
|
1439 |
vs->tight.tmp = vs->output;
|
|
1440 |
vs->output = vs->tight.tight;
|
1441 |
1441 |
}
|
1442 |
1442 |
|
1443 |
1443 |
static void vnc_tight_stop(VncState *vs)
|
1444 |
1444 |
{
|
1445 |
1445 |
// switch back to normal output/zlib buffers
|
1446 |
|
vs->tight = vs->output;
|
1447 |
|
vs->output = vs->tight_tmp;
|
|
1446 |
vs->tight.tight = vs->output;
|
|
1447 |
vs->output = vs->tight.tmp;
|
1448 |
1448 |
}
|
1449 |
1449 |
|
1450 |
1450 |
static int send_sub_rect(VncState *vs, int x, int y, int w, int h)
|
... | ... | |
1454 |
1454 |
int colors;
|
1455 |
1455 |
int ret = 0;
|
1456 |
1456 |
|
1457 |
|
vnc_framebuffer_update(vs, x, y, w, h, vs->tight_type);
|
|
1457 |
vnc_framebuffer_update(vs, x, y, w, h, vs->tight.type);
|
1458 |
1458 |
|
1459 |
1459 |
vnc_tight_start(vs);
|
1460 |
1460 |
vnc_raw_send_framebuffer_update(vs, x, y, w, h);
|
... | ... | |
1464 |
1464 |
|
1465 |
1465 |
if (colors == 0) {
|
1466 |
1466 |
if (tight_detect_smooth_image(vs, w, h)) {
|
1467 |
|
if (vs->tight_quality == -1) {
|
|
1467 |
if (vs->tight.quality == -1) {
|
1468 |
1468 |
ret = send_gradient_rect(vs, x, y, w, h);
|
1469 |
1469 |
} else {
|
1470 |
1470 |
#ifdef CONFIG_VNC_JPEG
|
1471 |
|
int quality = tight_conf[vs->tight_quality].jpeg_quality;
|
|
1471 |
int quality = tight_conf[vs->tight.quality].jpeg_quality;
|
1472 |
1472 |
|
1473 |
1473 |
ret = send_jpeg_rect(vs, x, y, w, h, quality);
|
1474 |
1474 |
#else
|
... | ... | |
1484 |
1484 |
ret = send_mono_rect(vs, x, y, w, h, bg, fg);
|
1485 |
1485 |
} else if (colors <= 256) {
|
1486 |
1486 |
#ifdef CONFIG_VNC_JPEG
|
1487 |
|
if (colors > 96 && vs->tight_quality != -1 && vs->tight_quality <= 3 &&
|
|
1487 |
if (colors > 96 && vs->tight.quality != -1 && vs->tight.quality <= 3 &&
|
1488 |
1488 |
tight_detect_smooth_image(vs, w, h)) {
|
1489 |
|
int quality = tight_conf[vs->tight_quality].jpeg_quality;
|
|
1489 |
int quality = tight_conf[vs->tight.quality].jpeg_quality;
|
1490 |
1490 |
|
1491 |
1491 |
ret = send_jpeg_rect(vs, x, y, w, h, quality);
|
1492 |
1492 |
} else {
|
... | ... | |
1502 |
1502 |
|
1503 |
1503 |
static int send_sub_rect_solid(VncState *vs, int x, int y, int w, int h)
|
1504 |
1504 |
{
|
1505 |
|
vnc_framebuffer_update(vs, x, y, w, h, vs->tight_type);
|
|
1505 |
vnc_framebuffer_update(vs, x, y, w, h, vs->tight.type);
|
1506 |
1506 |
|
1507 |
1507 |
vnc_tight_start(vs);
|
1508 |
1508 |
vnc_raw_send_framebuffer_update(vs, x, y, w, h);
|
... | ... | |
1519 |
1519 |
int rw, rh;
|
1520 |
1520 |
int n = 0;
|
1521 |
1521 |
|
1522 |
|
max_size = tight_conf[vs->tight_compression].max_rect_size;
|
1523 |
|
max_width = tight_conf[vs->tight_compression].max_rect_width;
|
|
1522 |
max_size = tight_conf[vs->tight.compression].max_rect_size;
|
|
1523 |
max_width = tight_conf[vs->tight.compression].max_rect_width;
|
1524 |
1524 |
|
1525 |
1525 |
if (w > max_width || w * h > max_size) {
|
1526 |
1526 |
max_sub_width = (w > max_width) ? max_width : w;
|
... | ... | |
1629 |
1629 |
|
1630 |
1630 |
if (vs->clientds.pf.bytes_per_pixel == 4 && vs->clientds.pf.rmax == 0xFF &&
|
1631 |
1631 |
vs->clientds.pf.bmax == 0xFF && vs->clientds.pf.gmax == 0xFF) {
|
1632 |
|
vs->tight_pixel24 = true;
|
|
1632 |
vs->tight.pixel24 = true;
|
1633 |
1633 |
} else {
|
1634 |
|
vs->tight_pixel24 = false;
|
|
1634 |
vs->tight.pixel24 = false;
|
1635 |
1635 |
}
|
1636 |
1636 |
|
1637 |
1637 |
if (w * h < VNC_TIGHT_MIN_SPLIT_RECT_SIZE)
|
... | ... | |
1639 |
1639 |
|
1640 |
1640 |
/* Calculate maximum number of rows in one non-solid rectangle. */
|
1641 |
1641 |
|
1642 |
|
max_rows = tight_conf[vs->tight_compression].max_rect_size;
|
1643 |
|
max_rows /= MIN(tight_conf[vs->tight_compression].max_rect_width, w);
|
|
1642 |
max_rows = tight_conf[vs->tight.compression].max_rect_size;
|
|
1643 |
max_rows /= MIN(tight_conf[vs->tight.compression].max_rect_width, w);
|
1644 |
1644 |
|
1645 |
1645 |
return find_large_solid_color_rect(vs, x, y, w, h, max_rows);
|
1646 |
1646 |
}
|
... | ... | |
1648 |
1648 |
int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y,
|
1649 |
1649 |
int w, int h)
|
1650 |
1650 |
{
|
1651 |
|
vs->tight_type = VNC_ENCODING_TIGHT;
|
|
1651 |
vs->tight.type = VNC_ENCODING_TIGHT;
|
1652 |
1652 |
return tight_send_framebuffer_update(vs, x, y, w, h);
|
1653 |
1653 |
}
|
1654 |
1654 |
|
1655 |
1655 |
int vnc_tight_png_send_framebuffer_update(VncState *vs, int x, int y,
|
1656 |
1656 |
int w, int h)
|
1657 |
1657 |
{
|
1658 |
|
vs->tight_type = VNC_ENCODING_TIGHT_PNG;
|
|
1658 |
vs->tight.type = VNC_ENCODING_TIGHT_PNG;
|
1659 |
1659 |
return tight_send_framebuffer_update(vs, x, y, w, h);
|
1660 |
1660 |
}
|
1661 |
1661 |
|
1662 |
1662 |
void vnc_tight_clear(VncState *vs)
|
1663 |
1663 |
{
|
1664 |
1664 |
int i;
|
1665 |
|
for (i=0; i<ARRAY_SIZE(vs->tight_stream); i++) {
|
1666 |
|
if (vs->tight_stream[i].opaque) {
|
1667 |
|
deflateEnd(&vs->tight_stream[i]);
|
|
1665 |
for (i=0; i<ARRAY_SIZE(vs->tight.stream); i++) {
|
|
1666 |
if (vs->tight.stream[i].opaque) {
|
|
1667 |
deflateEnd(&vs->tight.stream[i]);
|
1668 |
1668 |
}
|
1669 |
1669 |
}
|
1670 |
1670 |
|
1671 |
|
buffer_free(&vs->tight);
|
1672 |
|
buffer_free(&vs->tight_zlib);
|
1673 |
|
buffer_free(&vs->tight_gradient);
|
|
1671 |
buffer_free(&vs->tight.tight);
|
|
1672 |
buffer_free(&vs->tight.zlib);
|
|
1673 |
buffer_free(&vs->tight.gradient);
|
1674 |
1674 |
#ifdef CONFIG_VNC_JPEG
|
1675 |
|
buffer_free(&vs->tight_jpeg);
|
|
1675 |
buffer_free(&vs->tight.jpeg);
|
1676 |
1676 |
#endif
|
1677 |
1677 |
}
|