现在的位置: 首页 > 综合 > 正文

J2ME经验总结之JPEGDecoder

2013年02月03日 ⁄ 综合 ⁄ 共 12768字 ⁄ 字号 评论关闭

作者:hunhun1981
出自:http://blog.csdn.net/hunhun1981/

最近的项目提出一个直接读取手机中图片的需求。

但是一般手机上J2ME能使用的内存并不大,而拍出来的图却不小。我在多个真机上测试,结果都是OutOfMemory。只有一些高端机能够承受。

好在,我们的项目是一个对图像进行解码的算法。目的是从图片中获取像素颜色信息。于是我想到了使用流读取图片,直接对流中的数据进行解码并获取信息,无需构造图片对象。

于是,我从网上找到了这个JPEG解码器(PNG的以后再说吧),准备对它进行改造,然后从流中获取对我们算法的关键数据。

下面是JEPGDecoder的源代码,仅供大家学习和参考。并尊重原作者的劳动成果。

 

/* JPEGDecoder -- pure Java decoder for JPEG images
   Copyright (C) 2004 - Helmut Dersch  der@fh-furtwangen.de
   
   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, 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, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */

/////////////////////////////////////////////////////////////////////////

/* This decoder is based on C++-code for a Viewer ("JViewer") written and
   published by Bee-Chung Chen (
http://www.cs.wisc.edu/~beechung/home/coding/index.html).
   It is intended to be used with limited Java Runtimes not inluding
   JPEG decompression like the Java Microedition (J2ME) or gcj etc.

   Usage:
   ======
   
   (1) Implement the Interface "JPEGDecoder.PixelArray" with methods
       setSize(int width, int height) and setPixel(int x, int y, int argb).
       On a standard PC this could be just an Integer array (see example
       below), on a mobile device something more fancyful using RecordStores
       may be needed for large images (e.g. see my Panorama viewer 
       "PTViewerME" for PDAs).

   (2) Instantiate JPECDecoder: JPEGDecoder j = new JPEGDecoder();

   (3) Supply an InputStream in connecting to the image file
       and a PixelArray p, and start decoding:  j.decode(in,p);

   (4) Progress can be monitored by observing
       0 <= j.progress() <= 100

   (5) If space is scarce, destroy the decoder: j=null; System.gc();

   This is an example using standard JAVA (J2SE)     

   Example:
   ========

   // Simple JPEG-viewer using the pure JAVA JPEGDecoder
   // To run the viewer type "java Bild Filename"

   import java.awt.*;

   class Bild extends Frame implements Runnable, JPEGDecoder.PixelArray{
        Image im=null;
        Thread load;
        String file;
        JPEGDecoder j=null;

        // Implementation of PixelArray 

        int[] pix;
        int width,height;

        public void setSize(int width, int height){
            this.width = width;
            this.height = height;
            pix = new int[width*height];
        }

        public void setPixel(int x, int y, int argb){
            pix[x+y*width]=argb;
        }
        
        // Image viewer

    public static void main(String args[]){
            new Bild(args[0]);
    }

    public Bild(String s){
            file = s;
            j = new JPEGDecoder();
            load = new Thread(this);
            load.start();
         this.setTitle("Bild:" + s);
            this.resize(300,200);
        this.show();
            while(im == null){
               try{
                  Thread.sleep(1000);
               }catch(Exception e){}
               repaint();
            }
       }

       public void run(){
            try{
                FileInputStream in = new FileInputStream(file);                
                j.decode(in,this);
                in.close();
                MemoryImageSource mi = new MemoryImageSource(width,
                          height,
                          pix,
                          0,
                          width);
                im = createImage(mi);
                repaint();
            }catch(Exception e){
                System.out.println("Etwas ging schief: "+e);
            }    
    }

    public void paint(Graphics g){
                if(im != null){
                     g.drawImage(im,0,0,this);
                }else{
             g.drawString("Decodierung...",40,50);
                     if(j!=null)
                          g.drawString("Progress:..."+j.progress()+"%",40,70);
                }
    }
   }
     
   

--------------------------------------------------------------*/

////////////////////////////////////////////////////////////////

package PTViewer;

import java.io.*;

public class JPEGDecoder{
    
private int height;     

    // Private variables and constants
    private static final int  MSB = 0x80000000;
    
private static final int  MAX_HUFFMAN_SUBTREE = 50;   // max size = MAX_HUFFMAN_SUBTREE * 256
    private int nComp;                    //number of Components in a scan
    private int[] qTab[]  = new int[10][];//quantization table for the i-th Comp in a scan
    private int[] dcTab[] = new int[10][];//dc HuffTab for the i-th Comp in a scan
    private int[] acTab[] = new int[10][];//ac HuffTab for the i-th Comp in a scan
    private int nBlock[]  = new int[10];  //number of blocks in the i-th Comp in a scan
                                  
//                  i=0, ... ,Ns-1
    private int YH,YV,Xsize,Ysize;
    
private int marker ;
    
private int marker_index=0;
    
private int Ri = 0// RestartInterval

    
private int DU[][][]= new int[10][4][64];   //at most 10 data units in a MCU
                       
//at most 4 data units in one component 

    
private int x=0, y=0, num=0, yp=0// the begin point of MCU

    
private int IDCT_Source[]=new int[64];
    
private final static int IDCT_P[] ={
       
0,   5,  40,  16,  45,   2,   7,  42,
      
21,  56,   8,  61,  18,  47,   1,   4,
      
41,  23,  58,  13,  32,  24,  37,  10,
      
63,  17,  44,   3,   6,  43,  20,  57,
      
15,  34,  29,  48,  53,  26,  39,   9,
      
60,  19,  46,  22,  59,  12,  33,  31,
      
50,  55,  25,  36,  11,  62,  14,  35,
      
28,  49,  52,  27,  38,  30,  51,  54    
    } ;
    
private final static int table[] = {
        
0,    15,    6,    14,    15,    27,    28
        
2,    4,    7,    13,    16,    26,    29,    42,
        
3,    8,    12,    17,    25,    30,    41,    43,
        
9,    11,    18,    24,    31,    40,    44,    53,
        
1019233239455254,
        
2022333846515560,
        
2134374750565961,
        
3536484957586263
    };

    private FrameHeader       FH = new FrameHeader();
    
private ScanHeader        SH = new ScanHeader() ;
    
private QuantizationTable QT = new QuantizationTable();
    
private HuffmanTable      HT = new HuffmanTable();

    private void error(String message) throws Exception{
         
throw new Exception(message);
    }

    // Report progress in the range 0...100
    public int progress(){
         
if(height==0)
             
return 0;
         
if(yp>height) return 100;
         
return yp*100/height;
    }

    interface PixelArray{
        
public void setSize(int width, int height) throws Exception;
        
public void setPixel(int x, int y, int argb);
    }

    class ComponentSpec{
       
int C,  //Component id
           H,  //Horizontal sampling factor
           V,  //Vertical  ....
           Tq; //Quantization table destination selector
    }

    class FrameHeader{
           
int SOF,  //Start of frame in different type
               Lf,   //Length
               P,    //Sample Precision (from the orignal image)
               Y,    //Number of lines
               X,    //Number of samples per line
               Nf;   //Number of component in the frame

           ComponentSpec Comp[];  
//Components  C H V Tq

           
public int get(InputStream in, int sof) throws Exception{
           
//get data from file stream in
           
//return 0 : correct       otherwise : error

               
int i, temp, count=0, c;
               SOF
=sof;
               Lf
=get16(in); count+=2;
               P
=get8(in);   count++;
               Y
=get16(in);  count+=2;
               height
=Y;
               X
=get16(in);  count+=2;
               
//width=X;
               Nf=get8(in);  count++;
               Comp 
= new ComponentSpec[Nf+1];
               
for(i=0; i<=Nf; i++){ Comp[i]= new ComponentSpec();}
               
for(i=1; i<=Nf; i++){                 
                   
if(count>Lf){
                       error(
"ERROR: frame format error");
                   }
                   c
=get8(in);          count++;
                   
if(c>=Lf){
                       error(
"ERROR: fram format error [c>=Lf]");
                   }
                   Comp[c].C
=c;
                   temp
=get8(in);       count++;
                   Comp[c].H
=temp>>4;
                   Comp[c].V
=temp&0x0F;
                   Comp[c].Tq
=get8(in); count++;
               }
               
if(count!=Lf){
                   error(
"ERROR: frame format error [Lf!=count]");
               }
               
return 1;
           }
    }

    class ScanComponent{
           
int Cs,   //Scan component selector
               Td,   //DC table selector
               Ta;   //AC table selector
    }

    class ScanHeader{
          
int Ls,  //length
               Ns,  //Number of components in the scan
               Ss,  //Start of spectral or predictor selection
               Se,  //End of spectral selection
               Ah,  
               Al;
    
          ScanComponent Comp[]; 
//Components Cs Td Ta
                                
// from [0] to [Ns-1]
          int get(InputStream in) throws Exception{
             
//get data from file stream in
             
//return 0 : correct       otherwise : error

             
int i,temp,count=0;
             Ls
=get16(in);   count+=2;
             Ns
=get8(in);    count++;
             Comp 
= new ScanComponent[Ns];
             
for(i=0; i<Ns; i++){
                 Comp[i] 
= new ScanComponent();
                 
if(count>Ls){
                     error(
"ERROR: scan header format error");
                 }
                 Comp[i].Cs
=get8(in); count++;
                 temp
=get8(in);       count++;
                 Comp[i].Td
=temp>>4;
                 Comp[i].Ta
=temp&0x0F;
             }
             Ss
=get8(in);    count++;
             Se
=get8(in);    count++;
             temp
=get8(in);  count++;
             Ah
=temp>>4;
             Al
=temp&0x0F;
             
if(count!=Ls){
                 error(
"ERROR: scan header format error [count!=Ns]");
             }
             
return 1;
          }
    }

    class QuantizationTable{
          
int Lq,    //length
              Pq[]=new int[4], //Quantization precision 8 or 16
              Tq[]=new int[4]; //1: this table is presented
          int Q[][]=new int[4][64]; //Tables

          
public QuantizationTable(){
              Tq[
0]=0; Tq[1]=0; Tq[2]=0; Tq[3]=0;
          }

          int get(InputStream in) throws Exception{
              
//get data from file stream in
              
//return 0 : correct       otherwise : error

              
int i,count=0, temp, t;
              Lq
=get16(in); count+=2;
              
while(count<Lq){
                 temp
=get8(in);  count++;
                 t
=temp&0x0F;
                 
if(t>3){
                     error(
"ERROR: Quantization table ID > 3");
                 }
                 Pq[t]
=temp>>4;
                 
if(Pq[t]==0) Pq[t]=8;
                 
else if(Pq[t]==1) Pq[t]=16;
                 
else{
                     error(
"ERROR: Quantization table precision error");
                 }
                 Tq[t]
=1;
                 
if(Pq[t]==8){
                     
for(i=0; i<64; i++){
                          
if(count>Lq){
                               error(
"ERROR: Quantization table format error");
                          }
                          Q[t][i]
=get8(in); count++;
                     }
                     EnhanceQuantizationTable(Q[t]);
                 }
else{
                     
for(i=0; i<64; i++){
                          
if(count>Lq){
                             error(
"ERROR: Quantization table format error");
                          }
                          Q[t][i]
=get16(in); count+=2;
                     }
                     EnhanceQuantizationTable(Q[t]);
                 }
             }
             
if(count!=Lq){
                  error(
"ERROR: Quantization table error [count!=Lq]");
             }
             
return 1;
          }
    }

    class HuffmanTable{
          
int Lh,    //Length
              Tc[][]   = new int[4][2],   //1: this table is presented
              Th[]     = new int[4],      //1: this table is presented
              L[][][]  = new int[4][2][16],
              V[][][][]
= new int[4][2][16][200]; //tables

           
public HuffmanTable(){
              Tc[
0][0]=0; Tc[1][0]=0; Tc[2][0]=0; Tc[3][0]=0;
              Tc[
0][1]=0; Tc[1][1]=0; Tc[2][1]=0; Tc[3][1]=0;
              Th[
0]=0; Th[1]=0; Th[2]=0; Th[3]=0;
           }

           int get(InputStream in) 

抱歉!评论已关闭.