JAVA image transfer problem

Posted by user579098 on Stack Overflow See other posts from Stack Overflow or by user579098
Published on 2011-01-17T21:41:44Z Indexed on 2011/01/17 21:53 UTC
Read the original article Hit count: 486

Filed under:
|
|
|
|

Hi, I have a school assignment, to send a jpg image,split it into groups of 100 bytes, corrupt it, use a CRC check to locate the errors and re-transmit until it eventually is built back into its original form.

It's practically ready, however when I check out the new images, they appear with errors..

I would really appreciate if someone could look at my code below and maybe locate this logical mistake as I can't understand what the problem is because everything looks ok :S

For the file with all the data needed including photos and error patterns one could download it from this link:http://rapidshare.com/#!download|932tl2|443122762|Data.zip|739

Thanks in advance,

Stefan

p.s dont forget to change the paths in the code for the image and error files

package networks;

import java.io.*;               // for file reader
import java.util.zip.CRC32;     // CRC32 IEEE (Ethernet)

public class Main {

/**
 * Reads a whole file into an array of bytes.
 * @param file The file in question.
 * @return Array of bytes containing file data.
 * @throws IOException Message contains why it failed.
 */
public static byte[] readFileArray(File file) throws IOException {
    InputStream is = new FileInputStream(file);
    byte[] data=new byte[(int)file.length()];
    is.read(data);
    is.close();
    return data;
}

/**
 * Writes (or overwrites if exists) a file with data from an array of bytes.
 * @param file The file in question.
 * @param data Array of bytes containing the new file data.
 * @throws IOException Message contains why it failed.
 */
public static void writeFileArray(File file, byte[] data) throws IOException {
    OutputStream os = new FileOutputStream(file,false);
    os.write(data);
    os.close();
}

/**
 * Converts a long value to an array of bytes.
 * @param data The target variable.
 * @return Byte array conversion of data.
 * @see http://www.daniweb.com/code/snippet216874.html
 */
public static byte[] toByta(long data) {
    return new byte[] {
        (byte)((data >> 56) & 0xff),
        (byte)((data >> 48) & 0xff),
        (byte)((data >> 40) & 0xff),
        (byte)((data >> 32) & 0xff),
        (byte)((data >> 24) & 0xff),
        (byte)((data >> 16) & 0xff),
        (byte)((data >> 8) & 0xff),
        (byte)((data >> 0) & 0xff),
    };
}

/**
 * Converts a an array of bytes to long value.
 * @param data The target variable.
 * @return Long value conversion of data.
 * @see http://www.daniweb.com/code/snippet216874.html
 */
public static long toLong(byte[] data) {
    if (data == null || data.length != 8) return 0x0;
    return (long)(
        // (Below) convert to longs before shift because digits
        // are lost with ints beyond the 32-bit limit
        (long)(0xff & data[0]) << 56 |
        (long)(0xff & data[1]) << 48 |
        (long)(0xff & data[2]) << 40 |
        (long)(0xff & data[3]) << 32 |
        (long)(0xff & data[4]) << 24 |
        (long)(0xff & data[5]) << 16 |
        (long)(0xff & data[6]) << 8  |
        (long)(0xff & data[7]) << 0
    );
}

public static byte[] nextNoise(){
    byte[] result=new byte[100];
    // copy a frame's worth of data (or remaining data if it is less than frame length)
    int read=Math.min(err_data.length-err_pstn, 100);
    System.arraycopy(err_data, err_pstn, result, 0, read);
    // if read data is less than frame length, reset position and add remaining data
    if(read<100){
        err_pstn=100-read;
        System.arraycopy(err_data, 0, result, read, err_pstn);
    }else // otherwise, increase position
        err_pstn+=100;
    // return noise segment
    return result;
}

/**
 * Given some original data, it is purposefully corrupted according to a
 * second data array (which is read from a file). In pseudocode:
 * corrupt = original xor corruptor
 * @param data The original data.
 * @return The new (corrupted) data.
 */
public static byte[] corruptData(byte[] data){
    // get the next noise sequence
    byte[] noise = nextNoise();
    // finally, xor data with noise and return result
    for(int i=0; i<100; i++)data[i]^=noise[i];
    return data;
}

/**
 * Given an array of data, a packet is created. In pseudocode:
 * frame = corrupt(data) + crc(data)
 * @param data The original frame data.
 * @return The resulting frame data.
 */
public static byte[] buildFrame(byte[] data){
    // pack = [data]+crc32([data])
    byte[] hash = new byte[8];
    // calculate crc32 of data and copy it to byte array
    CRC32 crc = new CRC32();
    crc.update(data);
    hash=toByta(crc.getValue());
    // create a byte array holding the final packet
    byte[] pack = new byte[data.length+hash.length];
    // create the corrupted data
    byte[] crpt = new byte[data.length];
    crpt = corruptData(data);
    // copy corrupted data into pack
    System.arraycopy(crpt, 0, pack, 0, crpt.length);
    // copy hash into pack
    System.arraycopy(hash, 0, pack, data.length, hash.length);
    // return pack
    return pack;
}

/**
 * Verifies frame contents.
 * @param frame The frame data (data+crc32).
 * @return True if frame is valid, false otherwise.
 */
public static boolean verifyFrame(byte[] frame){
    // allocate hash and data variables
    byte[] hash=new byte[8];
    byte[] data=new byte[frame.length-hash.length];
    // read frame into hash and data variables
    System.arraycopy(frame, frame.length-hash.length, hash, 0, hash.length);
    System.arraycopy(frame, 0, data, 0, frame.length-hash.length);
    // get crc32 of data
    CRC32 crc = new CRC32();
    crc.update(data);
    // compare crc32 of data with crc32 of frame
    return crc.getValue()==toLong(hash);
}

/**
 * Transfers a file through a channel in frames and reconstructs it into a new file.
 * @param jpg_file File name of target file to transfer.
 * @param err_file The channel noise file used to simulate corruption.
 * @param out_file The name of the newly-created file.
 * @throws IOException
 */
public static void transferFile(String jpg_file, String err_file, String out_file) throws IOException {
    // read file data into global variables
    jpg_data = readFileArray(new File(jpg_file));
    err_data = readFileArray(new File(err_file));
    err_pstn = 0;
    // variable that will hold the final (transfered) data
    byte[] out_data = new byte[jpg_data.length];
    // holds the current frame data
    byte[] frame_orig = new byte[100];
    byte[] frame_sent = new byte[100];
    // send file in chunks (frames) of 100 bytes
    for(int i=0; i<Math.ceil(jpg_data.length/100); i++){
        // copy jpg data into frame and init first-time switch
        System.arraycopy(jpg_data, i*100, frame_orig, 0, 100);
        boolean not_first=false;
        System.out.print("Packet #"+i+": ");
        // repeat getting same frame until frame crc matches with frame content
        do {
            if(not_first)System.out.print("F");
            frame_sent=buildFrame(frame_orig);
            not_first=true;
        }while(!verifyFrame(frame_sent));   // usually, you'd constrain this by time to prevent infinite loops (in
                                            // case the channel is so wacked up it doesn't get a single packet right)
        // copy frame to image file
        System.out.println("S");
        System.arraycopy(frame_sent, 0, out_data, i*100, 100);
    }
    System.out.println("\nDone.");
    writeFileArray(new File(out_file),out_data);
}

// global variables for file data and pointer
public static byte[] jpg_data;
public static byte[] err_data;
public static int    err_pstn=0;

public static void main(String[] args) throws IOException {

    // list of jpg files
    String[] jpg_file={
        "C:\\Users\\Stefan\\Desktop\\Data\\Images\\photo1.jpg",
        "C:\\Users\\Stefan\\Desktop\\Data\\Images\\photo2.jpg",
        "C:\\Users\\Stefan\\Desktop\\Data\\Images\\photo3.jpg",
        "C:\\Users\\Stefan\\Desktop\\Data\\Images\\photo4.jpg"
    };

    // list of error patterns
    String[] err_file={
        "C:\\Users\\Stefan\\Desktop\\Data\\Error Pattern\\Error Pattern 1.DAT",
        "C:\\Users\\Stefan\\Desktop\\Data\\Error Pattern\\Error Pattern 2.DAT",
        "C:\\Users\\Stefan\\Desktop\\Data\\Error Pattern\\Error Pattern 3.DAT",
        "C:\\Users\\Stefan\\Desktop\\Data\\Error Pattern\\Error Pattern 4.DAT"
    };
    // loop through all jpg/channel combinations and run tests
    for(int x=0; x<jpg_file.length; x++){
        for(int y=0; y<err_file.length; y++){
            System.out.println("Transfering photo"+(x+1)+".jpg using Pattern "+(y+1)+"...");
            transferFile(jpg_file[x],err_file[y],jpg_file[x].replace("photo","CH#"+y+"_photo"));
        }
    }

}

}

© Stack Overflow or respective owner

Related posts about java

Related posts about image