encode To Bitmap - Java Language Basics

Java examples for Language Basics:Bit

Description

encode To Bitmap

Demo Code

/*/*from ww w  .j a v a  2  s.  c o m*/
 * Syncany, www.syncany.org
 * Copyright (C) 2011 Philipp C. Heckel <philipp.heckel@gmail.com> 
 *
 * 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 3 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, see <http://www.gnu.org/licenses/>.
 */
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

public class Main{
    public static void main(String[] argv) throws Exception{
        File srcFile = new File("Main.java");
        File dstFile = new File("Main.java");
        encodeToBitmap(srcFile,dstFile);
    }
    private static final int BMP_HEADER_LENGTH = 54;
    private static final int BMP_OFFSET_FILESIZE_BYTES = 2;
    private static final int BMP_OFFSET_IMAGE_WIDTH = 18;
    private static final int BMP_OFFSET_IMAGE_HEIGHT = 22;
    private static final int BMP_OFFSET_IMAGE_DATA_BYTES = 34;
    private static final int BMP_OFFSET_PAYLOAD_LENGTH = 38;
    private static final byte[] BMP_HEADER = new byte[] {
    /* 00 */0x42, 0x4d, // signature
            /* 02 */UDEF, UDEF, UDEF, UDEF, // size in bytes, filled dynamically
            /* 06 */0x00, 0x00, // reserved, must be zero
            /* 08 */0x00, 0x00, // reserved, must be zero
            /* 10 */0x36, 0x00, 0x00, 0x00, // offset to start of image data in bytes
            /* 14 */0x28, 0x00, 0x00, 0x00, // size of BITMAPINFOHEADER structure, must be 40 (0x28)
            /* 18 */UDEF, UDEF, UDEF, UDEF, // image width in pixels, filled dynamically
            /* 22 */UDEF, UDEF, UDEF, UDEF, // image height in pixels, filled dynamically
            /* 26 */0x01, 0x00, // number of planes, must be 1
            /* 28 */0x18, 0x00, // number of bits per pixel (1, 4, 8, or 24) -> 24 = 0x18
            /* 30 */0x00, 0x00, 0x00, 0x00, // compression type (0=none, 1=RLE-8, 2=RLE-4)
            /* 34 */UDEF, UDEF, UDEF, UDEF, // size of image data in bytes (including padding)
            /* 38 */UDEF, UDEF, UDEF, UDEF, // normally: horizontal resolution in pixels per meter (unreliable)
                                             // HERE: used to indicate the payload length
            /* 42 */0x00, 0x00, 0x00, 0x00, // vertical resolution in pixels per meter (unreliable)
            /* 46 */0x00, 0x00, 0x00, 0x00, // number of colors in image, or zero
            /* 50 */0x00, 0x00, 0x00, 0x00, // number of important colors, or zero
    };
    public static void encodeToBitmap(File srcFile, File dstFile)
            throws Exception {
        if (srcFile.length() > Integer.MAX_VALUE) {
            throw new RuntimeException("File too big; max. "
                    + Integer.MAX_VALUE + " bytes supported.");
        }

        int payloadLength = (int) srcFile.length();
        int pixelWidth = (int) Math.ceil(Math
                .sqrt((double) payloadLength / 3));
        int pixelHeight = (int) Math.ceil((double) payloadLength
                / (double) pixelWidth / 3 /* RGB */);
        int linePadding = 4 - (pixelWidth * 3 % 4); // row length must be divisible by 4; calculate padding

        int filesizeBytes = pixelWidth * pixelHeight * 3 /* RGB */
                + pixelHeight * linePadding /* padding */
                + BMP_HEADER_LENGTH /* BMP header*/;

        int imgBytesWithPadding = filesizeBytes - BMP_HEADER_LENGTH;
        int payloadPadding = pixelWidth * pixelHeight * 3 - payloadLength;

        /*System.out.println("payload = "+payloadLength);
        System.out.println("pixel width  = sqrt(payload/3) = "+pixelWidth);
        System.out.println("pixel height = payload / width / 3 = "+pixelHeight);
        System.out.println("padding per line = "+linePadding);
        System.out.println("imgbytes w/ padding = "+imgBytesWithPadding);
        System.out.println("filesize total = "+filesizeBytes);   
        System.out.println("padding = "+payloadPadding);*/

        byte[] header = BMP_HEADER.clone();

        writeIntLE(header, BMP_OFFSET_FILESIZE_BYTES, filesizeBytes);
        writeIntLE(header, BMP_OFFSET_IMAGE_WIDTH, pixelWidth);
        writeIntLE(header, BMP_OFFSET_IMAGE_HEIGHT, pixelHeight);
        writeIntLE(header, BMP_OFFSET_IMAGE_DATA_BYTES, imgBytesWithPadding);
        writeIntLE(header, BMP_OFFSET_PAYLOAD_LENGTH, payloadLength);

        // Add payload 
        InputStream is = new FileInputStream(srcFile);
        FileOutputStream os = new FileOutputStream(dstFile);

        os.write(header, 0, header.length);

        // Write first row [4 bytes, width-4 bytes]
        //os.write(toByteArrayLE(payloadLength));

        // Write other lines (regular width)
        byte[] row = new byte[pixelWidth * 3];
        int read;

        while ((read = is.read(row)) != -1) {
            os.write(row, 0, read);
            os.write(new byte[linePadding]); // padding
        }

        // Write payload padding
        os.write(new byte[payloadPadding]);

        is.close();
        os.close();
    }
    private static void writeIntLE(byte[] bytes, int startoffset, int value) {
        bytes[startoffset] = (byte) (value);
        bytes[startoffset + 1] = (byte) (value >>> 8);
        bytes[startoffset + 2] = (byte) (value >>> 16);
        bytes[startoffset + 3] = (byte) (value >>> 24);
    }
}

Related Tutorials