/* * 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 2 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 . */ #include "Config.h" #include #include #include #include "FilterPredictor.h" #include "Utils.h" #include "Object.h" #include "Parser.h" #include "core/memcheck.h" using namespace merge_lib; const std::string FilterPredictor::PREDICTOR_TOKEN = "/Predictor"; const std::string FilterPredictor::DECODE_PARAM_TOKEN = "/DecodeParms"; const std::string COLUMNS_TOKEN = "/Columns"; const std::string COLORS_TOKEN = "/Colors"; const std::string BITS_TOKEN = "/BitsPerComponent"; const std::string EARLY_TOKEN = "/EarlyChange"; const std::string DICT_START_TOKEN = "<<"; const std::string DICT_END_TOKEN = ">>"; FilterPredictor::FilterPredictor(): _predictor(1), _colors(1), _bits(8), _columns(1), _earlyChange(1) { } FilterPredictor::~FilterPredictor() { } bool FilterPredictor::encode(std::string & decoded) { Q_UNUSED(decoded); return false; } std::string FilterPredictor::getDictionaryContentStr(std::string & in, size_t &pos ) { size_t beg = in.find(DICT_START_TOKEN,pos); if((int) beg == -1 ) { return ""; } beg += DICT_START_TOKEN.size(); size_t end = in.find(DICT_END_TOKEN,beg); if((int) end == -1 ) { return ""; } return in.substr(beg,end-beg); } void FilterPredictor::obtainDecodeParams(Object *objectWithStream, std::string &dictStr) { typedef std::map< std::string, int> DecodeParams; DecodeParams params; // set some initiaial values params[PREDICTOR_TOKEN] = _predictor; params[COLUMNS_TOKEN] = _columns; params[COLORS_TOKEN] = _colors; params[BITS_TOKEN] = _bits; params[EARLY_TOKEN] = _earlyChange; // lets parse the content of dictionary and set actual values into the map DecodeParams::iterator it = params.begin(); for(; it != params.end();it++) { size_t pos = dictStr.find((*it).first); if((int) pos != -1 ) { pos += (*it).first.size(); // we assume the following pattern "/Colors 8" std::string numstr = objectWithStream->getNameSimpleValue(dictStr,(*it).first); if( numstr.empty() ) { std::cerr<<"Wrong value of "<<(*it).first<<"defined as "<getHeader(content); // we need to parse the header of file to obtain the decoder parameter size_t position = content.find(DECODE_PARAM_TOKEN); if((int) position != -1) { position += DECODE_PARAM_TOKEN.size(); std::string dictStr = getDictionaryContentStr(content,position); // trace_hex(dictStr.data(),dictStr.size()); obtainDecodeParams(objectWithStream,dictStr); } } } //----------------------------- // Function perorms decoding of one row of data. //----------------------------- bool FilterPredictor::decodeRow(const char *in,std::string & out,const std::string &prev,int curPrediction) { std::string dec(_bytesPerPixel,'\0'); dec.append(in,_rowLen); // the buffer to decode int start = _bytesPerPixel; int end = _bytesPerPixel + _rowLen; switch(curPrediction) { case 2: // TIFF predictor // to do, implement TIFF predictor std::cerr<<"TIFF predictor not yet implemented!\n"; return false; break; case 1: case 10: // PNG NONE prediction // nothing to do, take as is break; case 11: // PNG SUB on all raws for(int i = start;i>1)&0xFF)); dec[i] += average; } break; case 14: //PNG PAETH on all rows /*function PaethPredictor (a, b, c) ; a = left, b = above, c = upper left p := a + b - c ; initial estimate pa := abs(p - a) ; distances to a, b, c pb := abs(p - b) pc := abs(p - c) ; return nearest of a,b,c, ; breaking ties in order a,b,c. if pa <= pb AND pa <= pc then return a else if pb <= pc then return b else return c Paeth(x) + PaethPredictor(Raw(x-bpp), Prior(x), Prior(x-bpp)) */ for(int i = start;i= 10?true:false; int rowBits = _columns*_colors*_bits; _rowLen = (rowBits>>3) + (rowBits&7); _bytesPerPixel = (_colors * _bits + 7) >> 3; int rows = 0; if( isPNG ) { rows = content.size()/(_rowLen+1) + (content.size()% (_rowLen+1)); } else { rows = content.size()/(_rowLen) + (content.size()% (_rowLen) ); } int inSize = content.size(); std::string out = ""; if( inSize%(isPNG?_rowLen+1:_rowLen) != 0 ) { std::cerr<<"Warning : wrong PNG identation inSize "<