JNA, Mapping and pointers references - java

I need to use DLL inside my Java application. DLL is exporting some set of functions, authors called it "Direct DLL API". I'm trying to define in java equivalent of following function declaration:
int XcCompress( HXCEEDCMP hComp, const BYTE* pcSource, DWORD dwSourceSize, BYTE** ppcCompressed, DWORD* pdwCompressedSize, BOOL bEndOfData );
Inside my interface that extends Library I declared it as follows:
int XcCompress(WString hComp, Pointer pcSource, int dwSourceSize, Pointer[] ppcCompressed, IntByReference pdwCompressedSize, boolean bEndOfData);
Problem is everytime I get an error:
Exception in thread "main" java.lang.Error: Invalid memory access
So basically I'm stuck at this point.
HXCEEDCMP hComp - is suppose to store handler to the function, and works fine as WString for init DLL / destroying DLL functions so I kept it like this.
The header reference "creature" is:
typedef HXCEEDCMP ( XCD_WINAPI *LPFNXCCREATEXCEEDCOMPRESSIONW )( const WCHAR* );
const BYTE* pcSource - is the source data for compression, inside my code I instantiate it this way:
private static Pointer setByteArrayPointer(String dataToCompress) {
Pointer pointer = new Memory(1024);
pointer.write(0, dataToCompress.getBytes(), 0,
dataToCompress.getBytes().length);
return pointer;
}
DWORD dwSourceSize - for this im getting reserved Memory size in this way:
String testData = "ABCDABCDABCDAAD";
Pointer source = setByteArrayPointer(testData);
(int) ((Memory)source).size()
BYTE** ppcCompressed - function should populate ppcCompressed reference after work is done. I assume I made a mistake there, by doing it in this way:
Pointer[] compressed = {new Pointer(1024), new Pointer(1024)};
DWORD* pdwCompressedSize - returned by function size of compressed data. I map it in this way:
IntByReference intByReference = new IntByReference();
Not sure if it is good idea aswell..
BOOL bEndOfData - i need to set it to true.
So finally my method call, which returns an error looks like this:
xceedApiDll.XcCompress(handle, source, (int) ((Memory)source).size(), compressed, intByReference, true);
Any help will be appreciated. Thank you.

I think i solved the issue (thanks for comments guys). Maybe for someone using this library it will be useful:
In the end the main problem was with handler declaration and the ppcCompressed value.
I used the following solution which works fine for me:
Method declarations inside java interface:
int XcCompress(Pointer hComp, byte[] pcSource, int dwSourceSize, PointerByReference ppcCompressed, IntByReference pdwCompressedSize, int bEndOfData);
int XcUncompress(Pointer hComp, byte[] pcSource, int dwSourceSize, PointerByReference ppcUncompressed, IntByReference pdwUncompressedSize, int bEndOfdata);
Usage:
private static final XceedFunctions XCEED_DLL_API;
static {
XCEED_DLL_API = Native.load("XceedZipX64", XceedFunctions.class);
}
private static final String TEST_DATA = "abcabcddd";
//Data pointers
private static Pointer compHandle;
private static byte[] baSource = TEST_DATA.getBytes();
private static PointerByReference pbrCompressed = new PointerByReference();
private static PointerByReference pbrUncompressed = new PointerByReference();
private static IntByReference ibrCompressedSize = new IntByReference();
private static IntByReference ibrUncompressedSize = new IntByReference();
public static void main(String[] args) {
try {
boolean isSuccessfulInit = XCEED_DLL_API.XceedZipInitDLL();
if(isSuccessfulInit) {
compHandle = XCEED_DLL_API.XcCreateXceedCompressionW(new WString("YOUR_LICENCE_KEY_HERE"));
int compressionResult = XCEED_DLL_API.XcCompress(compHandle, baSource, baSource.length, pbrCompressed, ibrCompressedSize, 1);
byte[] compressed = getDataFromPbr(pbrCompressed, ibrCompressedSize);
System.out.println("Compression result: " + compressionResult + " Data: " + new String(compressed));
int decompressionResult = XCEED_DLL_API.XcUncompress(compHandle, compressed, compressed.length, pbrUncompressed, ibrUncompressedSize, 1);
byte[] uncompressed = getDataFromPbr(pbrUncompressed, ibrUncompressedSize);
System.out.println("Decompression result: " + decompressionResult + " Data: " + new String(uncompressed));
}
} finally {
System.out.println("Free memory and shutdown");
if(compHandle != null) {
XCEED_DLL_API.XcDestroyXceedCompression(compHandle);
}
XCEED_DLL_API.XceedZipShutdownDLL();
}
}
private static byte[] getDataFromPbr(PointerByReference pbr, IntByReference ibr) {
return pbr.getValue().getByteArray(0, ibr.getValue());
}
Example output:
Compression result: 0 Data: KLJNLJNII yK
Decompression result: 0 Data: abcabcddd
Free memory and shutdown

Related

CreateProcessAsUser function to run a GUI program from a service

Below is the code I am using to run a GUI app from service application. I am passing cmd string "C:\Windows\notepad.exe".
It is not opening the Notepad and not even giving any error. hToken is null even after using WTSQueryUserToken.
Here is a documentation link for create process as user : https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessasusera
private void cpasUser(String cmd) {
HANDLE h = null;
final HANDLEByReference childStdInRead = new HANDLEByReference();
final HANDLEByReference childStdInWrite = new HANDLEByReference();
final HANDLEByReference childStdOutRead = new HANDLEByReference();
final HANDLEByReference childStdOutWrite = new HANDLEByReference();
final int HANDLE_FLAG_INHERIT = 0x00000001;
final int HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x00000002;
final int BUFSIZE = 4096;
final int GENERIC_READ = 0x80000000;
final int FILE_ATTRIBUTE_READONLY = 1;
final int OPEN_EXISTING = 3;
final DWORD STD_OUTPUT_HANDLE = new DWORD(-11);
final int STARTF_USESTDHANDLES = 0x00000100;
String szCmdline = cmd;
PROCESS_INFORMATION processInformation = new PROCESS_INFORMATION();
STARTUPINFO startupInfo = new STARTUPINFO();
startupInfo.cb = new DWORD(processInformation.size());
startupInfo.hStdError = childStdOutWrite.getValue();
startupInfo.hStdOutput = childStdOutWrite.getValue();
startupInfo.hStdInput = childStdInRead.getValue();
startupInfo.dwFlags |= STARTF_USESTDHANDLES;
// Create the child process.
HANDLE hToken = null;
MyWtsapi32 mw = MyWtsapi32.INSTANCE;
mw.WTSQueryUserToken(Kernel32Ext.INSTANCE.WTSGetActiveConsoleSessionId(), hToken) ;
//be sure that the handle is correct ! (can be the issue)
if (hToken == null) logger.info("Token error.");
if (!Advapi32.INSTANCE.CreateProcessAsUser(
hToken,
szCmdline,
null,
null,
null,
true,
32,
null,
null,
startupInfo,
processInformation)){
// System.err.println(Advapi32.INSTANCE.GetLastError());
logger.error("Cannot create process as User ");
logger.error("error code "+Native.getLastError());
}
MyWtsApi32.java
public interface MyWtsapi32 extends Wtsapi32 {
// Your own instance to access your functions
MyWtsapi32 INSTANCE = Native.load("Wtsapi32", MyWtsapi32.class, W32APIOptions.DEFAULT_OPTIONS);
// From https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox
int MB_OK = 0;
// The function to send the message
boolean WTSSendMessageW(HANDLE hServer, int SessionId,
LPWSTR pTitle, int TitleLength,
LPWSTR pMessage, int MessageLength,
int Style, int Timeout, IntByReference pResponse, boolean bWait);
boolean WTSQueryUserToken(long SessionId,HANDLE hServer);
}
Kernel32Ext.java
public interface Kernel32Ext extends Kernel32{
Kernel32Ext INSTANCE = Native.load("Kernel32",Kernel32Ext.class,W32APIOptions.DEFAULT_OPTIONS);
int WTSGetActiveConsoleSessionId();
}
When your JNA function mappings don't work, the first debugging step should be to check your function mappings.
WTSQueryUserToken is defined as:
BOOL WTSQueryUserToken(
ULONG SessionId,
PHANDLE phToken
);
The Windows type ULONG is an unsigned 32-bit integer; it should be mapped as int, not long.
PHANDLE is a pointer to a HANDLE, not the handle itself. The correct JNA mapping is HANDLEByReference.
So your interface function mapping should be:
boolean WTSQueryUserToken(int SessionId, HANDLEByReference hServer);
And your code to call it should be:
HANDLEByReference phToken = new HANDLEByReference();
MyWtsapi32 mw = MyWtsapi32.INSTANCE;
// you should probably check the return value here
// on failure throw LastErrorException
mw.WTSQueryUserToken(Kernel32Ext.INSTANCE.WTSGetActiveConsoleSessionId(), phToken);
// Extract the HANDLE for use in later code
HANDLE hToken = phToken.getValue();

Accessing DLL pointers through Java

I am using Java (JNA) to access DLL code. Here is the DLL I am using:
U32 ReadMemU32(U32 Addr, U32 NumItems, U32* pData, U8* pStatus);
Here is my sample code:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.ptr.*;
import com.sun.jna.*;
import java.lang.*;
import java.util.*;
import com.sun.jna.*;
import java.lang.*;
public class DLL1 {
#UserFunction(Description="DLL1 Java wrapper", Name = "DLL1")
public static String DLL1(
#UserFunction.Arg(Name = "Address", Description = "Register Address")
String Address
) throws Exception {
byte Status[] = new byte[1];
PointerByReference Data = new PointerByReference ();
long Addr = Long.parseLong(Address.substring(2, Address.length()));
DllInterface.INSTANCE.ReadMemU32(Addr, 1, Data, Status);
System.out.println("Data = " + Data);
System.out.println("Data.getValue() = " + Data.getValue());
return null;
}
// C++ function definition and tell which DLL to fetch
public interface DllInterface extends Library {
DllInterface INSTANCE = (DllInterface) Native.loadLibrary("<dll name>", DllInterface.class);
long ReadMemU32(long Addr, long NumItems, PointerByReference pData, byte[] pStatus);
}
}
The result I am getting is:
Data = allocated#0xe25ac90 (8 bytes)(com.sun.jna.ptr.PointerByReference#e25ac90)
Data.getValue() = native#0xaaaaaaaa
The result (0xaaaaaaaa) does not match with what I expect it to be.
I am new to Java and I am not sure if PointerByReference is the correct thing to use for U32* pData. Please advice.
Looking at the type definition for the function, I would make an educated guess and say that pData is the array pointer to which the function writes the read memory. You can use int[] directly here. Since the status is returned as an out parameter via pointer, you can use a ByteByReference.
In Java, long refers to a 64-bit integer, equivalent to C++'s long long. Since the type is U32, it's probably safe to guess that it refers to a 32-bit integer. This would be an int. You can check JNA's type mappings here.
Notice also that since the function accepts a 32-bit integer for the address, you cannot pass 64-bit addresses to the function.
I would guess that one proper mapping for this function would be:
int ReadMemU32(
int address,
int numItems,
int[] pData,
ByteByReference status
);
If your function truly only needs to read one 32-bit integer from memory, you can change pData's type to IntByReference and use it in the same way as the status parameter's ByteByReference.
Since the function returns an integer, I would guess that it returns the amount of bytes read. If so, it's important to check that this value matches with what you're expecting. Check what the library's documentation says about the return value and error states.
Try this:
import java.lang.*;
import java.util.*;
import com.sun.jna.*;
import com.sun.jna.ptr.*;
public class DLL1 {
#UserFunction(Description="DLL1 Java wrapper", Name = "DLL1")
public static String DLL1(
#UserFunction.Arg(Name = "Address", Description = "Register Address")
String Address
) throws Exception {
String addressWithoutPrefix = Address.substring(2)
int parsedAddress = Integer.parseInt(addressWithoutPrefix, 16)
int bytesToRead = 1;
int[] buffer = new int[bytesToRead];
ByteByReference status = new ByteByReference(0);
int BytesRead = DllInterface.INSTANCE.ReadMemU32(
parsedAddress,
bytesToRead,
buffer,
status
);
System.out.println("Status = " + status.getValue());
System.out.println("Bytes read = " + bytesRead);
System.out.println("Data = " + Arrays.toString(buffer));
return null;
}
// C++ function definition and tell which DLL to fetch
public interface DllInterface extends Library {
DllInterface INSTANCE = (DllInterface) Native.loadLibrary("<dll name>", DllInterface.class);
int ReadMemU32(
int address,
int numItems,
int[] pData,
ByteByReference status
);
}
}

Pre-allocating drive space for file storage

Is there a Java way to pre-allocate drive space for exclusive usage in the application?
There is no requirement for this space to be a separate filesystem or a part of existing filesystem (so could easily be a database), but it should allow for reserving the specified amount of space and allow for random reads/writes with high enough throughput.
Here's a stripped down version of my JNA-based fallocate solution. The main trick is obtaining the native file descriptor. I've only tested it on Linux so far, but it should work on all modern POSIX/non-Windows systems. It's not necessary on Windows, as Windows does not create sparse files by default (only with StandardOpenOption.SPARSE), so RandomAccessFile.setLength(size) or FileChannel.write(ByteBuffer.allocate(1), size - 1) are adequate there.
/**
* Provides access to operating system-specific {#code fallocate} and
* {#code posix_fallocate} functions.
*/
public final class Fallocate {
private static final boolean IS_LINUX = Platform.isLinux();
private static final boolean IS_POSIX = !Platform.isWindows();
private static final int FALLOC_FL_KEEP_SIZE = 0x01;
private final int fd;
private int mode;
private long offset;
private final long length;
private Fallocate(int fd, long length) {
if (!isSupported()) {
throwUnsupported("fallocate");
}
this.fd = fd;
this.length = length;
}
public static boolean isSupported() {
return IS_POSIX;
}
public static Fallocate forChannel(FileChannel channel, long length) {
return new Fallocate(getDescriptor(channel), length);
}
public static Fallocate forDescriptor(FileDescriptor descriptor, long length) {
return new Fallocate(getDescriptor(descriptor), length);
}
public Fallocate fromOffset(long offset) {
this.offset = offset;
return this;
}
public Fallocate keepSize() {
requireLinux("fallocate keep size");
mode |= FALLOC_FL_KEEP_SIZE;
return this;
}
private void requireLinux(String feature) {
if (!IS_LINUX) {
throwUnsupported(feature);
}
}
private void throwUnsupported(String feature) {
throw new UnsupportedOperationException(feature +
" is not supported on this operating system");
}
public void execute() throws IOException {
final int errno;
if (IS_LINUX) {
final int result = FallocateHolder.fallocate(fd, mode, offset, length);
errno = result == 0 ? 0 : Native.getLastError();
} else {
errno = PosixFallocateHolder.posix_fallocate(fd, offset, length);
}
if (errno != 0) {
throw new IOException("fallocate returned " + errno);
}
}
private static class FallocateHolder {
static {
Native.register(Platform.C_LIBRARY_NAME);
}
private static native int fallocate(int fd, int mode, long offset, long length);
}
private static class PosixFallocateHolder {
static {
Native.register(Platform.C_LIBRARY_NAME);
}
private static native int posix_fallocate(int fd, long offset, long length);
}
private static int getDescriptor(FileChannel channel) {
try {
// sun.nio.ch.FileChannelImpl declares private final java.io.FileDescriptor fd
final Field field = channel.getClass().getDeclaredField("fd");
field.setAccessible(true);
return getDescriptor((FileDescriptor) field.get(channel));
} catch (final Exception e) {
throw new UnsupportedOperationException("unsupported FileChannel implementation", e);
}
}
private static int getDescriptor(FileDescriptor descriptor) {
try {
// Oracle java.io.FileDescriptor declares private int fd
final Field field = descriptor.getClass().getDeclaredField("fd");
field.setAccessible(true);
return (int) field.get(descriptor);
} catch (final Exception e) {
throw new UnsupportedOperationException("unsupported FileDescriptor implementation", e);
}
}
}
You could try using a RandomAccessFile object and use the setLength() method.
Example:
File file = ... //Create a temporary file on the filesystem your trying to reserve.
long bytes = ... //number of bytes you want to reserve.
RandomAccessFile rf = null;
try{
rf = new RandomAccessFile(file, "rw"); //rw stands for open in read/write mode.
rf.setLength(bytes); //This will cause java to "reserve" memory for your application by inflating/truncating the file to the specific size.
//Do whatever you want with the space here...
}catch(IOException ex){
//Handle this...
}finally{
if(rf != null){
try{
rf.close(); //Lets be nice and tidy here.
}catch(IOException ioex){
//Handle this if you want...
}
}
}
Note: The file must exist before you create the RandomAccessFile object.
The RandomAccessFile object can then be used to read/write to the file. Make sure the target filesystem has enough free space. The space may not be "exclusive" per-say but you can always use File Locks to do that.
P.S: If you end up realizing hard drives are slow and useless (or meant to use RAM from the start) you can use the ByteBuffer object from java.nio. The allocate() and allocateDirect() methods should be more than enough. The byte buffer will be allocated into RAM (and possible SwapFile) and will be exclusive to this java program. Random access can be done by changing the position of the buffer. Since these buffers use signed integers to reference position, max sizes are limited to 2^31 - 1.
Read more on RandomAccessFile here.
Read more on FileLock (the java object) here.
Read more on ByteBuffer here.
On Linux systems you can use fallocate() system call. It's extremely fast. Just run Bash command.
UPD:
fallocate -l 10G 10Gigfile
You can pre-allocate space by writing a large file, but to be honest I wouldn't bother. Performance will be pretty good/ probably better than you need.
If you really needed performance, you'd be writing C++/C# and doing RAW I/O.
But that's typically only done when writing an RDBMS engine, high-volume media capture or similar.

Function not found JNA + SiUSBXp

I'm trying to use JNA with USBXPRESS library from SiLabs (siusbxp.dll), and while basic functions work fine, there is a problem with SI_GetDeviceProductString function.
public class usbxpress
{
public interface SiUSBXp extends StdCallLibrary
{
SiUSBXp INSTANCE = (SiUSBXp) Native.loadLibrary("SiUSBXp", SiUSBXp.class);
byte SI_GetNumDevices (IntByReference lpdwNumDevices);
byte SI_GetProductString( int dwDeviceNum, byte[] lpvDeviceString, int dwFlags);
byte SI_Open (int dwDevice, HANDLEByReference cyHandle);
byte SI_GetPartNumber (HANDLE cyHandle, ByteByReference lpbPartNum);
byte SI_GetDeviceProductString (HANDLE cyHandle, PointerByReference lpProduct, ByteByReference lpbLength, int bConvertToASCII);
//byte SI_GetDeviceProductString (HANDLE cyHandle, LPVOID lpProduct, LPBYTE lpbLength, BOOL bConvertToASCII = TRUE); //original c function
}
public static void main(String[] args)
{
//checking number of connected devices
IntByReference lpdwNumDevices = new IntByReference();
SiUSBXp.INSTANCE.SI_GetNumDevices (lpdwNumDevices);
System.out.println(lpdwNumDevices.getValue());
//opening the device
HANDLEByReference dev_handle_ref = new HANDLEByReference();
byte status = SiUSBXp.INSTANCE.SI_Open(0, dev_handle_ref);
System.out.printf("Status %d\n", status);
HANDLE device_handle = dev_handle_ref.getValue();
//checking part number
ByteByReference lpbPartNum = new ByteByReference();
SiUSBXp.INSTANCE.SI_GetPartNumber(device_handle, lpbPartNum);
System.out.printf("Part number is CP210%d\n", lpbPartNum.getValue());
//checking product string - does not work
PointerByReference lpProduct = new PointerByReference();
ByteByReference lpbLength = new ByteByReference();
SiUSBXp.INSTANCE.SI_GetDeviceProductString(device_handle, lpProduct, lpbLength, 1);
}}
when I try to run it I get the following error:
> Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'SI_GetDeviceProductString': at com.sun.jna.Function.<init>(Function.java:179)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:391)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:371)
at com.sun.jna.Library$Handler.invoke(Library.java:205)
at $Proxy0.SI_GetDeviceProductString(Unknown Source)
It feels like it's the problem with the default argument of the C-function. I tried to use int as the argument and tried omitting it, but none of these helped.
I didn't even reach the SI_Write (HANDLE cyHandle, LPVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpdwBytesWritten, OVERLAPPED* o = NULL); function, which is promising to cause even more problems:)
Could please anyone suggest how can I deal with the default function arguments in JNA?
Update: SI_Write function works fine this way:
byte SI_Write (HANDLE cyHandle, PointerByReference lpBuffer, int dwBytesToWrite, IntByReference lpdwBytesWritten, Pointer o);
...
SiUSBXp.INSTANCE.SI_Write (device_handle, lpBuffer, message.length, lpdwBytesWritten, null);
So the problem is caused by something else, but still it exists.
I've managed to solve the problem by using an older version of the SiUSBXp library, which was found on the internet.
Newer version downloaded from SiLabs website is acting weird - sometimes SI_GetDeviceProductString function is visible in Dependency Walker and sometimes it's not, while older one is fine.

Launching Java main method from C with JNI causes OpenGL error

I'm creating a program in Java that will interface with a C library to take images from hardware and display with OpenGL (using JOGL). So the workflow is this:
Hardware -> C -> disk image file -> Java -> JOGL
I have the Java -> JOGL part working fine. The images are displayed fully and I can load multiple images at a time. I also have the Hardware -> C working as well, and a temporary viewer in C is showing that the images are being created just fine.
The crux of the problem is this: I want to be able to launch the main() method of the Java program in C and then display the image using only JNI code in C (using static methods I've created). However, when I do this, the image is truncated, where I only get the top 20 or so rows. I do know that I'm loading the entire image because I can check the pixel values for every pixel in the image. Only the display is truncated. The same number of pixels are shown for every image I load.
This is the C code in a nutshell:
int main () { ...
HMODULE * jvm_dll;
//HWND hWnd = GetConsoleWindow();
//ShowWindow( hWnd, SW_HIDE );
env = create_vm(&jvm, jvm_dll);
if (env == NULL) { return 1; }
//Create a new String array with one blank String
cls = (*env)->FindClass(env,"java/lang/String");
arg = (*env)->NewStringUTF(env,"");
args = (jobjectArray)(*env)->NewObjectArray(env, 1, cls, arg);
//Call the main method with the String array argument
cls = (*env)->FindClass(env, "path/to/package/program");
mID = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
(*env)->CallStaticVoidMethod(env, cls, mID, args);
PrintStackTrace(env);
blockAndClose(jvm, env, jvm_dll);
return ret;
}
int blockAndClose() {...
int ret = 0;
if (jvm == 0 || env == 0) {
FreeLibrary(*jvm_dll);
return 1;
}
ret = (*jvm)->DestroyJavaVM(jvm);
if(jvm_dll) {
FreeLibrary(*jvm_dll);
jvm_dll = 0;
}
env = 0;
jvm = 0;
return ret;
}
I know that I've only posted the C portion, but the Java portion is working when I run it purely in Java. At this point, the C portion is simply a "launcher" of sorts, so I'm wondering why it affects the running of the code. Any suggestions?
EDIT:
Here's the code for loading images. I use JAI to load in the image as a PlanarImage type (TiledImage class is a subclass).
tempI = JAI.create("fileload", path);
DataBufferUShort dbOut = null;
ColorModel CM = PlanarImage.getDefaultColorModel(DataBuffer.TYPE_USHORT, tempI.getNumBands());
SampleModel SM = CM.createCompatibleSampleModel(tempI.getWidth(), tempI.getHeight());
//Ensure that the buffer is in the internal format (USHORT)
if (tempI.getData().getDataBuffer().getDataType() != DataBuffer.TYPE_USHORT) {
DataBuffer dBIn = tempI.getData().getDataBuffer();
short [] dBPixels = new short[dBIn.getSize()];
switch(dBIn.getDataType()) {
case DataBuffer.TYPE_BYTE:
DataBufferByte dBByte = (DataBufferByte)dBIn;
byte [] pByte = dBByte.getData();
for (int b = 0; b < pByte.length; b++)
{ dBPixels[b] = (short)((double)pByte[b] / 0xFF * 0xFFFF); }
dbOut = new DataBufferUShort(dBPixels, dBPixels.length);
break;
case DataBuffer.TYPE_SHORT:
DataBufferShort dBShort = (DataBufferShort)dBIn;
dBPixels = dBShort.getData();
dbOut = new DataBufferUShort(dBPixels, dBPixels.length);
break;
} //SWITCH DATA TYPE --END
WritableRaster rs = Raster.createWritableRaster(SM, dbOut, new Point(0,0));
tempI = new TiledImage(0,0,tempI.getWidth(),tempI.getHeight(),0,0,SM,CM);
((TiledImage)tempI).setData(rs);
}

Categories

Resources