/* Bitmap.java
* Component: ProperJavaRDP
*
* Revision: $Revision: 1.7 $
* Author: $Author: telliott $
* Date: $Date: 2005/09/27 14:15:39 $
*
* Copyright (c) 2005 Propero Limited
*
* Purpose: Provide a class for storage of Bitmap images, along with
* static methods for decompression and conversion of bitmaps.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* (See gpl.txt for details of the GNU General Public License.)
*
*/
package org.jopenray.rdp;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import org.apache.log4j.Logger;
public class Bitmap {
public int usage;
private int[] highdata = null;
private int width = 0;
private int height = 0;
private int x = 0;
private int y = 0;
protected static Logger logger = Logger.getLogger(Rdp.class);
public static int convertTo24(int colour) {
if (Options.server_bpp == 15)
return convert15to24(colour);
if (Options.server_bpp == 16)
return convert16to24(colour);
return colour;
}
public static int convert15to24(int colour16) {
int r24 = (colour16 >> 7) & 0xF8;
int g24 = (colour16 >> 2) & 0xF8;
int b24 = (colour16 << 3) & 0xFF;
r24 |= r24 >> 5;
g24 |= g24 >> 5;
b24 |= b24 >> 5;
return (r24 << 16) | (g24 << 8) | b24;
}
public static int convert16to24(int colour16) {
int r24 = (colour16 >> 8) & 0xF8;
int g24 = (colour16 >> 3) & 0xFC;
int b24 = (colour16 << 3) & 0xFF;
r24 |= r24 >> 5;
g24 |= g24 >> 6;
b24 |= b24 >> 5;
return (r24 << 16) | (g24 << 8) | b24;
}
private static int bmpCount = 0;
/**
* Read integer of a specified byte-length from byte array
*
* @param data
* Array to read from
* @param offset
* Offset in array to read from
* @param Bpp
* Number of bytes to read
* @return
*/
static int cvalx(byte[] data, int offset, int Bpp) {
int rv = 0;
if (Options.server_bpp == 15) {
int lower = data[offset] & 0xFF;
int full = (data[offset + 1] & 0xFF) << 8 | lower;
int r24 = (full >> 7) & 0xF8;
r24 |= r24 >> 5;
int g24 = (full >> 2) & 0xF8;
g24 |= g24 >> 5;
int b24 = (lower << 3) & 0xFF;
b24 |= b24 >> 5;
return (r24 << 16) | (g24 << 8) | b24;
} else if (Options.server_bpp == 16) {
int lower = data[offset] & 0xFF;
int full = (data[offset + 1] & 0xFF) << 8 | lower;
int r24 = (full >> 8) & 0xF8;
r24 |= r24 >> 5;
int g24 = (full >> 3) & 0xFC;
g24 |= g24 >> 6;
int b24 = (lower << 3) & 0xFF;
b24 |= b24 >> 5;
return (r24 << 16) | (g24 << 8) | b24;
} else {
for (int i = (Bpp - 1); i >= 0; i--) {
rv = rv << 8;
rv |= data[offset + i] & 0xFF;
}
}
return rv;
}
/**
*
* @param input
* @param startOffset
* @param offset
* @param Bpp
* @return
*/
static int getli(byte[] input, int startOffset, int offset, int Bpp) {
int rv = 0;
int rOffset = startOffset + (offset * Bpp);
for (int i = 0; i < Bpp; i++) {
rv = rv << 8;
rv |= (input[rOffset + (Bpp - i - 1)]) & 0xFF;
}
return rv;
}
/**
*
* @param input
* @param startlocation
* @param offset
* @param value
* @param Bpp
*/
static void setli(byte[] input, int startlocation, int offset, int value,
int Bpp) {
int location = startlocation + offset * Bpp;
input[location] = (byte) (value & 0xFF);
if (Bpp > 1)
input[location + 1] = (byte) ((value & 0xFF00) >> 8);
if (Bpp > 2)
input[location + 2] = (byte) ((value & 0xFF0000) >> 16);
}
/**
* Convert byte array representing a bitmap into integer array of pixels
*
* @param bitmap
* Byte array of bitmap data
* @param bytePerPixel
* Bytes-per-pixel for bitmap
* @return Integer array of pixel data representing input image data
*/
static int[] convertImage(byte[] bitmap, int bytePerPixel) {
final int length = bitmap.length / bytePerPixel;
int[] out = new int[length];
switch (bytePerPixel) {
case 1:
for (int i = 0; i < length; i++) {
out[i] = bitmap[i] & 0xFF;
out[i] = Bitmap.convertTo24(out[i]);
}
break;
case 2:
for (int i = 0; i < length; i++) {
out[i] = ((bitmap[i * bytePerPixel + 1] & 0xFF) << 8)
| (bitmap[i * bytePerPixel] & 0xFF);
out[i] = Bitmap.convertTo24(out[i]);
}
break;
case 3:
for (int i = 0; i < length; i++) {
out[i] = ((bitmap[i * bytePerPixel + 2] & 0xFF) << 16)
| ((bitmap[i * bytePerPixel + 1] & 0xFF) << 8)
| (bitmap[i * bytePerPixel] & 0xFF);
out[i] = Bitmap.convertTo24(out[i]);
}
break;
default:
throw new IllegalArgumentException("Bytes-per-pixel "
+ bytePerPixel + " not supported");
}
return out;
}
/**
* Constructor for Bitmap based on integer pixel values
*
* @param data
* Array of pixel data, one integer per pixel. Should have a
* length of width*height.
* @param width
* Width of bitmap represented by data
* @param height
* Height of bitmap represented by data
* @param x
* Desired x-coordinate of bitmap
* @param y
* Desired y-coordinate of bitmap
*/
public Bitmap(int[] data, int width, int height, int x, int y) {
this.highdata = data;
this.width = width;
this.height = height;
this.x = x;
this.y = y;
}
/**
* Constructor for Bitmap based on
*
* @param data
* Array of pixel data, each pixel represented by Bpp bytes.
* Should have a length of width*height*Bpp.
* @param width
* Width of bitmap represented by data
* @param height
* Height of bitmap represented by data
* @param x
* Desired x-coordinate of bitmap
* @param y
* Desired y-coordinate of bitmap
* @param Bpp
* Number of bytes per pixel in image represented by data
*/
public Bitmap(byte[] data, int width, int height, int x, int y, int Bpp) {
this.highdata = Bitmap.convertImage(data, Bpp);
this.width = width;
this.height = height;
this.x = x;
this.y = y;
}
/**
* Retrieve data representing this Bitmap, as an array of integer pixel
* values
*
* @return Bitmap pixel data
*/
public int[] getBitmapData() {
return this.highdata;
}
/**
* Retrieve width of the bitmap represented by this object
*
* @return Bitmap width
*/
public int getWidth() {
return this.width;
}
/**
* Retrieve height of the bitmap represented by this object
*
* @return Bitmap height
*/
public int getHeight() {
return this.height;
}
/**
* Retrieve desired x-coordinate of the bitmap represented by this object
*
* @return x-coordinate of this bitmap
*/
public int getX() {
return this.x;
}
/**
* Retrieve desired y-coordinate of the bitmap represented by this object
*
* @return y-coordinate of this bitmap
*/
public int getY() {
return this.y;
}
/**
* Decompress bitmap data from packet and output directly to supplied image
* object
*
* @param width
* Width of bitmap to decompress
* @param height
* Height of bitmap to decompress
* @param size
* Size of compressed data in bytes
* @param data
* Packet containing bitmap data
* @param Bpp
* Bytes per-pixel for bitmap
* @param cm
* Colour model of bitmap
* @param left
* X offset for drawing bitmap
* @param top
* Y offset for drawing bitmap
* @param w
* Image to draw bitmap to
* @return Original image object, with decompressed bitmap drawn at
* specified coordinates
* @throws RdesktopException
*/
public static WrappedImage decompressImgDirect(int width, int height,
int size, RdpPacket_Localised data, int Bpp, IndexColorModel cm,
int left, int top, WrappedImage w) throws RdesktopException {
// WrappedImage w = null;
byte[] compressed_pixel = new byte[size];
data.copyToByteArray(compressed_pixel, 0, data.getPosition(), size);
data.incrementPosition(size);
int previous = -1, line = 0, prevY = 0;
int input = 0, end = size;
int opcode = 0, count = 0, offset = 0, x = width;
int lastopcode = -1, fom_mask = 0;
int code = 0, color1 = 0, color2 = 0;
byte mixmask = 0;
int mask = 0;
int mix = 0xffffffff;
boolean insertmix = false, bicolor = false, isfillormix = false;
while (input < end) {
fom_mask = 0;
code = (compressed_pixel[input++] & 0x000000ff);
opcode = code >> 4;
/* Handle different opcode forms */
switch (opcode) {
case 0xc:
case 0xd:
case 0xe:
opcode -= 6;
count = code & 0xf;
offset = 16;
break;
case 0xf:
opcode = code & 0xf;
if (opcode < 9) {
count = (compressed_pixel[input++] & 0xff);
count |= ((compressed_pixel[input++] & 0xff) << 8);
} else {
count = (opcode < 0xb) ? 8 : 1;
}
offset = 0;
break;
default:
opcode >>= 1;
count = code & 0x1f;
offset = 32;
break;
}
/* Handle strange cases for counts */
if (offset != 0) {
isfillormix = ((opcode == 2) || (opcode == 7));
if (count == 0) {
if (isfillormix)
count = (compressed_pixel[input++] & 0x000000ff) + 1;
else
count = (compressed_pixel[input++] & 0x000000ff)
+ offset;
} else if (isfillormix) {
count <<= 3;
}
}
switch (opcode) {
case 0: /* Fill */
if ((lastopcode == opcode)
&& !((x == width) && (previous == -1)))
insertmix = true;
break;
case 8: /* Bicolor */
color1 = cvalx(compressed_pixel, input, Bpp);
// (compressed_pixel[input++]&0x000000ff);
input += Bpp;
case 3: /* Color */
color2 = cvalx(compressed_pixel, input, Bpp);
// color2 = (compressed_pixel[input++]&0x000000ff);
input += Bpp;
break;
case 6: /* SetMix/Mix */
case 7: /* SetMix/FillOrMix */
// mix = compressed_pixel[input++];
mix = cvalx(compressed_pixel, input, Bpp);
input += Bpp;
opcode -= 5;
break;
case 9: /* FillOrMix_1 */
mask = 0x03;
opcode = 0x02;
fom_mask = 3;
break;
case 0x0a: /* FillOrMix_2 */
mask = 0x05;
opcode = 0x02;
fom_mask = 5;
break;
}
lastopcode = opcode;
mixmask = 0;
/* Output body */
while (count > 0) {
if (x >= width) {
if (height <= 0)
throw new RdesktopException(
"Decompressing bitmap failed! Height = "
+ height);
x = 0;
height--;
previous = line;
prevY = previous / width;
line = height * width;
}
switch (opcode) {
case 0: /* Fill */
if (insertmix) {
if (previous == -1) {
// pixel[line+x] = mix;
w.setRGB(left + x, top + height, mix);
} else {
w.setRGB(left + x, top + height, w.getRGB(left + x,
top + prevY)
^ mix);
// pixel[line+x] = (pixel[previous+x] ^ mix);
}
insertmix = false;
count--;
x++;
}
if (previous == -1) {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// pixel[line+x] = 0;
w.setRGB(left + x, top + height, 0);
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// pixel[line+x] = 0;
w.setRGB(left + x, top + height, 0);
count--;
x++;
}
} else {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// pixel[line + x] = pixel[previous + x];
w.setRGB(left + x, top + height, w.getRGB(left
+ x, top + prevY));
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// pixel[line + x] = pixel[previous + x];
w.setRGB(left + x, top + height, w.getRGB(left + x,
top + prevY));
count--;
x++;
}
}
break;
case 1: /* Mix */
if (previous == -1) {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// pixel[line + x] = mix;
w.setRGB(left + x, top + height, mix);
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// pixel[line + x] = mix;
w.setRGB(left + x, top + height, mix);
count--;
x++;
}
} else {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// pixel[line + x] = pixel[previous + x] ^ mix;
w.setRGB(left + x, top + height, w.getRGB(left
+ x, top + prevY)
^ mix);
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// pixel[line + x] = pixel[previous + x] ^ mix;
w.setRGB(left + x, top + height, w.getRGB(left + x,
top + prevY)
^ mix);
count--;
x++;
}
}
break;
case 2: /* Fill or Mix */
if (previous == -1) {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
mixmask <<= 1;
if (mixmask == 0) {
mask = (fom_mask != 0) ? (byte) fom_mask
: compressed_pixel[input++];
mixmask = 1;
}
if ((mask & mixmask) != 0) {
// pixel[line + x] = (byte) mix;
w
.setRGB(left + x, top + height,
(byte) mix);
} else {
// pixel[line + x] = 0;
w.setRGB(left + x, top + height, 0);
}
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
mixmask <<= 1;
if (mixmask == 0) {
mask = (fom_mask != 0) ? (byte) fom_mask
: compressed_pixel[input++];
mixmask = 1;
}
if ((mask & mixmask) != 0) {
// pixel[line + x] = mix;
w.setRGB(left + x, top + height, mix);
} else {
// pixel[line + x] = 0;
w.setRGB(left + x, top + height, 0);
}
count--;
x++;
}
} else {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
mixmask <<= 1;
if (mixmask == 0) {
mask = (fom_mask != 0) ? (byte) fom_mask
: compressed_pixel[input++];
mixmask = 1;
}
if ((mask & mixmask) != 0) {
// pixel[line + x] = (pixel[previous + x] ^
// mix);
w.setRGB(left + x, top + height, w.getRGB(
left + x, prevY + top)
^ mix);
} else {
// pixel[line + x] = pixel[previous + x];
w.setRGB(left + x, top + height, w.getRGB(
left + x, prevY + top));
}
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
mixmask <<= 1;
if (mixmask == 0) {
mask = (fom_mask != 0) ? (byte) fom_mask
: compressed_pixel[input++];
mixmask = 1;
}
if ((mask & mixmask) != 0) {
// pixel[line + x] = (pixel[previous + x] ^
// mix);
w.setRGB(left + x, top + height, w.getRGB(left
+ x, prevY + top)
^ mix);
} else {
// pixel[line + x] = pixel[previous + x];
w.setRGB(left + x, top + height, w.getRGB(left
+ x, prevY + top));
}
count--;
x++;
}
}
break;
case 3: /* Color */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// pixel[line + x] = color2;
w.setRGB(left + x, top + height, color2);
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// pixel[line + x] = color2;
w.setRGB(left + x, top + height, color2);
count--;
x++;
}
break;
case 4: /* Copy */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// pixel[line + x] = cvalx(compressed_pixel, input,
// Bpp);
w.setRGB(left + x, top + height, cvalx(
compressed_pixel, input, Bpp));
input += Bpp;
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// pixel[line + x] = cvalx(compressed_pixel, input,
// Bpp);
w.setRGB(left + x, top + height, cvalx(
compressed_pixel, input, Bpp));
input += Bpp;
count--;
x++;
}
break;
case 8: /* Bicolor */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
if (bicolor) {
// pixel[line + x] = color2;
w.setRGB(left + x, top + height, color2);
bicolor = false;
} else {
// pixel[line + x] = color1;
w.setRGB(left + x, top + height, color1);
bicolor = true;
count++;
}
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
if (bicolor) {
// pixel[line + x] = color2;
w.setRGB(left + x, top + height, color2);
bicolor = false;
} else {
// pixel[line + x] = color1;
w.setRGB(left + x, top + height, color1);
bicolor = true;
count++;
}
count--;
x++;
}
break;
case 0xd: /* White */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// pixel[line + x] = 0xffffff;
w.setRGB(left + x, top + height, 0xffffff);
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// pixel[line + x] = 0xffffff;
w.setRGB(left + x, top + height, 0xffffff);
count--;
x++;
}
break;
case 0xe: /* Black */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// pixel[line + x] = 0x00;
w.setRGB(left + x, top + height, 0x00);
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// pixel[line + x] = 0x00;
w.setRGB(left + x, top + height, 0x00);
count--;
x++;
}
break;
default:
throw new RdesktopException(
"Unimplemented decompress opcode " + opcode);// ;
}
}
}
/*
* if(Options.server_bpp == 16){ for(int i = 0; i < pixel.length; i++)
* pixel[i] = Bitmap.convert16to24(pixel[i]); }
*/
return w;
}
/**
* Decompress bitmap data from packet and output as an Image
*
* @param width
* Width of bitmap
* @param height
* Height of bitmap
* @param size
* Size of compressed data in bytes
* @param data
* Packet containing bitmap data
* @param Bpp
* Bytes per-pixel for bitmap
* @param cm
* Colour model for bitmap (if using indexed palette)
* @return Decompressed bitmap as Image object
* @throws RdesktopException
*/
public static Image decompressImg(int width, int height, int size,
RdpPacket_Localised data, int Bpp, IndexColorModel cm)
throws RdesktopException {
WrappedImage w = null;
byte[] compressed_pixel = new byte[size];
data.copyToByteArray(compressed_pixel, 0, data.getPosition(), size);
data.incrementPosition(size);
int previous = -1, line = 0, prevY = 0;
int input = 0, end = size;
int opcode = 0, count = 0, offset = 0, x = width;
int lastopcode = -1, fom_mask = 0;
int code = 0, color1 = 0, color2 = 0;
byte mixmask = 0;
int mask = 0;
int mix = 0xffffffff;
boolean insertmix = false, bicolor = false, isfillormix = false;
if (cm == null)
w = new WrappedImage(width, height, BufferedImage.TYPE_INT_RGB);
else
w = new WrappedImage(width, height, BufferedImage.TYPE_INT_RGB, cm);
while (input < end) {
fom_mask = 0;
code = (compressed_pixel[input++] & 0x000000ff);
opcode = code >> 4;
/* Handle different opcode forms */
switch (opcode) {
case 0xc:
case 0xd:
case 0xe:
opcode -= 6;
count = code & 0xf;
offset = 16;
break;
case 0xf:
opcode = code & 0xf;
if (opcode < 9) {
count = (compressed_pixel[input++] & 0xff);
count |= ((compressed_pixel[input++] & 0xff) << 8);
} else {
count = (opcode < 0xb) ? 8 : 1;
}
offset = 0;
break;
default:
opcode >>= 1;
count = code & 0x1f;
offset = 32;
break;
}
/* Handle strange cases for counts */
if (offset != 0) {
isfillormix = ((opcode == 2) || (opcode == 7));
if (count == 0) {
if (isfillormix)
count = (compressed_pixel[input++] & 0x000000ff) + 1;
else
count = (compressed_pixel[input++] & 0x000000ff)
+ offset;
} else if (isfillormix) {
count <<= 3;
}
}
switch (opcode) {
case 0: /* Fill */
if ((lastopcode == opcode)
&& !((x == width) && (previous == -1)))
insertmix = true;
break;
case 8: /* Bicolor */
color1 = cvalx(compressed_pixel, input, Bpp);
// (compressed_pixel[input++]&0x000000ff);
input += Bpp;
case 3: /* Color */
color2 = cvalx(compressed_pixel, input, Bpp);
// color2 = (compressed_pixel[input++]&0x000000ff);
input += Bpp;
break;
case 6: /* SetMix/Mix */
case 7: /* SetMix/FillOrMix */
// mix = compressed_pixel[input++];
mix = cvalx(compressed_pixel, input, Bpp);
input += Bpp;
opcode -= 5;
break;
case 9: /* FillOrMix_1 */
mask = 0x03;
opcode = 0x02;
fom_mask = 3;
break;
case 0x0a: /* FillOrMix_2 */
mask = 0x05;
opcode = 0x02;
fom_mask = 5;
break;
}
lastopcode = opcode;
mixmask = 0;
/* Output body */
while (count > 0) {
if (x >= width) {
if (height <= 0)
throw new RdesktopException(
"Decompressing bitmap failed! Height = "
+ height);
x = 0;
height--;
previous = line;
prevY = previous / width;
line = height * width;
}
switch (opcode) {
case 0: /* Fill */
if (insertmix) {
if (previous == -1) {
// pixel[line+x] = mix;
w.setRGB(x, height, mix);
} else {
w.setRGB(x, height, w.getRGB(x, prevY) ^ mix);
// pixel[line+x] = (pixel[previous+x] ^ mix);
}
insertmix = false;
count--;
x++;
}
if (previous == -1) {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// pixel[line+x] = 0;
w.setRGB(x, height, 0);
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// pixel[line+x] = 0;
w.setRGB(x, height, 0);
count--;
x++;
}
} else {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// pixel[line + x] = pixel[previous + x];
w.setRGB(x, height, w.getRGB(x, prevY));
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// pixel[line + x] = pixel[previous + x];
w.setRGB(x, height, w.getRGB(x, prevY));
count--;
x++;
}
}
break;
case 1: /* Mix */
if (previous == -1) {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// pixel[line + x] = mix;
w.setRGB(x, height, mix);
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// pixel[line + x] = mix;
w.setRGB(x, height, mix);
count--;
x++;
}
} else {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// pixel[line + x] = pixel[previous + x] ^ mix;
w.setRGB(x, height, w.getRGB(x, prevY) ^ mix);
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// pixel[line + x] = pixel[previous + x] ^ mix;
w.setRGB(x, height, w.getRGB(x, prevY) ^ mix);
count--;
x++;
}
}
break;
case 2: /* Fill or Mix */
if (previous == -1) {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
mixmask <<= 1;
if (mixmask == 0) {
mask = (fom_mask != 0) ? (byte) fom_mask
: compressed_pixel[input++];
mixmask = 1;
}
if ((mask & mixmask) != 0) {
// pixel[line + x] = (byte) mix;
w.setRGB(x, height, (byte) mix);
} else {
// pixel[line + x] = 0;
w.setRGB(x, height, 0);
}
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
mixmask <<= 1;
if (mixmask == 0) {
mask = (fom_mask != 0) ? (byte) fom_mask
: compressed_pixel[input++];
mixmask = 1;
}
if ((mask & mixmask) != 0) {
// pixel[line + x] = mix;
w.setRGB(x, height, mix);
} else {
// pixel[line + x] = 0;
w.setRGB(x, height, 0);
}
count--;
x++;
}
} else {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
mixmask <<= 1;
if (mixmask == 0) {
mask = (fom_mask != 0) ? (byte) fom_mask
: compressed_pixel[input++];
mixmask = 1;
}
if ((mask & mixmask) != 0) {
// pixel[line + x] = (pixel[previous + x] ^
// mix);
w.setRGB(x, height, w.getRGB(x, prevY)
^ mix);
} else {
// pixel[line + x] = pixel[previous + x];
w.setRGB(x, height, w.getRGB(x, prevY));
}
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
mixmask <<= 1;
if (mixmask == 0) {
mask = (fom_mask != 0) ? (byte) fom_mask
: compressed_pixel[input++];
mixmask = 1;
}
if ((mask & mixmask) != 0) {
// pixel[line + x] = (pixel[previous + x] ^
// mix);
w.setRGB(x, height, w.getRGB(x, prevY) ^ mix);
} else {
// pixel[line + x] = pixel[previous + x];
w.setRGB(x, height, w.getRGB(x, prevY));
}
count--;
x++;
}
}
break;
case 3: /* Color */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// pixel[line + x] = color2;
w.setRGB(x, height, color2);
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// pixel[line + x] = color2;
w.setRGB(x, height, color2);
count--;
x++;
}
break;
case 4: /* Copy */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// pixel[line + x] = cvalx(compressed_pixel, input,
// Bpp);
w.setRGB(x, height, cvalx(compressed_pixel, input,
Bpp));
input += Bpp;
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// pixel[line + x] = cvalx(compressed_pixel, input,
// Bpp);
w
.setRGB(x, height, cvalx(compressed_pixel,
input, Bpp));
input += Bpp;
// pixel[line+x] = compressed_pixel[input++];
count--;
x++;
}
break;
case 8: /* Bicolor */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
if (bicolor) {
// pixel[line + x] = color2;
w.setRGB(x, height, color2);
bicolor = false;
} else {
// pixel[line + x] = color1;
w.setRGB(x, height, color1);
bicolor = true;
count++;
}
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
if (bicolor) {
// pixel[line + x] = color2;
w.setRGB(x, height, color2);
bicolor = false;
} else {
// pixel[line + x] = color1;
w.setRGB(x, height, color1);
bicolor = true;
count++;
}
count--;
x++;
}
break;
case 0xd: /* White */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// pixel[line + x] = 0xffffff;
w.setRGB(x, height, 0xffffff);
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// pixel[line + x] = 0xffffff;
w.setRGB(x, height, 0xffffff);
count--;
x++;
}
break;
case 0xe: /* Black */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// pixel[line + x] = 0x00;
w.setRGB(x, height, 0x00);
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// pixel[line + x] = 0x00;
w.setRGB(x, height, 0x00);
count--;
x++;
}
break;
default:
throw new RdesktopException(
"Unimplemented decompress opcode " + opcode);// ;
}
}
}
/*
* if(Options.server_bpp == 16){ for(int i = 0; i < pixel.length; i++)
* pixel[i] = Bitmap.convert16to24(pixel[i]); }
*/
return w.getBufferedImage();
}
/**
* Decompress bitmap data from packet and store in array of integers
*
* @param width
* Width of bitmap
* @param height
* Height of bitmap
* @param size
* Size of compressed data in bytes
* @param data
* Packet containing bitmap data
* @param Bpp
* Bytes per-pixel for bitmap
* @return Integer array of pixels containing decompressed bitmap data
* @throws RdesktopException
*/
public static int[] decompressInt(int width, int height, int size,
RdpPacket_Localised data, int Bpp) throws RdesktopException {
byte[] compressed_pixel = new byte[size];
data.copyToByteArray(compressed_pixel, 0, data.getPosition(), size);
data.incrementPosition(size);
int previous = -1, line = 0;
int input = 0, output = 0, end = size;
int opcode = 0, count = 0, offset = 0, x = width;
int lastopcode = -1, fom_mask = 0;
int code = 0, color1 = 0, color2 = 0;
byte mixmask = 0;
int mask = 0;
int mix = 0xffffffff;
boolean insertmix = false, bicolor = false, isfillormix = false;
int[] pixel = new int[width * height];
while (input < end) {
fom_mask = 0;
code = (compressed_pixel[input++] & 0x000000ff);
opcode = code >> 4;
/* Handle different opcode forms */
switch (opcode) {
case 0xc:
case 0xd:
case 0xe:
opcode -= 6;
count = code & 0xf;
offset = 16;
break;
case 0xf:
opcode = code & 0xf;
if (opcode < 9) {
count = (compressed_pixel[input++] & 0xff);
count |= ((compressed_pixel[input++] & 0xff) << 8);
} else {
count = (opcode < 0xb) ? 8 : 1;
}
offset = 0;
break;
default:
opcode >>= 1;
count = code & 0x1f;
offset = 32;
break;
}
/* Handle strange cases for counts */
if (offset != 0) {
isfillormix = ((opcode == 2) || (opcode == 7));
if (count == 0) {
if (isfillormix)
count = (compressed_pixel[input++] & 0x000000ff) + 1;
else
count = (compressed_pixel[input++] & 0x000000ff)
+ offset;
} else if (isfillormix) {
count <<= 3;
}
}
switch (opcode) {
case 0: /* Fill */
if ((lastopcode == opcode)
&& !((x == width) && (previous == -1)))
insertmix = true;
break;
case 8: /* Bicolor */
color1 = cvalx(compressed_pixel, input, Bpp);
// (compressed_pixel[input++]&0x000000ff);
input += Bpp;
case 3: /* Color */
color2 = cvalx(compressed_pixel, input, Bpp);
// color2 = (compressed_pixel[input++]&0x000000ff);
input += Bpp;
break;
case 6: /* SetMix/Mix */
case 7: /* SetMix/FillOrMix */
// mix = compressed_pixel[input++];
mix = cvalx(compressed_pixel, input, Bpp);
input += Bpp;
opcode -= 5;
break;
case 9: /* FillOrMix_1 */
mask = 0x03;
opcode = 0x02;
fom_mask = 3;
break;
case 0x0a: /* FillOrMix_2 */
mask = 0x05;
opcode = 0x02;
fom_mask = 5;
break;
}
lastopcode = opcode;
mixmask = 0;
/* Output body */
while (count > 0) {
if (x >= width) {
if (height <= 0)
throw new RdesktopException(
"Decompressing bitmap failed! Height = "
+ height);
x = 0;
height--;
previous = line;
line = output + height * width;
}
switch (opcode) {
case 0: /* Fill */
if (insertmix) {
if (previous == -1) {
pixel[line + x] = mix;
} else {
pixel[line + x] = (pixel[previous + x] ^ mix);
}
insertmix = false;
count--;
x++;
}
if (previous == -1) {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// setli(pixel, line, x, 0);
pixel[line + x] = 0;
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// setli(pixel, line, x, 0);
pixel[line + x] = 0;
count--;
x++;
}
} else {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// setli(pixel, line, x, pixel[previous + x]);
pixel[line + x] = pixel[previous + x];
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// setli(pixel, line, x, pixel[previous + x]);
pixel[line + x] = pixel[previous + x];
count--;
x++;
}
}
break;
case 1: /* Mix */
if (previous == -1) {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// setli(pixel, line, x, mix, Bpp);
pixel[line + x] = mix;
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// setli(pixel, line, x, mix, Bpp);
pixel[line + x] = mix;
count--;
x++;
}
} else {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// setli(pixel, line, x, pixel[previous + x] ^
// mix);
pixel[line + x] = pixel[previous + x] ^ mix;
// setli(pixel, line, x, 0, Bpp);
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// setli(pixel, line, x, pixel[previous + x] ^ mix);
pixel[line + x] = pixel[previous + x] ^ mix;
// setli(pixel, line, x, 0, Bpp);
count--;
x++;
}
}
break;
case 2: /* Fill or Mix */
if (previous == -1) {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
mixmask <<= 1;
if (mixmask == 0) {
mask = (fom_mask != 0) ? (byte) fom_mask
: compressed_pixel[input++];
mixmask = 1;
}
if ((mask & mixmask) != 0)
// setli(pixel, line, x, mix, Bpp);
pixel[line + x] = (byte) mix;
else
// setli(pixel, line, x, 0, Bpp);
pixel[line + x] = 0;
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
mixmask <<= 1;
if (mixmask == 0) {
mask = (fom_mask != 0) ? (byte) fom_mask
: compressed_pixel[input++];
mixmask = 1;
}
if ((mask & mixmask) != 0)
// setli(pixel, line, x, mix, Bpp);
pixel[line + x] = mix;
else
// setli(pixel, line, x, 0, Bpp);
pixel[line + x] = 0;
count--;
x++;
}
} else {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
mixmask <<= 1;
if (mixmask == 0) {
mask = (fom_mask != 0) ? (byte) fom_mask
: compressed_pixel[input++];
mixmask = 1;
}
if ((mask & mixmask) != 0)
// setli(pixel, line, x,
// getli(pixel,previous, x, Bpp) ^ mix,
// Bpp);
pixel[line + x] = (pixel[previous + x] ^ mix);
else
// setli(pixel, line, x, getli(pixel,
// previous, x, Bpp), Bpp);
pixel[line + x] = pixel[previous + x];
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
mixmask <<= 1;
if (mixmask == 0) {
mask = (fom_mask != 0) ? (byte) fom_mask
: compressed_pixel[input++];
mixmask = 1;
}
if ((mask & mixmask) != 0)
// setli(pixel, line, x, getli(pixel, previous,
// x, Bpp) ^ mix, Bpp);
pixel[line + x] = (pixel[previous + x] ^ mix);
else
// setli(pixel, line, x, getli(pixel, previous,
// x, Bpp), Bpp);
pixel[line + x] = pixel[previous + x];
count--;
x++;
}
}
break;
case 3: /* Color */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// setli(pixel, line, x, color2, Bpp);
pixel[line + x] = color2;
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// setli(pixel, line, x, color2, Bpp);
pixel[line + x] = color2;
count--;
x++;
}
break;
case 4: /* Copy */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// setli(pixel, line, x, cvalx(compressed_pixel,
// input, Bpp), Bpp);
// pixel[line+x] = compressed_pixel[input++];
pixel[line + x] = cvalx(compressed_pixel, input,
Bpp);
input += Bpp;
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// setli(pixel, line, x, cvalx(compressed_pixel,
// input,Bpp), Bpp);
pixel[line + x] = cvalx(compressed_pixel, input, Bpp);
input += Bpp;
// pixel[line+x] = compressed_pixel[input++];
count--;
x++;
}
break;
case 8: /* Bicolor */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
if (bicolor) {
// setli(pixel, line, x, color2, Bpp);
pixel[line + x] = color2;
bicolor = false;
} else {
// setli(pixel, line, x, color1, Bpp);
pixel[line + x] = color1;
bicolor = true;
count++;
}
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
if (bicolor) {
// setli(pixel, line, x, color2, Bpp);
pixel[line + x] = color2;
bicolor = false;
} else {
// setli(pixel, line, x, color1, Bpp);
pixel[line + x] = color1;
bicolor = true;
count++;
}
count--;
x++;
}
break;
case 0xd: /* White */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// setli(pixel, line, x, 0xffffff, Bpp);
pixel[line + x] = 0xffffff;
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// setli(pixel, line, x, 0xffffff, Bpp);
pixel[line + x] = 0xffffff;
count--;
x++;
}
break;
case 0xe: /* Black */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// setli(pixel, line, x, 0x00, Bpp);
pixel[line + x] = 0x00;
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// setli(pixel, line, x, 0x00, Bpp);
pixel[line + x] = 0x00;
count--;
x++;
}
break;
default:
throw new RdesktopException(
"Unimplemented decompress opcode " + opcode);// ;
}
}
}
/*
* if(Options.server_bpp == 16){ for(int i = 0; i < pixel.length; i++)
* pixel[i] = Bitmap.convert16to24(pixel[i]); }
*/
return pixel;
}
/**
* Decompress bitmap data from packet and store in array of bytes
*
* @param width
* Width of bitmap
* @param height
* Height of bitmap
* @param size
* Size of compressed data in bytes
* @param data
* Packet containing bitmap data
* @param Bpp
* Bytes per-pixel for bitmap
* @return Byte array of pixels containing decompressed bitmap data
* @throws RdesktopException
*/
public static byte[] decompress(int width, int height, int size,
RdpPacket_Localised data, int Bpp) throws RdesktopException {
byte[] compressed_pixel = new byte[size];
data.copyToByteArray(compressed_pixel, 0, data.getPosition(), size);
data.incrementPosition(size);
int previous = 0, line = 0;
int input = 0, output = 0, end = size;
int opcode = 0, count = 0, offset = 0, x = width;
int lastopcode = -1, fom_mask = 0;
int code = 0, color1 = 0, color2 = 0;
byte mixmask = 0;
int mask = 0;
int mix = 0xffffffff;
boolean insertmix = false, bicolor = false, isfillormix = false;
byte[] pixel = new byte[width * height];
while (input < end) {
fom_mask = 0;
code = (compressed_pixel[input++] & 0x000000ff);
opcode = code >> 4;
/* Handle different opcode forms */
switch (opcode) {
case 0xc:
case 0xd:
case 0xe:
opcode -= 6;
count = code & 0xf;
offset = 16;
break;
case 0xf:
opcode = code & 0xf;
if (opcode < 9) {
count = (compressed_pixel[input++] & 0xff);
count |= ((compressed_pixel[input++] & 0xff) << 8);
} else {
count = (opcode < 0xb) ? 8 : 1;
}
offset = 0;
break;
default:
opcode >>= 1;
count = code & 0x1f;
offset = 32;
break;
}
/* Handle strange cases for counts */
if (offset != 0) {
isfillormix = ((opcode == 2) || (opcode == 7));
if (count == 0) {
if (isfillormix)
count = (compressed_pixel[input++] & 0x000000ff) + 1;
else
count = (compressed_pixel[input++] & 0x000000ff)
+ offset;
} else if (isfillormix) {
count <<= 3;
}
}
switch (opcode) {
case 0: /* Fill */
if ((lastopcode == opcode)
&& !((x == width) && (previous == 0)))
insertmix = true;
break;
case 8: /* Bicolor */
// color1 = cvalx(compressed_pixel, input, Bpp); //
// (compressed_pixel[input++]&0x000000ff);
color1 = (compressed_pixel[input++] & 0x000000ff);
// input += Bpp;
case 3: /* Color */
// color2 = cvalx(compressed_pixel, input, Bpp);
color2 = (compressed_pixel[input++] & 0x000000ff);
// input += Bpp;
break;
case 6: /* SetMix/Mix */
case 7: /* SetMix/FillOrMix */
mix = compressed_pixel[input++];
// mix = cvalx(compressed_pixel, input, Bpp);
// input += Bpp;
opcode -= 5;
break;
case 9: /* FillOrMix_1 */
mask = 0x03;
opcode = 0x02;
fom_mask = 3;
break;
case 0x0a: /* FillOrMix_2 */
mask = 0x05;
opcode = 0x02;
fom_mask = 5;
break;
}
lastopcode = opcode;
mixmask = 0;
/* Output body */
while (count > 0) {
if (x >= width) {
if (height <= 0)
throw new RdesktopException(
"Decompressing bitmap failed! Height = "
+ height);
x = 0;
height--;
previous = line;
line = output + height * width;
}
switch (opcode) {
case 0: /* Fill */
if (insertmix) {
if (previous == 0) {
pixel[line + x] = (byte) mix;
} else {
// setli(pixel, line, x, getli(pixel, previous, x,
// Bpp) ^ mix, Bpp);
pixel[line + x] = (byte) (pixel[previous + x] ^ (byte) mix);
}
insertmix = false;
count--;
x++;
}
if (previous == 0) {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// setli(pixel, line, x, 0, Bpp);
pixel[line + x] = 0;
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// setli(pixel, line, x, 0, Bpp);
pixel[line + x] = 0;
count--;
x++;
}
} else {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// setli(pixel, line, x, getli(pixel, previous,
// x, Bpp), Bpp);
pixel[line + x] = pixel[previous + x];
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// setli(pixel, line, x, getli(pixel, previous, x,
// Bpp), Bpp);
pixel[line + x] = pixel[previous + x];
count--;
x++;
}
}
break;
case 1: /* Mix */
if (previous == 0) {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// setli(pixel, line, x, mix, Bpp);
pixel[line + x] = (byte) mix;
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// setli(pixel, line, x, mix, Bpp);
pixel[line + x] = (byte) mix;
count--;
x++;
}
} else {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
setli(pixel, line, x, getli(pixel, previous, x,
1)
^ mix, 1);
// setli(pixel, line, x, 0, Bpp);
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
setli(pixel, line, x, getli(pixel, previous, x, 1)
^ mix, 1);
// setli(pixel, line, x, 0, Bpp);
count--;
x++;
}
}
break;
case 2: /* Fill or Mix */
if (previous == 0) {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
mixmask <<= 1;
if (mixmask == 0) {
mask = (fom_mask != 0) ? (byte) fom_mask
: compressed_pixel[input++];
mixmask = 1;
}
if ((mask & mixmask) != 0)
// setli(pixel, line, x, mix, Bpp);
pixel[line + x] = (byte) mix;
else
// setli(pixel, line, x, 0, Bpp);
pixel[line + x] = 0;
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
mixmask <<= 1;
if (mixmask == 0) {
mask = (fom_mask != 0) ? (byte) fom_mask
: compressed_pixel[input++];
mixmask = 1;
}
if ((mask & mixmask) != 0)
// setli(pixel, line, x, mix, Bpp);
pixel[line + x] = (byte) mix;
else
// setli(pixel, line, x, 0, Bpp);
pixel[line + x] = 0;
count--;
x++;
}
} else {
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
mixmask <<= 1;
if (mixmask == 0) {
mask = (fom_mask != 0) ? (byte) fom_mask
: compressed_pixel[input++];
mixmask = 1;
}
if ((mask & mixmask) != 0)
// setli(pixel, line, x, getli(pixel,
// previous, x, Bpp)
// ^ mix, Bpp);
pixel[line + x] = (byte) (pixel[previous
+ x] ^ (byte) mix);
else
// setli(pixel, line, x, getli(pixel,
// previous, x, Bpp), Bpp);
pixel[line + x] = pixel[previous + x];
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
mixmask <<= 1;
if (mixmask == 0) {
mask = (fom_mask != 0) ? (byte) fom_mask
: compressed_pixel[input++];
mixmask = 1;
}
if ((mask & mixmask) != 0)
// setli(pixel, line, x, getli(pixel, previous,
// x,
// Bpp)
// ^ mix, Bpp);
pixel[line + x] = (byte) (pixel[previous + x] ^ (byte) mix);
else
// setli(pixel, line, x, getli(pixel, previous,
// x,
// Bpp), Bpp);
pixel[line + x] = pixel[previous + x];
count--;
x++;
}
}
break;
case 3: /* Color */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// setli(pixel, line, x, color2, Bpp);
pixel[line + x] = (byte) color2;
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// setli(pixel, line, x, color2, Bpp);
pixel[line + x] = (byte) color2;
count--;
x++;
}
break;
case 4: /* Copy */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// setli(pixel, line, x, cvalx(compressed_pixel,
// input, Bpp), Bpp);
pixel[line + x] = compressed_pixel[input++];
// input += Bpp;
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// setli(pixel, line, x, cvalx(compressed_pixel, input,
// Bpp), Bpp);
// input += Bpp;
pixel[line + x] = compressed_pixel[input++];
count--;
x++;
}
break;
case 8: /* Bicolor */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
if (bicolor) {
// setli(pixel, line, x, color2, Bpp);
pixel[line + x] = (byte) color2;
bicolor = false;
} else {
// setli(pixel, line, x, color1, Bpp);
pixel[line + x] = (byte) color1;
bicolor = true;
count++;
}
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
if (bicolor) {
// setli(pixel, line, x, color2, Bpp);
pixel[line + x] = (byte) color2;
bicolor = false;
} else {
// setli(pixel, line, x, color1, Bpp);
pixel[line + x] = (byte) color1;
bicolor = true;
count++;
}
count--;
x++;
}
break;
case 0xd: /* White */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// setli(pixel, line, x, 0xffffffff, Bpp);
pixel[line + x] = (byte) 0xff;
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// setli(pixel, line, x, 0xffffffff, Bpp);
pixel[line + x] = (byte) 0xff;
count--;
x++;
}
break;
case 0xe: /* Black */
while (((count & ~0x7) != 0) && ((x + 8) < width)) {
for (int i = 0; i < 8; i++) {
// setli(pixel, line, x, 0, Bpp);
pixel[line + x] = (byte) 0x00;
count--;
x++;
}
}
while ((count > 0) && (x < width)) {
// setli(pixel, line, x, 0, Bpp);
pixel[line + x] = (byte) 0x00;
count--;
x++;
}
break;
default:
throw new RdesktopException(
"Unimplemented decompress opcode " + opcode);// ;
}
}
}
bmpCount++;
return pixel;
}
}