Skip to main content

Dear experts

6 replies [Last post]
huynt
Offline
Joined: 2005-06-24
Points: 0

I got problem when i create TIFF(MH or MR) image from image data. After i added tags into TIFF data it displayed on "Window Picture & Fax Viewer" app but I cant encode it to other formats this process throws RuntimeException "Scanline must begin with EOL code word." or "All fill bits preceding EOL code must be 0." I know that i must write EOL but I dont know what is "byte aligned" and how to determine it. Can you tell me how to i resolve my problem.

Thanks from VN
HuyNT

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
huynt
Offline
Joined: 2005-06-24
Points: 0

I resolved my problem.

Thanks
HuyNT.

Brian Burkhalter

That's great!

Would you tell us how?

Thanks,

Brian

On Mon, 23 Apr 2007, jai-interest@javadesktop.org wrote:

> I resolved my problem.
>
> Thanks
> HuyNT.
> [Message sent by forum member 'huynt' (huynt)]
>
> http://forums.java.net/jive/thread.jspa?messageID=213688
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
> For additional commands, e-mail: interest-help@jai.dev.java.net
>
>

----------------
Brian Burkhalter
Java Media, Imaging, and Graphics
Sun Microsystems, Inc.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This email message is for the sole use of the intended recipient(s)
and may contain confidential and privileged information. Any
unauthorized review, use, disclosure or distribution is prohibited.
If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
For additional commands, e-mail: interest-help@jai.dev.java.net

bpb
Offline
Joined: 2004-06-23
Points: 0

I modified your program so that it would run (included below). Apparently the TIFF file header and IFD that you are prepending do not match the data. The tiffinfo program outputs this

tiffinfo test.tif
test.tif: XResolution: Rational with zero denominator (num = 204).
TIFF Directory at offset 0x8 (8)
Image Width: 368 Image Length: 368
Resolution: 1, 196
Compression Scheme: CCITT Group 3
Photometric Interpretation: min-is-white
FillOrder: msb-to-lsb
Rows/Strip: 368
Planar Configuration: single image plane
Group 3 Options: 2-d encoding+EOL padding (5 = 0x5)

while tiffdump gives this

tiffdump test.tif
test.tif:
Magic: 0x4d4d Version: 0x2a
Directory 0: offset 8 (0x8) next 0 (0)
ImageWidth (256) LONG (4) 1<368>
ImageLength (257) LONG (4) 1<368>
Compression (259) SHORT (3) 1<3>
Photometric (262) SHORT (3) 1<0>
FillOrder (266) SHORT (3) 1<1>
StripOffsets (273) LONG (4) 1<162>
RowsPerStrip (278) LONG (4) 1<368>
StripByteCounts (279) LONG (4) 1<2800>
XResolution (282) RATIONAL (5) 1
YResolution (283) RATIONAL (5) 1<196>
Group3Options (292) LONG (4) 1<5>

The image is not displayable by a utility using libtiff either.

huynt
Offline
Joined: 2005-06-24
Points: 0

tiff header is correct but EOL is not. I can't determine address to add EOL.

Thanks
HuyNT

Brian Burkhalter

More information would be needed. What versions of Java and JAI are you using?
Can you supply a test case and data?

Brian

On Tue, 17 Apr 2007, jai-interest@javadesktop.org wrote:

> I got problem when i create TIFF(MH or MR) image from image data. After i added tags into TIFF data it displayed on "Window Picture & Fax Viewer" app but I cant encode it to other formats this process throws RuntimeException "Scanline must begin with EOL code word." or "All fill bits preceding EOL code must be 0." I know that i must write EOL but I dont know what is "byte aligned" and how to determine it. Can you tell me how to i resolve my problem.
>
> Thanks from VN
> HuyNT
> [Message sent by forum member 'huynt' (huynt)]
>
> http://forums.java.net/jive/thread.jspa?messageID=212658
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
> For additional commands, e-mail: interest-help@jai.dev.java.net
>
>

----------------
Brian Burkhalter
Java Media, Imaging, and Graphics
Sun Microsystems, Inc.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This email message is for the sole use of the intended recipient(s)
and may contain confidential and privileged information. Any
unauthorized review, use, disclosure or distribution is prohibited.
If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
For additional commands, e-mail: interest-help@jai.dev.java.net

huynt
Offline
Joined: 2005-06-24
Points: 0

this link is data http://www.freewebtown.com/htmn1001/library/test.dat
below is my code.
[code]
package test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

public class Main {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
File f = new File("D:\\test.dat");
FileInputStream fis = null;
byte[] data = new byte[(int)f.length()];
try {
fis = new FileInputStream(f);
fis.read(data);
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
f = null;
TiffHeader fileHeader = new TiffHeader((short) 0x0B);

fileHeader.setField((short)0x0100, (short)0x4, 1, 368);// DPI
fileHeader.setField((short)0x0101, (short)0x4, 1, 368);// DPI

fileHeader.setField((short)0x0103, (short)0x3, 1, 0x03);
fileHeader.setField((short)0x0106, (short)0x3, 1, 0x00);
fileHeader.setField((short)0x010A, (short)0x3, 1, 0x01);
int stripPosition = fileHeader.getTiffHeaderLength();
fileHeader.setField((short)0x0111, (short)0x4, 1, stripPosition);
fileHeader.setField((short)0x0116, (short)0x4, 1, 368);// consider IMAGE_LENGTH

fileHeader.setField((short)0x0124, (short)0x4, 1, 0x05); // MR
fileHeader.setField((short)0x0117, (short)0x4, 1, data.length);

fileHeader.setX_Res_Value(204, 1);
fileHeader.setY_Res_Value(196, 1);

byte[] imageData = new byte[fileHeader.getTiffHeaderLength() + data.length];
System.arraycopy(fileHeader.getTiffHeader(), 0, imageData, 0, fileHeader.getTiffHeaderLength());
System.arraycopy(data, 0, imageData, fileHeader.getTiffHeaderLength(), data.length);
FileOutputStream fos = null;
try {
fos = new FileOutputStream("D:\\test.tif");
fos.write(imageData);
fos.close();
RenderedOp op = JAI.create("fileload", "D:\\test.tif");
fos = new FileOutputStream("D:\\test.bmp");
JAI.create("filestore", op, "tiff", fos, null);
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

class TiffHeader {

protected short byteOrder = 0x4D4D;
protected short fileIdentity = 0x002A;
protected int IFDOffset = 0x00000008;

protected short numberOfDirectoryEntries;

protected ArrayList entries = new ArrayList();

protected byte[] X_Res_Value, Y_Res_Value;
protected byte[] stripOffsetValue,stripByteCountValue;

protected int nextIFDOffset = 0x0;
protected int headerEndOffset;

public TiffHeader(short numberOfDirectoryEntries )
{
this.setNumberOfDirectoryEntries(numberOfDirectoryEntries);
}

/**
* Get index of a field
* @param tagValue the tag to look for in header
* @return index of a field.
*/
protected int getFieldIndex(short tagValue)
{
for (int i = 0; i < entries.size(); i++)
if ( ((IFDEntry)entries.get(i)).tag >= tagValue) return i;

return -1;
}

/**
* Get tiff header length (include extra fields)
* @return header length - int
*/
public int getTiffHeaderLength()
{
return (headerEndOffset + 2*0x8);
}

/**
* Set a TIFF field.
* If a new field, then add, othewise, change value
* @param tag
* @param type
* @param count
* @param offset
*/
public void setField(short tag,short type,int count, int offset)
{
//Move to higher position
if (type == 0x3) offset*=0x10000;

int index = getFieldIndex(tag);
if (index != -1)
{
if (((IFDEntry)entries.get(index)).tag == tag)
((IFDEntry)entries.get(index)).setValue(count, offset);
else
entries.add(index, new IFDEntry(tag, type, count, offset));
}
else
entries.add(new IFDEntry(tag, type, count, offset));
}

/**
* Set X_Resolution value
* @param nume numerator
* @param deno denominator
*/
public void setX_Res_Value(int nume,int deno)
{
X_Res_Value = new byte[0x8];
Util.copyArrayToArray(Util.intToByteArray(nume),X_Res_Value,0);
Util.copyArrayToArray(Util.intToByteArray(deno),X_Res_Value,4);
setField((short)0x011A, (short)0x5, 1, headerEndOffset);

}

/**
* Set Y_Resolution value
* @param nume numerator
* @param deno denominator
*/
public void setY_Res_Value(int nume, int deno)
{
Y_Res_Value = new byte[0x8];
Util.copyArrayToArray(Util.intToByteArray(nume),Y_Res_Value,0);
Util.copyArrayToArray(Util.intToByteArray(deno),Y_Res_Value,4);
setField((short)0x011B, (short)0x5, 1,
headerEndOffset + 0x05);
}

/**
* Get byte array contains tiff header information
* @return a byte array contains tiff header information
*/
public byte[] getTiffHeader()
{

byte[] header = new byte[this.getTiffHeaderLength()];
int i = 0;

Util.copyArrayToArray(Util.shortToByteArray(byteOrder),header,i);
i+=2;
Util.copyArrayToArray(Util.shortToByteArray(fileIdentity),header,i);
i+=2;
Util.copyArrayToArray(Util.intToByteArray(IFDOffset),header,i);
i+=4;
Util.copyArrayToArray(Util.shortToByteArray(numberOfDirectoryEntries),header,i);
i+=2;

for (int j = 0; j < entries.size(); j++)
{
Util.copyArrayToArray(entries.get(j).getValue(),header,i);
i+=12;
}

Util.copyArrayToArray(X_Res_Value,header,
entries.get(getFieldIndex((short)0x011A)).valueOffset);

Util.copyArrayToArray(Y_Res_Value,header,
entries.get(getFieldIndex((short)0x011B)).valueOffset);

return header;
}

/**
* @param byteOrder the byteOrder to set
*/
public void setByteOrder(short byteOrder) {
this.byteOrder = byteOrder;
}

/**
* @param offset the iFDOffset to set
*/
public void setIFDOffset(int offset) {
IFDOffset = offset;
}

/**
* Set number of directory entries in TIFF header
* @param numberOfDirectoryEntries the numberOfDirectoryEntries to set
*/
private void setNumberOfDirectoryEntries(short numberOfDirectoryEntries) {
this.numberOfDirectoryEntries = numberOfDirectoryEntries;

headerEndOffset = 14 + numberOfDirectoryEntries*12;
}

}

class IFDEntry {
protected short tag;
protected short type;
protected int count;
protected int valueOffset;

public IFDEntry(short tag,short type, int count, int valueOffset)
{
this.tag = tag;
this.type = type;
this.count = count;
this.valueOffset = valueOffset;
}

/**
* Change a TIFF field
* @param count
* @param valueOffset
*/
public void setValue(int count, int valueOffset)
{
this.count = count;
this.valueOffset = valueOffset;
}

/**
*
* @return 12 bytes array contains Tag,Type,Count,Offset
*/
public byte[] getValue()
{
byte[] ifd = new byte[12];

System.arraycopy(Util.shortToByteArray(tag),0,
ifd, 0,2);
System.arraycopy(Util.shortToByteArray(type),0,
ifd, 2,2);
System.arraycopy(Util.intToByteArray(count),0,
ifd, 4,4);
System.arraycopy(Util.intToByteArray(valueOffset),0,
ifd, 8,4);
return ifd;
}
}

class Util {

public static final void copyArrayToArray(byte[] source, byte[] dest, int position)
{
if (dest.length - position < source.length) return;
for (int i = 0; i < source.length; i++)
dest[position + i] = source[i];
}

/**
* Convert Int to array of bytes
* @param value
*/
public static final byte[] intToByteArray(int value) {
return new byte[]{
(byte)(value >> 24),
(byte)(value >> 16 & 0xff),
(byte)(value >> 8 & 0xff),
(byte)(value & 0xff) };
}

/**
* Convert int to array of bytes, fill 0 if not fit size
* Ex: value = 123, size = 5 -> return byte array = 00123
* @param value
* @param size
*/
public static final byte[] intToByteArray(int value,int size) {
byte[] data = new byte[size];
String str = Integer.toString(value);

int j = str.length() - 1;
for (int i = size - 1; i >= 0; i--)
{
if (j > -1) data[i] = (byte)str.charAt(j--);
else data[i] = 0x30;
}
return data;
}

/**
* Reads short into array of bytes.
* @param value short type.
*/
public static final byte[] shortToByteArray(short value) {
return new byte[]{
(byte)(value >> 8 & 0xff),
(byte)(value & 0xff) };
}

}
[/code]

Thanks.
HuyNT

Message was edited by: huynt