Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
164 views
in Technique[技术] by (71.8m points)

java - Unable to encode a tiff file properly, Some characters are not encoding

I have TIFF file which contains multiple images , I will need to loop through that TIFF file to extract the images seperately , I have used base64 encode, then used substring to seperate the images and used base64 decode to write in a filesystem, However only some images are able to extract.

Example : I have 7 Images in a tiff file but it extracted only 4 images.

So I have write the encoded data to a file and read that and I can only able to see the II* encode character as 4 places instead of 7 .. When I open the TIFF file using notedpad , I can see 7 II* . Please advise , the best method to do this.

I have tried to decode the ecoded file and it is correct, It has 7 II* , however in the ecoded file I can only see the 4 encoded(SUkq) value of II*.

I can't use the below code , as my TIFF file contains header part before the II* which will need to remove before I use the below method.

class

 public void  doitJAI() throws IOException {
    FileSeekableStream ss = new FileSeekableStream("D:\Users\Vinoth\workspace\image.tif");
    ImageDecoder dec = ImageCodec.createImageDecoder("tiff", ss, null);
    int count = dec.getNumPages();
    TIFFEncodeParam param = new TIFFEncodeParam();
   param.setCompression(TIFFEncodeParam.COMPRESSION_GROUP4);   
    param.setLittleEndian(false); // Intel
    System.out.println("This TIF has " + count + " image(s)");
    for (int i = 0; i < count; i++) {
        RenderedImage page = dec.decodeAsRenderedImage(i);
        File f = new File("D:\Users\Vinoth\workspace\single_" + i + ".tif");
        System.out.println("Saving " + f.getCanonicalPath());
        ParameterBlock pb = new ParameterBlock();
        pb.addSource(page);
        pb.add(f.toString());
        pb.add("tiff");
        pb.add(param);
        RenderedOp r = JAI.create("filestore",pb);
        r.dispose();
    }
}

so Im using the below code , this is just to extract the first image .

Class

public class SplitTIFFFile {

public static void main(String[] args) throws IOException {
    new SplitTIFFFile().doitJAI();
}

File file = new File("D:\Users\Vinoth\workspace\Testing\image.tif");

    try {

                FileOutputStream imageOutFile;
                /*imageOutFile*/ try ( /*
                 * Reading a Image file from file system
                 */ FileInputStream imageInFile = new FileInputStream(file)) {
                    byte imageData[] = new byte[(int)file.length()];
                    imageInFile.read(imageData);
                    /*
                    * Converting Image byte array into Base64 String
                    */
                    String imageDataString = encodeImage(imageData);
                    String result = imageDataString.substring(imageDataString.indexOf("SUkq") , imageDataString.indexOf("SUkq"));
                    /*
                    * Converting a Base64 String into Image byte array
                    */
                    byte[] imageByteArray = decodeImage(result);

                    /*
                     * Write a image byte array into file system
                     */
                    imageOutFile = new FileOutputStream("D:\Users\Vinoth\workspace\Testing\image_converted_Vinoth_2.jpg");
                    imageOutFile.write(imageByteArray);
                }
        imageOutFile.close();

        System.out.println("Image Successfully Manipulated!");
    }

            catch (FileNotFoundException e) {
        System.out.println("Image not found" + e);
    } catch (IOException ioe) {
        System.out.println("Exception while reading the Image " + ioe);
    }

}

/**
 * Encodes the byte array into base64 string
 * @param imageByteArray - byte array
 * @return String a {@link java.lang.String}
 */
public static String encodeImage(byte[] imageByteArray){        
    return Base64.encodeBase64URLSafeString(imageByteArray);        
}

/**
 * Decodes the base64 string into byte array
 * @param imageDataString - a {@link java.lang.String} 
 * @return byte array
 */
public static byte[] decodeImage(String imageDataString) {      
    return Base64.decodeBase64(imageDataString);
}

}
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Simply do not use a conversion of byte[] to a Base64 String and then search "SUkq".

SUkq represent 3 bytes (ASCII II* = byte[] { 73, 73, 42 }), but when those same 3 bytes are shifted 1 or 2 positions, a totally different string happens, needing 5 letters.

The code with byte only:

    byte[] imageData = Files.readAllBytes(file.toPath());

    final byte[] soughtBytes = { 73, 73, 42 };
    int from = indexOf(imageData, soughtBytes, 0);
    from += soughtBytes.length;
    int to = indexOf(imageData, soughtBytes, from);
    if (to == -1) {
        throw new IllegalArgumentException();
    }
    byte[] imageByteArray = Arrays.copyOfRange(imageData, from, to);

    Path imageOutFile = Paths.get(
                "D:\Users\Vinoth\workspace\Testing\image_converted_Vinoth_2.jpg");
    Files.write(imageOutFile, imageByteArray);
}

static int indexOf(byte[] totalBytes, byte[] soughtBytes, int start) {
    for (int index = start; index <= totalBytes.length - soughtBytes.length; ++index) {
        boolean equal = true;
        for (int i = 0; i < soughtBytes.length; ++i) {
            if (totalBytes[index + i] != soughtBytes[i]) {
                equal = false;
                break;
            }
        }
        if (equal) {
            return index;
        }
    }
    return -1;
}

This saves the bytes between the first two "II*".

Not tested.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...