Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

jpeg.c

Go to the documentation of this file.
00001 /*===========================================================================*
00002  * jpeg.c                                                                    *
00003  *                                                                           *
00004  *      procedures to deal with JPEG files                                   *
00005  *                                                                           *
00006  * EXPORTED PROCEDURES:                                                      *
00007  *      JMovie2JPEG                                                          *
00008  *      ReadJPEG                                                             *
00009  *                                                                           *
00010  *===========================================================================*/
00011 
00012 /*
00013  * Copyright (c) 1995 The Regents of the University of California.
00014  * All rights reserved.
00015  *
00016  * Permission to use, copy, modify, and distribute this software and its
00017  * documentation for any purpose, without fee, and without written agreement is
00018  * hereby granted, provided that the above copyright notice and the following
00019  * two paragraphs appear in all copies of this software.
00020  *
00021  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
00022  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
00023  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
00024  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00025  *
00026  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
00027  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00028  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
00029  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
00030  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
00031  */
00032 
00033 /*  
00034  *  $Header: /misc/elrond0/share/cvs/AFNI/src/mpeg_encodedir/jpeg.c,v 1.4 2004/04/02 15:12:40 rwcox Exp $
00035  *  $Log: jpeg.c,v $
00036  *  Revision 1.4  2004/04/02 15:12:40  rwcox
00037  *  Cput
00038  *
00039  *  Revision 1.3  2003/12/23 13:50:08  rwcox
00040  *  Cput
00041  *
00042  *  Revision 1.2  2003/12/03 14:46:14  rwcox
00043  *  Cput
00044  *
00045  *  Revision 1.1  2001/12/17 16:11:54  rwcox
00046  *  Cadd
00047  *
00048  * Revision 1.6  1995/06/08  20:36:00  smoot
00049  * added "b"'s to fopen()s for MSDOS
00050  *
00051  * Revision 1.5  1995/02/02  21:24:02  eyhung
00052  * slight cleanup of unused variables
00053  *
00054  * Revision 1.4  1995/01/19  23:08:33  eyhung
00055  * Changed copyrights
00056  *
00057  * Revision 1.3  1995/01/19  22:58:34  smoot
00058  * fixes (I dont know what)
00059  *
00060  * Revision 1.2  1994/11/12  02:11:50  keving
00061  * nothing
00062  *
00063  * Revision 1.1  1994/03/15  00:27:11  keving
00064  * nothing
00065  *
00066  * Revision 1.2  1993/12/22  19:19:01  keving
00067  * nothing
00068  *
00069  * Revision 1.1  1993/07/22  22:23:43  keving
00070  * nothing
00071  *
00072  */
00073 
00074 
00075 /*==============*
00076  * HEADER FILES *
00077  *==============*/
00078 
00079 #include <stdio.h>
00080 #include "all.h"
00081 #include "mtypes.h"
00082 #include "frames.h"
00083 #include "prototypes.h"
00084 #include "param.h"
00085 #include "readframe.h"
00086 #include "fsize.h"
00087 #include "rgbtoycc.h"
00088 #include "jpeg.h"
00089 
00090 /* make it happier.... */
00091 #undef DCTSIZE2
00092 #include "jpeg/jpeglib.h"
00093 
00094 
00095 #define HEADER_SIZE 607   /*JFIF header size used on output images*/
00096 
00097 
00098 
00099 /*=======================================================================*
00100  *                                                                       *
00101  * JMovie2JPEG                                                           *
00102  *                                                                       *
00103  *      Splits up a Parallax J_Movie into a set of JFIF image files      *
00104  *                                                                       *
00105  * RETURNS:     nothing                                                  *
00106  *                                                                       *
00107  * SIDE EFFECTS:    none                                                 *
00108  *                                                                       *
00109  *   Contributed By James Boucher(jboucher@flash.bu.edu)                 *
00110  *               Boston University Multimedia Communications Lab         *
00111  * This code was adapted from the Berkeley Playone.c and Brian Smith's   *
00112  * JGetFrame code after being modified on 10-7-93 by Dinesh Venkatesh    *
00113  * of BU.                                                                *
00114  *       This code converts a version 2 Parallax J_Movie into a          *
00115  * set of JFIF compatible JPEG images. It works for all image            *
00116  * sizes and qualities.                                                  *
00117  ************************************************************************/
00118 void
00119   JMovie2JPEG(infilename,obase,start,end)
00120 char *infilename;       /* input filename string */
00121 char *obase;            /* output filename base string=>obase##.jpg */ 
00122 int start;              /* first frame to be extracted */
00123 int end;                /* last frame to be extracted */
00124 {
00125   FILE *inFile;                 /* Jmovie file pointer */
00126   FILE *outFile;                /* JPEG file pointer for output file */
00127   int fd, i;                    /* input file descriptor and a counting variable*/
00128   char ofname[256];             /* output filename string */
00129   int Temp = 0, temp = 0;       /* dummy variables */
00130   int image_offset = 0;         /* counting variable */
00131   /* J_Movie header infomation */
00132   int ver_no;                   /* version number - expected to be 2 */
00133   int fps;                      /* frame rate - frames per second */
00134   int no_frames;                /* total number of frames in jmovie */
00135   int bandwidth;                /* bandwidth required for normal playback*/
00136   int qfactor;                  /* quality factor used to scale Q matrix */
00137   int mapsize;                  /* number of color map entries - 2^24 */
00138   int audio_tracks;             /* number of audio tracks ==1    */
00139   int audiosize;                /*number of bytes in audio tracks */
00140   int *inoffsets;               /* input frame offsets from start of jmovie*/
00141   int width;                    /* image width */
00142   int height;                   /* image height */
00143   int size;                     /* total image size in bytes */
00144   char op_code;                 /* jmovie op_code */
00145   char jpeg_size[4];            /* jpeg data size */
00146   static char junk[1000];       /* data sink for audio data */
00147 
00148   /* The next array represents the default JFIF header for
00149      quality = 100 and size = 320x240. The values are
00150      adjusted as the J_Movie header is read.  The default
00151      size of this array is set large so as to make room
00152      for the appending of the jpeg bitstream. It can be
00153      made smaller if you have a better idea of its expected size*/
00154   static char inbuffer[300000] = {    
00155     0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46,  
00156     0x49, 0x46, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01,
00157     0x00, 0x01, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x11,  
00158     0x08, 0x00, 0xF0, 0x01, 0x40, 0x03, 0x01, 0x21,
00159     0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xFF,  
00160     0xDB, 0x00, 0x84, 0x00, 0x10, 0x0B, 0x0C, 0x0E,
00161     0x0C, 0x0A, 0x10, 0x0E, 0x0D, 0x0E, 0x12,  
00162     0x11, 0x10, 0x13, 0x18, 0x28, 0x1A, 0x18, 0x16,
00163     0x16, 0x18, 0x31, 0x23, 0x25, 0x1D, 0x28, 0x3A,  
00164     0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38, 0x37, 0x40,
00165     0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57, 0x45, 0x37,  
00166     0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F, 0x62, 0x67,
00167     0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79, 0x70, 0x64,  
00168     0x78, 0x5C, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12,
00169     0x12, 0x18, 0x15, 0x18, 0x2F, 0x1A, 0x1A, 0x2F,  
00170     0x63, 0x42, 0x38, 0x42, 0x63, 0x63, 0x63, 0x63,
00171     0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,  
00172     0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,  
00173     0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,  
00174     0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,  
00175     0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,  
00176     0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0xFF, 0xC4,
00177     0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,  
00178     0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
00179     0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,  
00180     0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
00181     0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04,  
00182     0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01,
00183     0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05,  
00184     0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
00185     0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,  
00186     0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1,
00187     0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09,   
00188     0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26,
00189     0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37,  
00190     0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47,
00191     0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57,  
00192     0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,
00193     0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77,  
00194     0x78, 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87,
00195     0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96,  
00196     0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5,
00197     0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4,  
00198     0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3,
00199     0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2,  
00200     0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
00201     0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8,  
00202     0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6,
00203     0xF7, 0xF8, 0xF9, 0xFA, 0x01, 0x00, 0x03, 0x01,  
00204     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
00205     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,  
00206     0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 
00207     0x0A, 0x0B, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04,  
00208     0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00,
00209     0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11,  
00210     0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51,
00211     0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08,  
00212     0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23,
00213     0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1,   
00214     0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17,
00215     0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,  
00216     0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
00217     0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54,  
00218     0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64,
00219     0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74,  
00220     0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83,
00221     0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92,  
00222     0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A,
00223     0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9,  
00224     0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
00225     0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,  
00226     0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
00227     0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5,  
00228     0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4,
00229     0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0xDA,  
00230     0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03,
00231     0x11, 0x00, 0x3F, 0x00  
00232 
00233     };
00234     
00235   if(start > end)
00236     {
00237       fprintf(stderr,"bad frame numbers\n");
00238       exit(1);
00239     }
00240     
00241   /* open J_Movie */
00242   inFile = fopen(infilename, "rb");
00243   if (inFile == NULL) 
00244     {
00245       perror (infilename);
00246       exit (1);
00247     }
00248     
00249   /* get file descriptor */    
00250   fd = fileno(inFile);
00251     
00252   /* The following lines parse the jpeg_movie header and recover the */
00253   /* relavant information */
00254 
00255   fseek (inFile, (8*sizeof(char)),0);
00256     
00257   if (fread (&ver_no,sizeof(int),1,inFile) != 1)
00258     {
00259       perror("Error in reading version");
00260       exit(1);
00261     }  
00262   if(ver_no != 2){
00263     perror("Unrecognized version - Quantization tables may be wrong\n");
00264   }
00265   if (fread (&(fps),sizeof(int),1,inFile) != 1)
00266     {
00267       perror("Error in reading fps");
00268       exit(1);
00269     }  
00270   if (fread (&(no_frames),sizeof(int),1,inFile) != 1)
00271     {
00272       perror("Error in reading no_frames");
00273       exit(1);
00274     }  
00275 
00276   inoffsets = (int *)malloc(no_frames*sizeof(int));
00277     
00278   if (fread (&(width),sizeof(int),1,inFile) != 1)
00279     {
00280       perror("Error in reading width");
00281       exit(1);
00282     }  
00283   /* set image width in JFIF header */
00284   inbuffer[27] = (char)(0xFF & (width >> 8));
00285   inbuffer[28] = (char)(0xFF & width);
00286  
00287   if (fread (&(height),sizeof(int), 1,inFile) != 1)
00288     {
00289       perror("Error in reading height");
00290       exit(1);
00291     }  
00292   /* set image height in JFIF header */
00293   inbuffer[25] = (char)(0xFF & (height >> 8));
00294   inbuffer[26] = (char)(0xFF & height);
00295     
00296   if (fread (&(bandwidth),sizeof(int),1,inFile) != 1)
00297     {
00298       perror("Error in reading bandwidth");
00299       exit(1);
00300     }  
00301     
00302   if (fread (&(qfactor),sizeof(int),1,inFile) != 1)
00303     {
00304       perror("Error in reading qfactor");
00305       exit(1);
00306     }  
00307   /* The default quality factor = 100, therefore, if
00308      our quality factor does not equal 100 we must
00309      scale the quantization matrices in the JFIF header*/    
00310   /* Note values are clipped to a max of 255 */
00311   if(qfactor != 100){
00312     for(Temp=44;Temp<108;Temp++){
00313       temp= (inbuffer[Temp]*qfactor)/100;
00314       inbuffer[Temp] = (char)((temp<255) ? temp : 255);
00315     }
00316     for(Temp=109;Temp<173;Temp++){
00317       temp = (inbuffer[Temp]*qfactor)/100;
00318       inbuffer[Temp] = (char)((temp<255) ? temp : 255);
00319     }    
00320   }
00321   
00322   if (fread (&(mapsize),sizeof(int),1,inFile) != 1)
00323     {
00324       perror("Error in reading mapsize");
00325       exit(1);
00326     }  
00327   if (fread (&(image_offset),sizeof(int),1,inFile) != 1)
00328     {
00329       perror("Error in reading image offset");
00330       exit(1);
00331     }
00332   if (fread (&(audio_tracks),sizeof(int),1,inFile) != 1)
00333     {
00334       perror("Error in reading audio tracks");
00335       exit(1);
00336     }
00337     
00338   fread(junk,sizeof(int),1,inFile);
00339     
00340   if (fread (&(audiosize),sizeof(int),1,inFile) != 1)
00341     {
00342       perror("Error in reading audiosize");
00343       exit(1);
00344     }
00345     
00346   fseek (inFile,(image_offset),0);
00347     
00348 
00349   if(no_frames <= end)
00350     {
00351       end = no_frames - 1;
00352     }
00353     
00354 
00355   for(i=0;i<no_frames;i++) 
00356     {
00357       fread(&(inoffsets[i]),sizeof(int),1,inFile);
00358     } /* Reads in the frame sizes into the array */
00359     
00360   rewind(inFile);
00361 
00362   /* Extract JFIF files from J_Movie */    
00363   for (i=start; i<=end ; i++) 
00364     {
00365       size = inoffsets[i]- inoffsets[i-1]- 5;
00366       lseek(fd, inoffsets[i-1],0); 
00367       read(fd, &(op_code), 1);
00368       while( op_code !=  0xffffffec)
00369         {
00370           read(fd,junk,audiosize);
00371           read(fd, &(op_code), 1);  
00372           size = size - audiosize ;
00373         } /* To skip the audio bytes in each frame */
00374       read(fd,jpeg_size,4);
00375       read(fd,&(inbuffer[607]),(size));
00376       sprintf(ofname,"%s%d.jpg",obase,i);
00377       outFile = fopen(ofname, "wb");
00378       fwrite(inbuffer,(size+607),sizeof(char),outFile);
00379       fclose(outFile);        
00380     }
00381   free(inoffsets);
00382   fclose(inFile);
00383 }
00384 
00385 
00386 
00387 
00388 /*===========================================================================*
00389  *
00390  * ReadJPEG  contributed by James Arthur Boucher of Boston University's
00391  *                                Multimedia Communications Lab
00392  *
00393  *      read a JPEG file and copy data into frame original data arrays
00394  *
00395  * RETURNS:     mf modified
00396  *
00397  * SIDE EFFECTS:    none
00398  *
00399  *===========================================================================*/
00400 /*************************JPEG LIBRARY INTERFACE*********************/
00401 /*
00402  * THE BIG PICTURE:
00403  *
00404  * The rough outline this JPEG decompression operation is:
00405  *
00406  *      allocate and initialize JPEG decompression object
00407  *      specify data source (eg, a file)
00408  *      jpeg_read_header();     // obtain image dimensions and other parameters
00409  *      set parameters for decompression
00410  *      jpeg_start_decompress();
00411  *      while (scan lines remain to be read)
00412  *              jpeg_read_scanlines(...);
00413  *      jpeg_finish_decompress();
00414  *      release JPEG decompression object
00415  *
00416  */
00417 void
00418 ReadJPEG(mf, fp)
00419     MpegFrame *mf;
00420     FILE *fp;
00421 {
00422 
00423   /* This struct contains the JPEG decompression parameters and pointers to
00424    * working data (which is allocated as needed by the JPEG library).
00425    */
00426   static struct jpeg_decompress_struct cinfo;
00427   struct jpeg_error_mgr jerr;
00428   /* More stuff */
00429   JSAMPARRAY scanarray[3];
00430   int ci,cd,cp;
00431   JDIMENSION ncols[3];
00432   JDIMENSION nrows[3];
00433   jpeg_component_info *compptr;
00434   int buffer_height;
00435   int current_row[3];
00436   uint8 **orig[3];
00437   int h_samp[3],v_samp[3];
00438   int max_h_samp,max_v_samp;
00439   int temp_h, temp_v;
00440   int temp;
00441 
00442   /* Allocate and initialize JPEG decompression object */
00443    cinfo.err = jpeg_std_error(&jerr);
00444 
00445   /*
00446   ** If we're reading from stdin we want to create the cinfo struct
00447   ** ONCE (during the first read).  This is because when reading jpeg
00448   ** from stdin we will not release the cinfo struct, because doing
00449   ** so would totally screw up the read buffer and make it impossible
00450   ** to read jpegs from stdin.
00451   ** Dave Scott (dhs), UofO, 7/19/95
00452   */
00453   {
00454     static int first_stdin = 1;
00455     if( (fp != stdin) || first_stdin)
00456       {
00457         first_stdin = 0;
00458         /* Now we can initialize the JPEG decompression object. */
00459         jpeg_create_decompress(&cinfo);
00460         /* specify data source (eg, a file) */
00461         jpeg_stdio_src(&cinfo, fp);
00462       }
00463   }
00464   
00465   /* specify data source (eg, a file) */
00466   
00467   jpeg_stdio_src(&cinfo, fp);
00468   
00469   /* read file parameters with jpeg_read_header() */
00470   
00471   
00472   (void) jpeg_read_header(&cinfo, TRUE);
00473   /* We can ignore the return value from jpeg_read_header since
00474    *   (a) suspension is not possible with the stdio data source, and
00475    *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
00476    */
00477   
00478   /* set parameters for decompression */
00479 #ifdef JPEG4
00480   cinfo.want_raw_output = TRUE;
00481 #else
00482   cinfo.raw_data_out = TRUE;
00483 #endif
00484   cinfo.out_color_space = JCS_YCbCr;
00485   
00486   /* calculate image output dimensions */
00487   jpeg_calc_output_dimensions(&cinfo);
00488   /* the above calculation will set these soon */
00489   /* for now we'll set them ourselves */
00490   
00491   
00492   /* tell mpeg_encode the size of the JPEG Image*/
00493   Fsize_Note(mf->id,(int)(cinfo.image_width),(int)(cinfo.image_height));
00494   
00495   /* Allocate memory for the raw YCbCr data to occupy*/
00496   Frame_AllocYCC(mf);      /*allocate space for mpeg frame*/
00497   
00498   /* copy pointers to array structure- this make the following
00499      code more compact  */
00500   orig[0] = mf->orig_y;
00501   orig[1] = mf->orig_cb;
00502   orig[2] = mf->orig_cr;
00503   
00504   /* Note that we can use the info obtained from jpeg_read_header.
00505    */
00506   
00507   /* Start decompressor */
00508   
00509   jpeg_start_decompress(&cinfo);
00510   
00511   
00512   /* JSAMPLEs per row in output buffer  */
00513   /* collect component subsample values*/
00514   for(cp=0,compptr = cinfo.comp_info;cp<cinfo.num_components;
00515       cp++,compptr++) {
00516     h_samp[cp] = compptr->h_samp_factor;
00517     v_samp[cp] = compptr->v_samp_factor;
00518   }
00519   /* calculate max subsample values*/
00520   temp_h = (h_samp[0]<h_samp[1]) ? h_samp[1] : h_samp[0];
00521   max_h_samp = (temp_h<h_samp[2]) ? h_samp[2]:temp_h;
00522   temp_v = (v_samp[0]<v_samp[1]) ? v_samp[1] : v_samp[0];
00523   max_v_samp = (temp_v<v_samp[2]) ? v_samp[2]:temp_v;
00524   
00525   /* Make an 8-row-high sample array that will go away when done with image */
00526 #ifdef JPEG4
00527   buffer_height = 8;  /* could be 2, 4,8 rows high */
00528 #else
00529   buffer_height = cinfo.max_v_samp_factor * cinfo.min_DCT_scaled_size;
00530 #endif
00531   
00532   for(cp=0,compptr = cinfo.comp_info;cp<cinfo.num_components;
00533       cp++,compptr++) {
00534     ncols[cp] = (JDIMENSION)((cinfo.image_width*compptr->h_samp_factor)/
00535                              max_h_samp);
00536     
00537     nrows[cp] = (JDIMENSION)((buffer_height*compptr->v_samp_factor)/
00538                              max_v_samp);
00539     
00540     scanarray[cp] = (*cinfo.mem->alloc_sarray)
00541       ((j_common_ptr) &cinfo, JPOOL_IMAGE, ncols[cp], nrows[cp]);
00542     
00543   }
00544   
00545   
00546   /*  while (scan lines remain to be read) */
00547   /*           jpeg_read_scanlines(...); */
00548   
00549   /* Here we use the library's state variable cinfo.output_scanline as the
00550    * loop counter, so that we don't have to keep track ourselves.
00551    */
00552 
00553   while (cinfo.output_scanline < cinfo.output_height) {
00554 
00555 #ifdef JPEG4
00556     (void) jpeg_read_raw_scanlines(&cinfo, scanarray, buffer_height);
00557 #else
00558     (void) jpeg_read_raw_data(&cinfo, scanarray, buffer_height);
00559 #endif
00560 
00561 /* alter subsample ratio's if neccessary */
00562     if((h_samp[0]==2)&&(h_samp[1]==1)&&(h_samp[2]==1)&&
00563        (v_samp[0]==2)&&(v_samp[1]==1)&&(v_samp[2]==1)){
00564       /* we are 4:1:1 as expected by the encoder*/
00565     }else if((h_samp[0]==2)&&(h_samp[1]==1)&&(h_samp[2]==1)&&
00566              (v_samp[0]==1)&&(v_samp[1]==1)&&(v_samp[2]==1)){
00567       /* must subsample 2:1 vertically and adjust params*/
00568       for(ci=1; ci<3; ci++){
00569         for(cp=0; cp<(buffer_height/2);cp=cp+1){
00570           for(cd=0;cd<ncols[ci];cd++){
00571             temp =((scanarray[ci][cp*2][cd]+scanarray[ci][(cp*2)+1][cd])/2);
00572             scanarray[ci][cp][cd] = (JSAMPLE)(temp);
00573           }
00574         }
00575       }
00576       /* only reset values the first time through*/
00577       if(cinfo.output_scanline==buffer_height){
00578         nrows[1] = nrows[1]/2;
00579         nrows[2] = nrows[2]/2;
00580         max_v_samp = 2;
00581         v_samp[0] = 2;
00582       }
00583     }else{
00584       fprintf(stderr, "Not a supported subsampling ratio\n");
00585       exit(1);
00586     }
00587     
00588     /* transfer data from jpeg buffer to MPEG frame */
00589     /* calculate the row we wish to output into */
00590     for(ci=0,compptr=cinfo.comp_info;ci<cinfo.num_components;
00591         ci++,compptr++){
00592       current_row[ci] =((cinfo.output_scanline - buffer_height)*
00593                         (v_samp[ci])/max_v_samp);  
00594       
00595       jcopy_sample_rows(scanarray[ci],0,(JSAMPARRAY)(orig[ci]),
00596                         current_row[ci],nrows[ci],ncols[ci]);
00597     }
00598     
00599   }  
00600   
00601   /* Step 7: Finish decompression */
00602   
00603   (void) jpeg_finish_decompress(&cinfo);
00604   /* We can ignore the return value since suspension is not possible
00605    * with the stdio data source.
00606    */
00607   
00608   /* Step 8: Release JPEG decompression object */
00609   
00610   /*
00611    ** DO NOT release the cinfo struct if we are reading from stdin, this
00612    ** is because the cinfo struct contains the read buffer, and the read
00613    ** buffer may (and almost always does) contain the end of one image and
00614    ** the beginning of another.  If we throw away the read buffer then
00615    ** we loose the beginning of the next image, and we're screwed.
00616   ** Dave Scott (dhs), UofO, 7/19/95
00617   */
00618   if( fp == stdin) {
00619     static int no_from_stdin = 0;
00620     no_from_stdin++;
00621     /* fprintf( stderr, "%d jpeg images read from stdin\n", no_from_stdin); */
00622   }
00623   else {
00624     /* This is an important step since it will release a good deal of memory. */
00625     jpeg_destroy_decompress(&cinfo);
00626   }
00627 
00628   /* After finish_decompress, we can close the input file.
00629    * Here we postpone it until after no more JPEG errors are possible,
00630    * so as to simplify the setjmp error logic above.  (Actually, I don't
00631    * think that jpeg_destroy can do an error exit, but why assume anything...)
00632    */
00633   
00634   
00635   /* At this point you may want to check to see whether any corrupt-data
00636    * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
00637    * If you prefer to treat corrupt data as a fatal error, override the
00638    * error handler's emit_message method to call error_exit on a warning.
00639    */
00640 
00641   /* And we're done! */
00642   
00643 }
00644 
00645 
00646 /*
00647  * SOME FINE POINTS:
00648  *
00649  * In the above loop, we ignored the return value of jpeg_read_scanlines,
00650  * which is the number of scanlines actually read.  We could get away with
00651  * this for the same reasons discussed in the compression example.  Actually
00652  * there is one perfectly normal situation in which jpeg_read_scanlines may
00653  * return fewer lines than you asked for: at the bottom of the image.  But the
00654  * loop above can't ask for more lines than there are in the image since it
00655  * reads only one line at a time.
00656  *
00657  * In some high-speed operating modes, some data copying can be saved by
00658  * making the buffer passed to jpeg_read_scanlines be cinfo.rec_outbuf_height
00659  * lines high (or a multiple thereof).  This will usually be 1, 2, or 4 lines.
00660  *
00661  * To decompress multiple images, you can repeat the whole sequence, or you
00662  * can keep the JPEG object around and just repeat steps 2-7.  This will
00663  * save a little bit of startup/shutdown time.
00664  *
00665  * As with compression, some operating modes may require temporary files.
00666  * On some systems you may need to set up a signal handler to ensure that
00667  * temporary files are deleted if the program is interrupted.
00668  *
00669  * Scanlines are returned in the same order as they appear in the JPEG file,
00670  * which is standardly top-to-bottom.  If you must have data supplied
00671  * bottom-to-top, you can use one of the virtual arrays provided by the
00672  * JPEG memory manager to invert the data.  See wrrle.c for an example.
00673  */
 

Powered by Plone

This site conforms to the following standards: