📄 bitmap.java
字号:
/* 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 net.propero.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 Bpp Bytes-per-pixel for bitmap
* @return Integer array of pixel data representing input image data
*/
static int[] convertImage(byte[] bitmap, int Bpp) {
int[] out = new int[bitmap.length / Bpp];
for (int i = 0; i < out.length; i++) {
if (Bpp == 1)
out[i] = bitmap[i] & 0xFF;
else if (Bpp == 2)
out[i] = ((bitmap[i * Bpp + 1] & 0xFF) << 8)
| (bitmap[i * Bpp] & 0xFF);
else if (Bpp == 3)
out[i] = ((bitmap[i * Bpp + 2] & 0xFF) << 16)
| ((bitmap[i * Bpp + 1] & 0xFF) << 8)
| (bitmap[i * Bpp] & 0xFF);
out[i] = Bitmap.convertTo24(out[i]);
}
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -