开发者

How to detect and convert progressive jpegs with python

I'd like to be able to detect progressive jpegs using python and convert them to non progressive.

(I'm writing a tool to manage images for android and p开发者_运维百科rogressive jpegs seem to break it.)


I apologise in advance for providing a php based answer, whereas the question was asked about python. Nevertheless, I think it adds value and can be useful. Before attempting to convert a progressive image to non-progressive, it is good to have a detection method for progressive Jpeg.

Here is the php function that does it, could easily be rewritten in other languages (python would be a candidate), as it reads binary data and Jpeg markers (and therefore does not rely on language specific library)

    public function checkProgressiveJPEG($filepath) {
    $result = false;
    // $this->log = 'started analysis...';

    // http://en.wikipedia.org/wiki/Jpeg 
    // for more details on JPEG structure

    // SOI  [0xFF, 0xD8] = Start Of Image
    // SOF0 [0xFF, 0xC0] = Start Of Frame (Baseline DCT)
    // SOF2 [0xFF, 0xC2] = Start Of Frame (Progressive DCT)
    // SOS  [0xFF, 0xDA] = Start Of Scan

    if(file_exists($filepath)) {
        $fs = @fopen($filepath, "rb");

        $bytecount = 0;
        $byte_last = 0;
        $buffer = 0;
        $buffer_length = 4*1024;
        $begins_with_SOI = false;

        while($buffer = fread($fs, $buffer_length)) {

            // always carry over previous ending byte
            // just in case the buffer is read after a 0xFF marker
            if($byte_last) {
                $buffer = $byte_last.$buffer;
            }
            $byte_last = 0;
            preg_match("/\.$/", $buffer, $matches); 
            if(count($matches)) { 
                $byte_last = $matches[0];
            }

            // check if it begins with SOI marker
            if(!$begins_with_SOI) {
                preg_match("/^\\xff\\xd8/", $buffer, $matches); 
                if(count($matches)) { 
                    $begins_with_SOI = true;
                } else {
                    // $this->log = 'does not start with SOI marker';
                    $result = false;
                    break;
                }
            }

            // check if SOS or SOF2 is reached
            preg_match("/\\xff(\\xda|\\xc2)/", $buffer, $matches); 
            if(count($matches)) {
                if(bin2hex($matches[0]) == 'ffda') {
                    // $this->log = 'SOS is reached and SOF2 has not been detected, so image is not progressive.';
                    $result = false;
                    break;
                } else if(bin2hex($matches[0]) == 'ffc2') {
                    // $this->log = 'SOF2 is reached, so image is progressive.';
                    $result = true;
                    break;
                }

            } 
        } // end while

        fclose($fs);
    } // end if
    return $result;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜