问题
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);
}
}
}
回答1:
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.
来源:https://stackoverflow.com/questions/38418111/unable-to-encode-a-tiff-file-properly-some-characters-are-not-encoding