/*
* PSXperia Converter Tool - PSImage Extraction
* Copyright (C) 2011 Yifan Lu (http://yifan.lu/)
*
* 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/>.
*/
package com.yifanlu.PSXperiaTool;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
public class PSImageExtract extends PSImage {
public PSImageExtract(InputStream in) {
super(in);
}
public void uncompress(OutputStream out) throws IOException, DataFormatException {
Logger.info("Extracting PS Image [BETA! This tool WILL return with an exception, even if successful].");
check();
mIn.skip(HEADER.length);
mBytesRead = HEADER.length;
mBytesWritten = 0;
Inflater inf = new Inflater();
int n;
byte[] buff = new byte[BLOCK_SIZE];
try
{
while ((n = inf.inflate(buff, 0, BLOCK_SIZE)) != -1) {
out.write(buff, 0, n);
addBytesWritten(n);
if (inf.finished() || inf.needsDictionary()) {
int remainder = inf.getRemaining();
changeBuffer(remainder);
inf.reset();
inf.setInput(mBuff, 0, remainder);
} else if (inf.needsInput()) {
fill(inf);
}
}
}catch(DataFormatException ex){
out.write(new byte[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15});
out.write(mBuff);
byte[] b = new byte[1024];
mIn.read(b);
out.write(b);
out.close();
throw ex;
}
Logger.debug("Extraction done.");
}
protected void fill(Inflater inf) throws IOException {
Logger.verbose("Filling buffer with compressed data.");
if (mBuff.length < BLOCK_SIZE)
mBuff = new byte[BLOCK_SIZE];
int n = mIn.read(mBuff, 0, BLOCK_SIZE);
if (n == -1) {
throw new IOException("Unexpected end of ZLIB input stream");
}
inf.setInput(mBuff, 0, BLOCK_SIZE);
addBytesRead(n);
}
protected void changeBuffer(int remaining) throws IOException {
Logger.verbose("End of segment, shifting buffer and trying next segment.");
int bs = mBuff.length;
byte[] newBuff = new byte[remaining];
int i, j;
i = bs - remaining;
j = 0;
while (i < bs) {
newBuff[j++] = mBuff[i++];
}
mBuff = newBuff;
}
}