0001: ///////////////////////////////////////////////////////////////////////////////
0002: //
0003: // This program is free software; you can redistribute it and/or modify
0004: // it under the terms of the GNU General Public License and GNU Library
0005: // General Public License as published by the Free Software Foundation;
0006: // either version 2, or (at your option) any later version.
0007: //
0008: // This program is distributed in the hope that it will be useful,
0009: // but WITHOUT ANY WARRANTY; without even the implied warranty of
0010: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0011: // GNU General Public License and GNU Library General Public License
0012: // for more details.
0013: //
0014: // You should have received a copy of the GNU General Public License
0015: // and GNU Library General Public License along with this program; if
0016: // not, write to the Free Software Foundation, 675 Mass Ave, Cambridge,
0017: // MA 02139, USA.
0018: //
0019: ///////////////////////////////////////////////////////////////////////////////
0020:
0021: package org.rdesktop.server.rdp;
0022:
0023: import java.awt.Image;
0024: import java.awt.image.*;
0025: import java.awt.image.IndexColorModel;
0026:
0027: public class RdpBitmap {
0028: private int m_x = 0;
0029: private int m_y = 0;
0030: private int m_width = 0;
0031: private int m_height = 0;
0032: private int[] m_highdata = null;
0033: public int usage;
0034:
0035: public static int convertTo24(int colour) {
0036: if (RdpOptions.server_bpp == 15) {
0037: return convert15to24(colour);
0038: }
0039:
0040: if (RdpOptions.server_bpp == 16) {
0041: return convert16to24(colour);
0042: }
0043:
0044: return colour;
0045: }
0046:
0047: public static int convert15to24(int colour16) {
0048: int r24 = (colour16 >> 7) & 0xF8;
0049: int g24 = (colour16 >> 2) & 0xF8;
0050: int b24 = (colour16 << 3) & 0xFF;
0051:
0052: r24 |= r24 >> 5;
0053: g24 |= g24 >> 5;
0054: b24 |= b24 >> 5;
0055:
0056: return (r24 << 16) | (g24 << 8) | b24;
0057: }
0058:
0059: public static int convert16to24(int colour16) {
0060: int r24 = (colour16 >> 8) & 0xF8;
0061: int g24 = (colour16 >> 3) & 0xFC;
0062: int b24 = (colour16 << 3) & 0xFF;
0063:
0064: r24 |= r24 >> 5;
0065: g24 |= g24 >> 6;
0066: b24 |= b24 >> 5;
0067:
0068: return (r24 << 16) | (g24 << 8) | b24;
0069: }
0070:
0071: static int cvalx(byte[] data, int offset, int Bpp) {
0072: int rv = 0;
0073:
0074: if (RdpOptions.server_bpp == 15) {
0075: int lower = data[offset] & 0xFF;
0076: int full = (data[offset + 1] & 0xFF) << 8 | lower;
0077:
0078: int r24 = (full >> 7) & 0xF8;
0079: r24 |= r24 >> 5;
0080: int g24 = (full >> 2) & 0xF8;
0081: g24 |= g24 >> 5;
0082: int b24 = (lower << 3) & 0xFF;
0083: b24 |= b24 >> 5;
0084:
0085: return (r24 << 16) | (g24 << 8) | b24;
0086: } else if (RdpOptions.server_bpp == 16) {
0087: int lower = data[offset] & 0xFF;
0088: int full = (data[offset + 1] & 0xFF) << 8 | lower;
0089:
0090: int r24 = (full >> 8) & 0xF8;
0091: r24 |= r24 >> 5;
0092: int g24 = (full >> 3) & 0xFC;
0093: g24 |= g24 >> 6;
0094: int b24 = (lower << 3) & 0xFF;
0095: b24 |= b24 >> 5;
0096:
0097: return (r24 << 16) | (g24 << 8) | b24;
0098: } else {
0099: for (int i = (Bpp - 1); i >= 0; i--) {
0100: rv = rv << 8;
0101: rv |= data[offset + i] & 0xFF;
0102: }
0103: }
0104:
0105: return rv;
0106: }
0107:
0108: static int getli(byte[] input, int startOffset, int offset, int Bpp) {
0109: int rv = 0;
0110:
0111: int rOffset = startOffset + (offset * Bpp);
0112:
0113: for (int i = 0; i < Bpp; i++) {
0114: rv = rv << 8;
0115: rv |= (input[rOffset + (Bpp - i - 1)]) & 0xFF;
0116: }
0117:
0118: return rv;
0119: }
0120:
0121: static void setli(byte[] input, int startlocation, int offset,
0122: int value, int Bpp) {
0123: int location = startlocation + offset * Bpp;
0124:
0125: input[location] = (byte) (value & 0xFF);
0126:
0127: if (Bpp > 1) {
0128: input[location + 1] = (byte) ((value & 0xFF00) >> 8);
0129: }
0130:
0131: if (Bpp > 2) {
0132: input[location + 2] = (byte) ((value & 0xFF0000) >> 16);
0133: }
0134: }
0135:
0136: static int[] convertImage(byte[] bitmap, int Bpp) {
0137: int[] out = new int[bitmap.length / Bpp];
0138:
0139: for (int i = 0; i < out.length; i++) {
0140: if (Bpp == 1) {
0141: out[i] = bitmap[i] & 0xFF;
0142: } else if (Bpp == 2) {
0143: out[i] = ((bitmap[i * Bpp + 1] & 0xFF) << 8)
0144: | (bitmap[i * Bpp] & 0xFF);
0145: } else if (Bpp == 3) {
0146: out[i] = ((bitmap[i * Bpp + 2] & 0xFF) << 16)
0147: | ((bitmap[i * Bpp + 1] & 0xFF) << 8)
0148: | (bitmap[i * Bpp] & 0xFF);
0149: }
0150:
0151: out[i] = RdpBitmap.convertTo24(out[i]);
0152: }
0153:
0154: return out;
0155: }
0156:
0157: public static RdpImage decompressImgDirect(int width, int height,
0158: int size, RdpPacket data, int Bpp, IndexColorModel cm,
0159: int left, int top, RdpImage w) throws RdpDesktopException {
0160: byte[] compressed_pixel = new byte[size];
0161: data.copyToByteArray(compressed_pixel, 0, data.getPosition(),
0162: size);
0163: data.incrementPosition(size);
0164:
0165: int previous = -1, line = 0, prevY = 0;
0166: int input = 0, end = size;
0167: int opcode = 0, count = 0, offset = 0, x = width;
0168: int lastopcode = -1, fom_mask = 0;
0169: int code = 0, color1 = 0, color2 = 0;
0170: byte mixmask = 0;
0171: int mask = 0;
0172: int mix = 0xffffffff;
0173:
0174: boolean insertmix = false, bicolor = false, isfillormix = false;
0175:
0176: while (input < end) {
0177: fom_mask = 0;
0178: code = (compressed_pixel[input++] & 0x000000ff);
0179: opcode = code >> 4;
0180:
0181: switch (opcode) {
0182: case 0xc:
0183: case 0xd:
0184: case 0xe: {
0185: opcode -= 6;
0186: count = code & 0xf;
0187: offset = 16;
0188: break;
0189: }
0190: case 0xf: {
0191: opcode = code & 0xf;
0192: if (opcode < 9) {
0193: count = (compressed_pixel[input++] & 0xff);
0194: count |= ((compressed_pixel[input++] & 0xff) << 8);
0195: } else {
0196: count = (opcode < 0xb) ? 8 : 1;
0197: }
0198: offset = 0;
0199: break;
0200: }
0201: default: {
0202: opcode >>= 1;
0203: count = code & 0x1f;
0204: offset = 32;
0205: break;
0206: }
0207: }
0208:
0209: if (offset != 0) {
0210: isfillormix = ((opcode == 2) || (opcode == 7));
0211:
0212: if (count == 0) {
0213: if (isfillormix) {
0214: count = (compressed_pixel[input++] & 0x000000ff) + 1;
0215: } else {
0216: count = (compressed_pixel[input++] & 0x000000ff)
0217: + offset;
0218: }
0219: } else if (isfillormix) {
0220: count <<= 3;
0221: }
0222: }
0223:
0224: switch (opcode) {
0225: case 0: /* Fill */
0226: {
0227: if ((lastopcode == opcode)
0228: && !((x == width) && (previous == -1))) {
0229: insertmix = true;
0230: }
0231: break;
0232: }
0233: case 8: /* Bicolor */
0234: {
0235: color1 = cvalx(compressed_pixel, input, Bpp);
0236: input += Bpp;
0237: }
0238: case 3: /* Color */
0239: {
0240: color2 = cvalx(compressed_pixel, input, Bpp);
0241: input += Bpp;
0242: break;
0243: }
0244: case 6: /* SetMix/Mix */
0245: case 7: /* SetMix/FillOrMix */
0246: {
0247: mix = cvalx(compressed_pixel, input, Bpp);
0248: input += Bpp;
0249: opcode -= 5;
0250: break;
0251: }
0252: case 9: /* FillOrMix_1 */
0253: {
0254: mask = 0x03;
0255: opcode = 0x02;
0256: fom_mask = 3;
0257: break;
0258: }
0259: case 0x0a: /* FillOrMix_2 */
0260: {
0261: mask = 0x05;
0262: opcode = 0x02;
0263: fom_mask = 5;
0264: break;
0265: }
0266: }
0267:
0268: lastopcode = opcode;
0269: mixmask = 0;
0270:
0271: while (count > 0) {
0272: if (x >= width) {
0273: if (height <= 0) {
0274: throw new RdpDesktopException(
0275: "Decompressing bitmap failed! Height = "
0276: + height);
0277: }
0278: x = 0;
0279: height--;
0280:
0281: previous = line;
0282: prevY = previous / width;
0283: line = height * width;
0284: }
0285:
0286: switch (opcode) {
0287: case 0: /* Fill */
0288: {
0289: if (insertmix == true) {
0290: if (previous == -1) {
0291: w.setRGB(left + x, top + height, mix);
0292: } else {
0293: w.setRGB(left + x, top + height, w.getRGB(
0294: left + x, top + prevY)
0295: ^ mix);
0296: }
0297:
0298: insertmix = false;
0299: count--;
0300: x++;
0301: }
0302:
0303: if (previous == -1) {
0304: while (((count & ~0x7) != 0)
0305: && ((x + 8) < width)) {
0306: for (int i = 0; i < 8; i++) {
0307: w.setRGB(left + x, top + height, 0);
0308: count--;
0309: x++;
0310: }
0311: }
0312:
0313: while ((count > 0) && (x < width)) {
0314: w.setRGB(left + x, top + height, 0);
0315: count--;
0316: x++;
0317: }
0318: } else {
0319: while (((count & ~0x7) != 0)
0320: && ((x + 8) < width)) {
0321: for (int i = 0; i < 8; i++) {
0322: w.setRGB(left + x, top + height, w
0323: .getRGB(left + x, top + prevY));
0324: count--;
0325: x++;
0326: }
0327: }
0328:
0329: while ((count > 0) && (x < width)) {
0330: w.setRGB(left + x, top + height, w.getRGB(
0331: left + x, top + prevY));
0332: count--;
0333: x++;
0334: }
0335: }
0336: break;
0337: }
0338: case 1: /* Mix */
0339: {
0340: if (previous == -1) {
0341: while (((count & ~0x7) != 0)
0342: && ((x + 8) < width)) {
0343: for (int i = 0; i < 8; i++) {
0344: w.setRGB(left + x, top + height, mix);
0345: count--;
0346: x++;
0347: }
0348: }
0349:
0350: while ((count > 0) && (x < width)) {
0351: w.setRGB(left + x, top + height, mix);
0352: count--;
0353: x++;
0354: }
0355: } else {
0356: while (((count & ~0x7) != 0)
0357: && ((x + 8) < width)) {
0358: for (int i = 0; i < 8; i++) {
0359: w.setRGB(left + x, top + height, w
0360: .getRGB(left + x, top + prevY)
0361: ^ mix);
0362: count--;
0363: x++;
0364: }
0365: }
0366:
0367: while ((count > 0) && (x < width)) {
0368: w.setRGB(left + x, top + height, w.getRGB(
0369: left + x, top + prevY)
0370: ^ mix);
0371: count--;
0372: x++;
0373: }
0374: }
0375: break;
0376: }
0377: case 2: /* Fill or Mix */
0378: {
0379: if (previous == -1) {
0380: while (((count & ~0x7) != 0)
0381: && ((x + 8) < width)) {
0382: for (int i = 0; i < 8; i++) {
0383: mixmask <<= 1;
0384: if (mixmask == 0) {
0385: mask = (fom_mask != 0) ? (byte) fom_mask
0386: : compressed_pixel[input++];
0387: mixmask = 1;
0388: }
0389:
0390: if ((mask & mixmask) != 0) {
0391: w.setRGB(left + x, top + height,
0392: (byte) mix);
0393: } else {
0394: w.setRGB(left + x, top + height, 0);
0395: }
0396: count--;
0397: x++;
0398: }
0399: }
0400:
0401: while ((count > 0) && (x < width)) {
0402: mixmask <<= 1;
0403: if (mixmask == 0) {
0404: mask = (fom_mask != 0) ? (byte) fom_mask
0405: : compressed_pixel[input++];
0406: mixmask = 1;
0407: }
0408:
0409: if ((mask & mixmask) != 0) {
0410: w.setRGB(left + x, top + height, mix);
0411: } else {
0412: w.setRGB(left + x, top + height, 0);
0413: }
0414: count--;
0415: x++;
0416: }
0417: } else {
0418: while (((count & ~0x7) != 0)
0419: && ((x + 8) < width)) {
0420: for (int i = 0; i < 8; i++) {
0421: mixmask <<= 1;
0422: if (mixmask == 0) {
0423: mask = (fom_mask != 0) ? (byte) fom_mask
0424: : compressed_pixel[input++];
0425: mixmask = 1;
0426: }
0427:
0428: if ((mask & mixmask) != 0) {
0429: w.setRGB(left + x, top + height, w
0430: .getRGB(left + x, prevY
0431: + top)
0432: ^ mix);
0433: } else {
0434: w.setRGB(left + x, top + height, w
0435: .getRGB(left + x, prevY
0436: + top));
0437: }
0438: count--;
0439: x++;
0440: }
0441: }
0442: while ((count > 0) && (x < width)) {
0443: mixmask <<= 1;
0444: if (mixmask == 0) {
0445: mask = (fom_mask != 0) ? (byte) fom_mask
0446: : compressed_pixel[input++];
0447: mixmask = 1;
0448: }
0449:
0450: if ((mask & mixmask) != 0) {
0451: w.setRGB(left + x, top + height, w
0452: .getRGB(left + x, prevY + top)
0453: ^ mix);
0454: } else {
0455: w.setRGB(left + x, top + height, w
0456: .getRGB(left + x, prevY + top));
0457: }
0458: count--;
0459: x++;
0460: }
0461: }
0462: break;
0463: }
0464: case 3: /* Color */
0465: {
0466: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
0467: for (int i = 0; i < 8; i++) {
0468: w.setRGB(left + x, top + height, color2);
0469: count--;
0470: x++;
0471: }
0472: }
0473:
0474: while ((count > 0) && (x < width)) {
0475: w.setRGB(left + x, top + height, color2);
0476: count--;
0477: x++;
0478: }
0479:
0480: break;
0481: }
0482: case 4: /* Copy */
0483: {
0484: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
0485: for (int i = 0; i < 8; i++) {
0486: w.setRGB(left + x, top + height, cvalx(
0487: compressed_pixel, input, Bpp));
0488: input += Bpp;
0489: count--;
0490: x++;
0491: }
0492: }
0493:
0494: while ((count > 0) && (x < width)) {
0495: w.setRGB(left + x, top + height, cvalx(
0496: compressed_pixel, input, Bpp));
0497: input += Bpp;
0498: count--;
0499: x++;
0500: }
0501: break;
0502: }
0503: case 8: /* Bicolor */
0504: {
0505: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
0506: for (int i = 0; i < 8; i++) {
0507: if (bicolor) {
0508: w
0509: .setRGB(left + x, top + height,
0510: color2);
0511: bicolor = false;
0512: } else {
0513: w
0514: .setRGB(left + x, top + height,
0515: color1);
0516: bicolor = true;
0517: count++;
0518: }
0519: count--;
0520: x++;
0521: }
0522: }
0523:
0524: while ((count > 0) && (x < width)) {
0525: if (bicolor) {
0526: w.setRGB(left + x, top + height, color2);
0527: bicolor = false;
0528: } else {
0529: w.setRGB(left + x, top + height, color1);
0530: bicolor = true;
0531: count++;
0532: }
0533: count--;
0534: x++;
0535: }
0536:
0537: break;
0538: }
0539: case 0xd: /* White */
0540: {
0541: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
0542: for (int i = 0; i < 8; i++) {
0543: w.setRGB(left + x, top + height, 0xffffff);
0544: count--;
0545: x++;
0546: }
0547: }
0548:
0549: while ((count > 0) && (x < width)) {
0550: w.setRGB(left + x, top + height, 0xffffff);
0551: count--;
0552: x++;
0553: }
0554:
0555: break;
0556: }
0557: case 0xe: /* Black */
0558: {
0559: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
0560: for (int i = 0; i < 8; i++) {
0561: w.setRGB(left + x, top + height, 0x00);
0562: count--;
0563: x++;
0564: }
0565: }
0566:
0567: while ((count > 0) && (x < width)) {
0568: w.setRGB(left + x, top + height, 0x00);
0569: count--;
0570: x++;
0571: }
0572:
0573: break;
0574: }
0575: default: {
0576: throw new RdpDesktopException(
0577: "Unimplemented decompress opcode " + opcode);
0578: }
0579: }
0580: }
0581: }
0582:
0583: return w;
0584: }
0585:
0586: public static Image decompressImg(int width, int height, int size,
0587: RdpPacket data, int Bpp, IndexColorModel cm)
0588: throws RdpDesktopException {
0589: RdpImage w = null;
0590:
0591: byte[] compressed_pixel = new byte[size];
0592: data.copyToByteArray(compressed_pixel, 0, data.getPosition(),
0593: size);
0594: data.incrementPosition(size);
0595:
0596: int previous = -1, line = 0, prevY = 0;
0597: int input = 0, end = size;
0598: int opcode = 0, count = 0, offset = 0, x = width;
0599: int lastopcode = -1, fom_mask = 0;
0600: int code = 0, color1 = 0, color2 = 0;
0601: byte mixmask = 0;
0602: int mask = 0;
0603: int mix = 0xffffffff;
0604:
0605: boolean insertmix = false, bicolor = false, isfillormix = false;
0606:
0607: if (cm == null) {
0608: w = new RdpImage(width, height, BufferedImage.TYPE_INT_RGB);
0609: } else {
0610: w = new RdpImage(width, height, BufferedImage.TYPE_INT_RGB,
0611: cm);
0612: }
0613:
0614: while (input < end) {
0615: fom_mask = 0;
0616: code = (compressed_pixel[input++] & 0x000000ff);
0617: opcode = code >> 4;
0618:
0619: /* Handle different opcode forms */
0620: switch (opcode) {
0621: case 0xc:
0622: case 0xd:
0623: case 0xe: {
0624: opcode -= 6;
0625: count = code & 0xf;
0626: offset = 16;
0627: break;
0628:
0629: }
0630: case 0xf: {
0631: opcode = code & 0xf;
0632: if (opcode < 9) {
0633: count = (compressed_pixel[input++] & 0xff);
0634: count |= ((compressed_pixel[input++] & 0xff) << 8);
0635: } else {
0636: count = (opcode < 0xb) ? 8 : 1;
0637: }
0638: offset = 0;
0639: break;
0640: }
0641: default: {
0642: opcode >>= 1;
0643: count = code & 0x1f;
0644: offset = 32;
0645: break;
0646: }
0647: }
0648:
0649: /* Handle strange cases for counts */
0650: if (offset != 0) {
0651: isfillormix = ((opcode == 2) || (opcode == 7));
0652:
0653: if (count == 0) {
0654: if (isfillormix) {
0655: count = (compressed_pixel[input++] & 0x000000ff) + 1;
0656: } else {
0657: count = (compressed_pixel[input++] & 0x000000ff)
0658: + offset;
0659: }
0660: } else if (isfillormix == true) {
0661: count <<= 3;
0662: }
0663: }
0664:
0665: switch (opcode) {
0666: case 0: /* Fill */
0667: {
0668: if ((lastopcode == opcode)
0669: && !((x == width) && (previous == -1))) {
0670: insertmix = true;
0671: }
0672: break;
0673: }
0674: case 8: /* Bicolor */
0675: {
0676: color1 = cvalx(compressed_pixel, input, Bpp);
0677: input += Bpp;
0678: }
0679: case 3: /* Color */
0680: {
0681: color2 = cvalx(compressed_pixel, input, Bpp);
0682: input += Bpp;
0683: break;
0684: }
0685: case 6: /* SetMix/Mix */
0686: case 7: /* SetMix/FillOrMix */
0687: {
0688: mix = cvalx(compressed_pixel, input, Bpp);
0689: input += Bpp;
0690: opcode -= 5;
0691: break;
0692: }
0693: case 9: /* FillOrMix_1 */
0694: {
0695: mask = 0x03;
0696: opcode = 0x02;
0697: fom_mask = 3;
0698: break;
0699: }
0700: case 0x0a: /* FillOrMix_2 */
0701: {
0702: mask = 0x05;
0703: opcode = 0x02;
0704: fom_mask = 5;
0705: break;
0706: }
0707: }
0708:
0709: lastopcode = opcode;
0710: mixmask = 0;
0711:
0712: /* Output body */
0713: while (count > 0) {
0714: if (x >= width) {
0715: if (height <= 0) {
0716: throw new RdpDesktopException(
0717: "Decompressing bitmap failed! Height = "
0718: + height);
0719: }
0720:
0721: x = 0;
0722: height--;
0723:
0724: previous = line;
0725: prevY = previous / width;
0726: line = height * width;
0727: }
0728:
0729: switch (opcode) {
0730: case 0: /* Fill */
0731: {
0732: if (insertmix) {
0733: if (previous == -1) {
0734: w.setRGB(x, height, mix);
0735: } else {
0736: w.setRGB(x, height, w.getRGB(x, prevY)
0737: ^ mix);
0738: }
0739:
0740: insertmix = false;
0741: count--;
0742: x++;
0743: }
0744:
0745: if (previous == -1) {
0746: while (((count & ~0x7) != 0)
0747: && ((x + 8) < width)) {
0748: for (int i = 0; i < 8; i++) {
0749: w.setRGB(x, height, 0);
0750: count--;
0751: x++;
0752: }
0753: }
0754:
0755: while ((count > 0) && (x < width)) {
0756: w.setRGB(x, height, 0);
0757: count--;
0758: x++;
0759: }
0760: } else {
0761: while (((count & ~0x7) != 0)
0762: && ((x + 8) < width)) {
0763: for (int i = 0; i < 8; i++) {
0764: w.setRGB(x, height, w.getRGB(x, prevY));
0765: count--;
0766: x++;
0767: }
0768: }
0769:
0770: while ((count > 0) && (x < width)) {
0771: w.setRGB(x, height, w.getRGB(x, prevY));
0772: count--;
0773: x++;
0774: }
0775: }
0776: break;
0777: }
0778: case 1: /* Mix */
0779: {
0780: if (previous == -1) {
0781: while (((count & ~0x7) != 0)
0782: && ((x + 8) < width)) {
0783: for (int i = 0; i < 8; i++) {
0784: w.setRGB(x, height, mix);
0785: count--;
0786: x++;
0787: }
0788: }
0789:
0790: while ((count > 0) && (x < width)) {
0791: w.setRGB(x, height, mix);
0792: count--;
0793: x++;
0794: }
0795: } else {
0796: while (((count & ~0x7) != 0)
0797: && ((x + 8) < width)) {
0798: for (int i = 0; i < 8; i++) {
0799: w.setRGB(x, height, w.getRGB(x, prevY)
0800: ^ mix);
0801: count--;
0802: x++;
0803: }
0804: }
0805:
0806: while ((count > 0) && (x < width)) {
0807: w.setRGB(x, height, w.getRGB(x, prevY)
0808: ^ mix);
0809: count--;
0810: x++;
0811: }
0812:
0813: }
0814: break;
0815: }
0816: case 2: /* Fill or Mix */
0817: {
0818: if (previous == -1) {
0819: while (((count & ~0x7) != 0)
0820: && ((x + 8) < width)) {
0821: for (int i = 0; i < 8; i++) {
0822: mixmask <<= 1;
0823: if (mixmask == 0) {
0824: mask = (fom_mask != 0) ? (byte) fom_mask
0825: : compressed_pixel[input++];
0826: mixmask = 1;
0827: }
0828: if ((mask & mixmask) != 0) {
0829: w.setRGB(x, height, (byte) mix);
0830: } else {
0831: w.setRGB(x, height, 0);
0832: }
0833: count--;
0834: x++;
0835: }
0836: }
0837: while ((count > 0) && (x < width)) {
0838: mixmask <<= 1;
0839: if (mixmask == 0) {
0840: mask = (fom_mask != 0) ? (byte) fom_mask
0841: : compressed_pixel[input++];
0842: mixmask = 1;
0843: }
0844: if ((mask & mixmask) != 0) {
0845: w.setRGB(x, height, mix);
0846: } else {
0847: w.setRGB(x, height, 0);
0848: }
0849: count--;
0850: x++;
0851: }
0852: } else {
0853: while (((count & ~0x7) != 0)
0854: && ((x + 8) < width)) {
0855: for (int i = 0; i < 8; i++) {
0856: mixmask <<= 1;
0857: if (mixmask == 0) {
0858: mask = (fom_mask != 0) ? (byte) fom_mask
0859: : compressed_pixel[input++];
0860: mixmask = 1;
0861: }
0862:
0863: if ((mask & mixmask) != 0) {
0864: w.setRGB(x, height, w.getRGB(x,
0865: prevY)
0866: ^ mix);
0867: } else {
0868: w.setRGB(x, height, w.getRGB(x,
0869: prevY));
0870: }
0871: count--;
0872: x++;
0873: }
0874: }
0875:
0876: while ((count > 0) && (x < width)) {
0877: mixmask <<= 1;
0878: if (mixmask == 0) {
0879: mask = (fom_mask != 0) ? (byte) fom_mask
0880: : compressed_pixel[input++];
0881: mixmask = 1;
0882: }
0883:
0884: if ((mask & mixmask) != 0) {
0885: w.setRGB(x, height, w.getRGB(x, prevY)
0886: ^ mix);
0887: } else {
0888: w.setRGB(x, height, w.getRGB(x, prevY));
0889: }
0890: count--;
0891: x++;
0892: }
0893:
0894: }
0895: break;
0896: }
0897: case 3: /* Color */
0898: {
0899: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
0900: for (int i = 0; i < 8; i++) {
0901: w.setRGB(x, height, color2);
0902: count--;
0903: x++;
0904: }
0905: }
0906:
0907: while ((count > 0) && (x < width)) {
0908: w.setRGB(x, height, color2);
0909: count--;
0910: x++;
0911: }
0912:
0913: break;
0914: }
0915: case 4: /* Copy */
0916: {
0917: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
0918: for (int i = 0; i < 8; i++) {
0919: w.setRGB(x, height, cvalx(compressed_pixel,
0920: input, Bpp));
0921: input += Bpp;
0922: count--;
0923: x++;
0924: }
0925: }
0926:
0927: while ((count > 0) && (x < width)) {
0928: w.setRGB(x, height, cvalx(compressed_pixel,
0929: input, Bpp));
0930: input += Bpp;
0931: count--;
0932: x++;
0933: }
0934: break;
0935: }
0936: case 8: /* Bicolor */
0937: {
0938: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
0939: for (int i = 0; i < 8; i++) {
0940: if (bicolor == true) {
0941: w.setRGB(x, height, color2);
0942: bicolor = false;
0943: } else {
0944: w.setRGB(x, height, color1);
0945: bicolor = true;
0946: count++;
0947: }
0948: count--;
0949: x++;
0950: }
0951: }
0952:
0953: while ((count > 0) && (x < width)) {
0954: if (bicolor) {
0955: w.setRGB(x, height, color2);
0956: bicolor = false;
0957: } else {
0958: w.setRGB(x, height, color1);
0959: bicolor = true;
0960: count++;
0961: }
0962: count--;
0963: x++;
0964: }
0965:
0966: break;
0967: }
0968: case 0xd: /* White */
0969: {
0970: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
0971: for (int i = 0; i < 8; i++) {
0972: w.setRGB(x, height, 0xffffff);
0973: count--;
0974: x++;
0975: }
0976: }
0977:
0978: while ((count > 0) && (x < width)) {
0979: w.setRGB(x, height, 0xffffff);
0980: count--;
0981: x++;
0982: }
0983:
0984: break;
0985: }
0986: case 0xe: /* Black */
0987: {
0988: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
0989: for (int i = 0; i < 8; i++) {
0990: w.setRGB(x, height, 0x00);
0991: count--;
0992: x++;
0993: }
0994: }
0995:
0996: while ((count > 0) && (x < width)) {
0997: w.setRGB(x, height, 0x00);
0998: count--;
0999: x++;
1000: }
1001:
1002: break;
1003: }
1004: default: {
1005: throw new RdpDesktopException(
1006: "Unimplemented decompress opcode " + opcode);
1007: }
1008: }
1009: }
1010: }
1011:
1012: return w.getBufferedImage();
1013: }
1014:
1015: public static int[] decompressInt(int width, int height, int size,
1016: RdpPacket data, int Bpp) throws RdpDesktopException {
1017: byte[] compressed_pixel = new byte[size];
1018: data.copyToByteArray(compressed_pixel, 0, data.getPosition(),
1019: size);
1020: data.incrementPosition(size);
1021:
1022: int previous = -1, line = 0;
1023: int input = 0, output = 0, end = size;
1024: int opcode = 0, count = 0, offset = 0, x = width;
1025: int lastopcode = -1, fom_mask = 0;
1026: int code = 0, color1 = 0, color2 = 0;
1027: byte mixmask = 0;
1028: int mask = 0;
1029: int mix = 0xffffffff;
1030:
1031: boolean insertmix = false, bicolor = false, isfillormix = false;
1032:
1033: int[] pixel = new int[width * height];
1034: while (input < end) {
1035: fom_mask = 0;
1036: code = (compressed_pixel[input++] & 0x000000ff);
1037: opcode = code >> 4;
1038:
1039: /* Handle different opcode forms */
1040: switch (opcode) {
1041: case 0xc:
1042: case 0xd:
1043: case 0xe: {
1044: opcode -= 6;
1045: count = code & 0xf;
1046: offset = 16;
1047: break;
1048: }
1049: case 0xf: {
1050: opcode = code & 0xf;
1051: if (opcode < 9) {
1052: count = (compressed_pixel[input++] & 0xff);
1053: count |= ((compressed_pixel[input++] & 0xff) << 8);
1054: } else {
1055: count = (opcode < 0xb) ? 8 : 1;
1056: }
1057: offset = 0;
1058: break;
1059: }
1060: default: {
1061: opcode >>= 1;
1062: count = code & 0x1f;
1063: offset = 32;
1064: break;
1065: }
1066: }
1067:
1068: /* Handle strange cases for counts */
1069: if (offset != 0) {
1070: isfillormix = ((opcode == 2) || (opcode == 7));
1071:
1072: if (count == 0) {
1073: if (isfillormix == true) {
1074: count = (compressed_pixel[input++] & 0x000000ff) + 1;
1075: } else {
1076: count = (compressed_pixel[input++] & 0x000000ff)
1077: + offset;
1078: }
1079: } else if (isfillormix == true) {
1080: count <<= 3;
1081: }
1082: }
1083:
1084: switch (opcode) {
1085: case 0: /* Fill */
1086: {
1087: if ((lastopcode == opcode)
1088: && !((x == width) && (previous == -1))) {
1089: insertmix = true;
1090: }
1091: break;
1092: }
1093: case 8: /* Bicolor */
1094: {
1095: color1 = cvalx(compressed_pixel, input, Bpp);
1096: input += Bpp;
1097: }
1098: case 3: /* Color */
1099: {
1100: color2 = cvalx(compressed_pixel, input, Bpp);
1101: input += Bpp;
1102: break;
1103: }
1104: case 6: /* SetMix/Mix */
1105: case 7: /* SetMix/FillOrMix */
1106: {
1107: mix = cvalx(compressed_pixel, input, Bpp);
1108: input += Bpp;
1109: opcode -= 5;
1110: break;
1111: }
1112: case 9: /* FillOrMix_1 */
1113: {
1114: mask = 0x03;
1115: opcode = 0x02;
1116: fom_mask = 3;
1117: break;
1118: }
1119: case 0x0a: /* FillOrMix_2 */
1120: {
1121: mask = 0x05;
1122: opcode = 0x02;
1123: fom_mask = 5;
1124: break;
1125: }
1126: default: {
1127: break;
1128: }
1129: }
1130:
1131: lastopcode = opcode;
1132: mixmask = 0;
1133:
1134: /* Output body */
1135: while (count > 0) {
1136: if (x >= width) {
1137: if (height <= 0) {
1138: throw new RdpDesktopException(
1139: "Decompressing bitmap failed! Height = "
1140: + height);
1141: }
1142:
1143: x = 0;
1144: height--;
1145:
1146: previous = line;
1147: line = output + height * width;
1148: }
1149:
1150: switch (opcode) {
1151: case 0: /* Fill */
1152: {
1153: if (insertmix == true) {
1154: if (previous == -1) {
1155: pixel[line + x] = mix;
1156: } else {
1157: pixel[line + x] = (pixel[previous + x] ^ mix);
1158: }
1159:
1160: insertmix = false;
1161: count--;
1162: x++;
1163: }
1164:
1165: if (previous == -1) {
1166: while (((count & ~0x7) != 0)
1167: && ((x + 8) < width)) {
1168: for (int i = 0; i < 8; i++) {
1169: pixel[line + x] = 0;
1170: count--;
1171: x++;
1172: }
1173: }
1174:
1175: while ((count > 0) && (x < width)) {
1176: pixel[line + x] = 0;
1177: count--;
1178: x++;
1179: }
1180: } else {
1181: while (((count & ~0x7) != 0)
1182: && ((x + 8) < width)) {
1183: for (int i = 0; i < 8; i++) {
1184: pixel[line + x] = pixel[previous + x];
1185: count--;
1186: x++;
1187: }
1188: }
1189:
1190: while ((count > 0) && (x < width)) {
1191: pixel[line + x] = pixel[previous + x];
1192: count--;
1193: x++;
1194: }
1195: }
1196:
1197: break;
1198: }
1199: case 1: /* Mix */
1200: {
1201: if (previous == -1) {
1202: while (((count & ~0x7) != 0)
1203: && ((x + 8) < width)) {
1204: for (int i = 0; i < 8; i++) {
1205: pixel[line + x] = mix;
1206: count--;
1207: x++;
1208: }
1209: }
1210:
1211: while ((count > 0) && (x < width)) {
1212: pixel[line + x] = mix;
1213: count--;
1214: x++;
1215: }
1216: } else {
1217: while (((count & ~0x7) != 0)
1218: && ((x + 8) < width)) {
1219: for (int i = 0; i < 8; i++) {
1220: pixel[line + x] = pixel[previous + x]
1221: ^ mix;
1222: count--;
1223: x++;
1224: }
1225: }
1226:
1227: while ((count > 0) && (x < width)) {
1228: pixel[line + x] = pixel[previous + x] ^ mix;
1229: count--;
1230: x++;
1231: }
1232: }
1233:
1234: break;
1235: }
1236: case 2: /* Fill or Mix */
1237: {
1238: if (previous == -1) {
1239: while (((count & ~0x7) != 0)
1240: && ((x + 8) < width)) {
1241: for (int i = 0; i < 8; i++) {
1242: mixmask <<= 1;
1243: if (mixmask == 0) {
1244: mask = (fom_mask != 0) ? (byte) fom_mask
1245: : compressed_pixel[input++];
1246: mixmask = 1;
1247: }
1248:
1249: if ((mask & mixmask) != 0) {
1250: pixel[line + x] = (byte) mix;
1251: } else {
1252: pixel[line + x] = 0;
1253: }
1254:
1255: count--;
1256: x++;
1257: }
1258: }
1259:
1260: while ((count > 0) && (x < width)) {
1261: mixmask <<= 1;
1262: if (mixmask == 0) {
1263: mask = (fom_mask != 0) ? (byte) fom_mask
1264: : compressed_pixel[input++];
1265: mixmask = 1;
1266: }
1267:
1268: if ((mask & mixmask) != 0) {
1269: pixel[line + x] = mix;
1270: } else {
1271: pixel[line + x] = 0;
1272: }
1273:
1274: count--;
1275: x++;
1276: }
1277: } else {
1278: while (((count & ~0x7) != 0)
1279: && ((x + 8) < width)) {
1280: for (int i = 0; i < 8; i++) {
1281: mixmask <<= 1;
1282: if (mixmask == 0) {
1283: mask = (fom_mask != 0) ? (byte) fom_mask
1284: : compressed_pixel[input++];
1285: mixmask = 1;
1286: }
1287:
1288: if ((mask & mixmask) != 0) {
1289: pixel[line + x] = (pixel[previous
1290: + x] ^ mix);
1291: } else {
1292: pixel[line + x] = pixel[previous
1293: + x];
1294: }
1295:
1296: count--;
1297: x++;
1298: }
1299: }
1300:
1301: while ((count > 0) && (x < width)) {
1302: mixmask <<= 1;
1303: if (mixmask == 0) {
1304: mask = (fom_mask != 0) ? (byte) fom_mask
1305: : compressed_pixel[input++];
1306: mixmask = 1;
1307: }
1308:
1309: if ((mask & mixmask) != 0) {
1310: pixel[line + x] = (pixel[previous + x] ^ mix);
1311: } else {
1312: pixel[line + x] = pixel[previous + x];
1313: }
1314:
1315: count--;
1316: x++;
1317: }
1318: }
1319:
1320: break;
1321: }
1322: case 3: /* Color */
1323: {
1324: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
1325: for (int i = 0; i < 8; i++) {
1326: pixel[line + x] = color2;
1327: count--;
1328: x++;
1329: }
1330: }
1331:
1332: while ((count > 0) && (x < width)) {
1333: pixel[line + x] = color2;
1334: count--;
1335: x++;
1336: }
1337:
1338: break;
1339: }
1340: case 4: /* Copy */
1341: {
1342: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
1343: for (int i = 0; i < 8; i++) {
1344: pixel[line + x] = cvalx(compressed_pixel,
1345: input, Bpp);
1346: input += Bpp;
1347: count--;
1348: x++;
1349: }
1350: }
1351:
1352: while ((count > 0) && (x < width)) {
1353: pixel[line + x] = cvalx(compressed_pixel,
1354: input, Bpp);
1355: input += Bpp;
1356: count--;
1357: x++;
1358: }
1359:
1360: break;
1361: }
1362: case 8: /* Bicolor */
1363: {
1364: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
1365: for (int i = 0; i < 8; i++) {
1366: if (bicolor == true) {
1367: pixel[line + x] = color2;
1368: bicolor = false;
1369: } else {
1370: pixel[line + x] = color1;
1371: bicolor = true;
1372: count++;
1373: }
1374: count--;
1375: x++;
1376: }
1377: }
1378:
1379: while ((count > 0) && (x < width)) {
1380: if (bicolor == true) {
1381: pixel[line + x] = color2;
1382: bicolor = false;
1383: } else {
1384: pixel[line + x] = color1;
1385: bicolor = true;
1386: count++;
1387: }
1388: count--;
1389: x++;
1390: }
1391:
1392: break;
1393: }
1394: case 0xd: /* White */
1395: {
1396: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
1397: for (int i = 0; i < 8; i++) {
1398: pixel[line + x] = 0xffffff;
1399: count--;
1400: x++;
1401: }
1402: }
1403:
1404: while ((count > 0) && (x < width)) {
1405: pixel[line + x] = 0xffffff;
1406: count--;
1407: x++;
1408: }
1409:
1410: break;
1411: }
1412: case 0xe: /* Black */
1413: {
1414: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
1415: for (int i = 0; i < 8; i++) {
1416: pixel[line + x] = 0x00;
1417: count--;
1418: x++;
1419: }
1420: }
1421:
1422: while ((count > 0) && (x < width)) {
1423: pixel[line + x] = 0x00;
1424: count--;
1425: x++;
1426: }
1427:
1428: break;
1429: }
1430: default: {
1431: throw new RdpDesktopException(
1432: "Unimplemented decompress opcode " + opcode);
1433: }
1434: }
1435: }
1436: }
1437:
1438: return pixel;
1439: }
1440:
1441: public static byte[] decompress(int width, int height, int size,
1442: RdpPacket data, int Bpp) throws RdpDesktopException {
1443: byte[] compressed_pixel = new byte[size];
1444: data.copyToByteArray(compressed_pixel, 0, data.getPosition(),
1445: size);
1446: data.incrementPosition(size);
1447:
1448: int previous = 0, line = 0;
1449: int input = 0, output = 0, end = size;
1450: int opcode = 0, count = 0, offset = 0, x = width;
1451: int lastopcode = -1, fom_mask = 0;
1452: int code = 0, color1 = 0, color2 = 0;
1453: byte mixmask = 0;
1454: int mask = 0;
1455: int mix = 0xffffffff;
1456:
1457: boolean insertmix = false, bicolor = false, isfillormix = false;
1458:
1459: byte[] pixel = new byte[width * height];
1460: while (input < end) {
1461: fom_mask = 0;
1462: code = (compressed_pixel[input++] & 0x000000ff);
1463: opcode = code >> 4;
1464:
1465: /* Handle different opcode forms */
1466: switch (opcode) {
1467: case 0xc:
1468: case 0xd:
1469: case 0xe: {
1470: opcode -= 6;
1471: count = code & 0xf;
1472: offset = 16;
1473: break;
1474: }
1475: case 0xf: {
1476: opcode = code & 0xf;
1477: if (opcode < 9) {
1478: count = (compressed_pixel[input++] & 0xff);
1479: count |= ((compressed_pixel[input++] & 0xff) << 8);
1480: } else {
1481: count = (opcode < 0xb) ? 8 : 1;
1482: }
1483: offset = 0;
1484: break;
1485: }
1486: default: {
1487: opcode >>= 1;
1488: count = code & 0x1f;
1489: offset = 32;
1490: break;
1491: }
1492: }
1493:
1494: /* Handle strange cases for counts */
1495: if (offset != 0) {
1496: isfillormix = ((opcode == 2) || (opcode == 7));
1497:
1498: if (count == 0) {
1499: if (isfillormix == true) {
1500: count = (compressed_pixel[input++] & 0x000000ff) + 1;
1501: } else {
1502: count = (compressed_pixel[input++] & 0x000000ff)
1503: + offset;
1504: }
1505: } else if (isfillormix == true) {
1506: count <<= 3;
1507: }
1508: }
1509:
1510: switch (opcode) {
1511: case 0: /* Fill */
1512: {
1513: if ((lastopcode == opcode)
1514: && !((x == width) && (previous == 0))) {
1515: insertmix = true;
1516: }
1517: break;
1518: }
1519: case 8: /* Bicolor */
1520: {
1521: color1 = (compressed_pixel[input++] & 0x000000ff);
1522: }
1523: case 3: /* Color */
1524: {
1525: color2 = (compressed_pixel[input++] & 0x000000ff);
1526: break;
1527: }
1528: case 6: /* SetMix/Mix */
1529: case 7: /* SetMix/FillOrMix */
1530: {
1531: mix = compressed_pixel[input++];
1532: opcode -= 5;
1533: break;
1534: }
1535: case 9: /* FillOrMix_1 */
1536: {
1537: mask = 0x03;
1538: opcode = 0x02;
1539: fom_mask = 3;
1540: break;
1541: }
1542: case 0x0a: /* FillOrMix_2 */
1543: {
1544: mask = 0x05;
1545: opcode = 0x02;
1546: fom_mask = 5;
1547: break;
1548: }
1549: default: {
1550: break;
1551: }
1552: }
1553:
1554: lastopcode = opcode;
1555: mixmask = 0;
1556:
1557: /* Output body */
1558: while (count > 0) {
1559: if (x >= width) {
1560: if (height <= 0) {
1561: throw new RdpDesktopException(
1562: "Decompressing bitmap failed! Height = "
1563: + height);
1564: }
1565:
1566: x = 0;
1567: height--;
1568:
1569: previous = line;
1570: line = output + height * width;
1571: }
1572:
1573: switch (opcode) {
1574: case 0: /* Fill */
1575: {
1576: if (insertmix == true) {
1577: if (previous == 0) {
1578: pixel[line + x] = (byte) mix;
1579: } else {
1580: pixel[line + x] = (byte) (pixel[previous
1581: + x] ^ (byte) mix);
1582: }
1583:
1584: insertmix = false;
1585: count--;
1586: x++;
1587: }
1588:
1589: if (previous == 0) {
1590: while (((count & ~0x7) != 0)
1591: && ((x + 8) < width)) {
1592: for (int i = 0; i < 8; i++) {
1593: pixel[line + x] = 0;
1594: count--;
1595: x++;
1596: }
1597: }
1598:
1599: while ((count > 0) && (x < width)) {
1600: pixel[line + x] = 0;
1601: count--;
1602: x++;
1603: }
1604: } else {
1605: while (((count & ~0x7) != 0)
1606: && ((x + 8) < width)) {
1607: for (int i = 0; i < 8; i++) {
1608: pixel[line + x] = pixel[previous + x];
1609: count--;
1610: x++;
1611: }
1612: }
1613:
1614: while ((count > 0) && (x < width)) {
1615: pixel[line + x] = pixel[previous + x];
1616: count--;
1617: x++;
1618: }
1619: }
1620:
1621: break;
1622: }
1623: case 1: /* Mix */
1624: {
1625: if (previous == 0) {
1626: while (((count & ~0x7) != 0)
1627: && ((x + 8) < width)) {
1628: for (int i = 0; i < 8; i++) {
1629: pixel[line + x] = (byte) mix;
1630: count--;
1631: x++;
1632: }
1633: }
1634:
1635: while ((count > 0) && (x < width)) {
1636: pixel[line + x] = (byte) mix;
1637: count--;
1638: x++;
1639: }
1640: } else {
1641: while (((count & ~0x7) != 0)
1642: && ((x + 8) < width)) {
1643: for (int i = 0; i < 8; i++) {
1644: setli(pixel, line, x, getli(pixel,
1645: previous, x, 1)
1646: ^ mix, 1);
1647: count--;
1648: x++;
1649: }
1650: }
1651:
1652: while ((count > 0) && (x < width)) {
1653: setli(pixel, line, x, getli(pixel,
1654: previous, x, 1)
1655: ^ mix, 1);
1656: count--;
1657: x++;
1658: }
1659: }
1660:
1661: break;
1662: }
1663: case 2: /* Fill or Mix */
1664: {
1665: if (previous == 0) {
1666: while (((count & ~0x7) != 0)
1667: && ((x + 8) < width)) {
1668: for (int i = 0; i < 8; i++) {
1669: mixmask <<= 1;
1670: if (mixmask == 0) {
1671: mask = (fom_mask != 0) ? (byte) fom_mask
1672: : compressed_pixel[input++];
1673: mixmask = 1;
1674: }
1675:
1676: if ((mask & mixmask) != 0) {
1677: pixel[line + x] = (byte) mix;
1678: } else {
1679: pixel[line + x] = 0;
1680: }
1681:
1682: count--;
1683: x++;
1684: }
1685: }
1686:
1687: while ((count > 0) && (x < width)) {
1688: mixmask <<= 1;
1689: if (mixmask == 0) {
1690: mask = (fom_mask != 0) ? (byte) fom_mask
1691: : compressed_pixel[input++];
1692: mixmask = 1;
1693: }
1694:
1695: if ((mask & mixmask) != 0) {
1696: pixel[line + x] = (byte) mix;
1697: } else {
1698: pixel[line + x] = 0;
1699: }
1700:
1701: count--;
1702: x++;
1703: }
1704: } else {
1705: while (((count & ~0x7) != 0)
1706: && ((x + 8) < width)) {
1707: for (int i = 0; i < 8; i++) {
1708: mixmask <<= 1;
1709: if (mixmask == 0) {
1710: mask = (fom_mask != 0) ? (byte) fom_mask
1711: : compressed_pixel[input++];
1712: mixmask = 1;
1713: }
1714:
1715: if ((mask & mixmask) != 0) {
1716: pixel[line + x] = (byte) (pixel[previous
1717: + x] ^ (byte) mix);
1718: } else {
1719: pixel[line + x] = pixel[previous
1720: + x];
1721: }
1722:
1723: count--;
1724: x++;
1725: }
1726: }
1727:
1728: while ((count > 0) && (x < width)) {
1729: mixmask <<= 1;
1730: if (mixmask == 0) {
1731: mask = (fom_mask != 0) ? (byte) fom_mask
1732: : compressed_pixel[input++];
1733: mixmask = 1;
1734: }
1735:
1736: if ((mask & mixmask) != 0) {
1737: pixel[line + x] = (byte) (pixel[previous
1738: + x] ^ (byte) mix);
1739: } else {
1740: pixel[line + x] = pixel[previous + x];
1741: }
1742:
1743: count--;
1744: x++;
1745: }
1746: }
1747:
1748: break;
1749: }
1750: case 3: /* Color */
1751: {
1752: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
1753: for (int i = 0; i < 8; i++) {
1754: pixel[line + x] = (byte) color2;
1755: count--;
1756: x++;
1757: }
1758: }
1759:
1760: while ((count > 0) && (x < width)) {
1761: pixel[line + x] = (byte) color2;
1762: count--;
1763: x++;
1764: }
1765:
1766: break;
1767: }
1768: case 4: /* Copy */
1769: {
1770: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
1771: for (int i = 0; i < 8; i++) {
1772: pixel[line + x] = compressed_pixel[input++];
1773: count--;
1774: x++;
1775: }
1776: }
1777:
1778: while ((count > 0) && (x < width)) {
1779: pixel[line + x] = compressed_pixel[input++];
1780: count--;
1781: x++;
1782: }
1783:
1784: break;
1785: }
1786: case 8: /* Bicolor */
1787: {
1788: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
1789: for (int i = 0; i < 8; i++) {
1790: if (bicolor == true) {
1791: pixel[line + x] = (byte) color2;
1792: bicolor = false;
1793: } else {
1794: pixel[line + x] = (byte) color1;
1795: bicolor = true;
1796: count++;
1797: }
1798:
1799: count--;
1800: x++;
1801: }
1802: }
1803:
1804: while ((count > 0) && (x < width)) {
1805: if (bicolor == true) {
1806: pixel[line + x] = (byte) color2;
1807: bicolor = false;
1808: } else {
1809: pixel[line + x] = (byte) color1;
1810: bicolor = true;
1811: count++;
1812: }
1813:
1814: count--;
1815: x++;
1816: }
1817:
1818: break;
1819: }
1820: case 0xd: /* White */
1821: {
1822: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
1823: for (int i = 0; i < 8; i++) {
1824: pixel[line + x] = (byte) 0xff;
1825: count--;
1826: x++;
1827: }
1828: }
1829:
1830: while ((count > 0) && (x < width)) {
1831: pixel[line + x] = (byte) 0xff;
1832: count--;
1833: x++;
1834: }
1835:
1836: break;
1837: }
1838: case 0xe: /* Black */
1839: {
1840: while (((count & ~0x7) != 0) && ((x + 8) < width)) {
1841: for (int i = 0; i < 8; i++) {
1842: pixel[line + x] = (byte) 0x00;
1843: count--;
1844: x++;
1845: }
1846: }
1847:
1848: while ((count > 0) && (x < width)) {
1849: pixel[line + x] = (byte) 0x00;
1850: count--;
1851: x++;
1852: }
1853:
1854: break;
1855: }
1856: default: {
1857: throw new RdpDesktopException(
1858: "Unimplemented decompress opcode " + opcode);
1859: }
1860: }
1861: }
1862: }
1863:
1864: return pixel;
1865: }
1866:
1867: public RdpBitmap(int[] data, int width, int height, int x, int y) {
1868: m_highdata = data;
1869: m_width = width;
1870: m_height = height;
1871: m_x = x;
1872: m_y = y;
1873: }
1874:
1875: public RdpBitmap(byte[] data, int width, int height, int x, int y,
1876: int Bpp) {
1877: m_highdata = RdpBitmap.convertImage(data, Bpp);
1878: m_width = width;
1879: m_height = height;
1880: m_x = x;
1881: m_y = y;
1882: }
1883:
1884: public int[] getBitmapData() {
1885: return m_highdata;
1886: }
1887:
1888: public int getWidth() {
1889: return m_width;
1890: }
1891:
1892: public int getHeight() {
1893: return m_height;
1894: }
1895:
1896: public int getX() {
1897: return m_x;
1898: }
1899:
1900: public int getY() {
1901: return m_y;
1902: }
1903: }
|