//
// Android PDF Writer
// http://coderesearchlabs.com/androidpdfwriter
//
// by Javier Santo Domingo (j-a-s-d@coderesearchlabs.com)
//
package totalcross.util.pdf;
import totalcross.io.*;
import totalcross.ui.image.*;
import totalcross.util.zip.*;
public class XObjectImage
{
public static final int BITSPERCOMPONENT_8 = 8;
public static final String DEVICE_RGB = "/DeviceRGB";
public static boolean INTERPOLATION = false;
public static int BITSPERCOMPONENT = BITSPERCOMPONENT_8;
public static String COLORSPACE = DEVICE_RGB;
private static int mImageCount = 0;
private PDFDocument mDocument;
private IndirectObject mIndirectObject;
private int mDataSize = 0;
private int mWidth = -1;
private int mHeight = -1;
private String mName = "";
private String mId = "";
private String mProcessedImage = "";
public XObjectImage(PDFDocument document, Image Image) throws IOException
{
mDocument = document;
mProcessedImage = processImage(configureImage(Image));
mId = Indentifiers.generateId(mProcessedImage);
mName = "/img" + (++mImageCount);
}
public void appendToDocument()
{
mIndirectObject = mDocument.newIndirectObject();
mDocument.includeIndirectObject(mIndirectObject);
mIndirectObject.addDictionaryContent(" /Type /XObject\n" + " /Subtype /Image\n" + " /Filter [/ASCII85Decode /FlateDecode]\n" + " /Width " + mWidth + "\n"
+ " /Height " + mHeight + "\n" + " /BitsPerComponent " + String.valueOf(BITSPERCOMPONENT) + "\n" + " /Interpolate "
+ String.valueOf(INTERPOLATION) + "\n" + " /ColorSpace " + DEVICE_RGB + "\n" + " /Length " + mProcessedImage.length() + "\n");
mIndirectObject.addStreamContent(mProcessedImage);
}
private Image configureImage(Image image)
{
if (image != null)
{
mWidth = image.getWidth();
mHeight = image.getHeight();
mDataSize = mWidth * mHeight * 3;
}
return image;
}
private byte[] getImageData(Image image)
{
byte[] data = null;
if (image != null)
{
data = new byte[mDataSize];
int w = mWidth;
int h = mHeight;
final int bytesPerPixel = 4;
byte[] row = new byte[bytesPerPixel * w];
int offset = 0;
for (int y = 0; y < h; y++)
{
image.getPixelRow(row, y);
int r = 0;
for (int x = 0; x < w; x++)
{
data[offset++] = row[r++];
data[offset++] = row[r++];
data[offset++] = row[r++];
r++;
}
}
}
return data;
}
private boolean deflateImageData(ByteArrayStream baos, byte[] data) throws IOException
{
if (data != null)
{
ZLib.deflate(new ByteArrayStream(data), baos, ZLib.NO_COMPRESSION);
return true;
}
return false;
}
private String encodeImageData(ByteArrayStream baos)
{
ByteArrayStream sob = new ByteArrayStream(1024);
ASCII85Encoder enc85 = new ASCII85Encoder(sob);
byte[] nl = {(byte)'\n'};
try
{
int i = 0;
for (byte b : baos.toByteArray())
{
enc85.write(b);
if (i++ == 255)
{
sob.writeBytes(nl,0,1);
i = 0;
}
}
return new String(sob.toByteArray());
}
catch (IOException e)
{
e.printStackTrace();
}
return "";
}
private String processImage(Image Image) throws IOException
{
ByteArrayStream baos = new ByteArrayStream(1024);
if (deflateImageData(baos, getImageData(Image)))
return encodeImageData(baos);
return null;
}
public String asXObjectReference()
{
return mName + " " + mIndirectObject.getIndirectReference();
}
public String getName()
{
return mName;
}
public String getId()
{
return mId;
}
public int getWidth()
{
return mWidth;
}
public int getHeight()
{
return mHeight;
}
}