home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / MacDP 1.1.2 / JFIF-PICT.c next >
Encoding:
C/C++ Source or Header  |  1995-07-06  |  20.1 KB  |  923 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        JPEGtoPICT.c
  3.  
  4.     Written by:    Mark Krueger, Apple Computer, Inc.
  5.  
  6.     Contains:    Converts JPEG interchange files to JPEG PICT files, which can be used by any application.
  7.     
  8.     
  9.                 The JPEG File  Interchange Format ( JFIF) is a cross platform standard file format for
  10.                 storing JPEG compressed image files. This application shows you how you can easily convert
  11.                 these to QuickTime PICT format, or vice-verse. 
  12.                 
  13.                 You can use this in your application to open JFIF files directly or put a user interface 
  14.                 ( Drag and Drop would be cool ) on it to make a conversion program ). When files are to 
  15.                 be used on the Mac it is best to keep them in QTPict format so they can be easily copied
  16.                 and pasted, but JFIF format is useful for transfering data to other platforms that cannot
  17.                 use PICT formated JPEG images. 
  18.                 
  19.                 NOTE: the PICT to JFIF format translator is incomplete in that it only converts PICT
  20.                 files which are already in QuickTIme JPEG format and it does not handle banded JPEG
  21.                 Picts ( which may be commonly created by QuickTime applications which call 
  22.                 CompressPictureFile in low memory conditions or which create their own banded picts)
  23.                 To fully handle these images, the individual bands would have to be converted into a 
  24.                 single JPEG stream when put into JFIF format, and this code does not show you how
  25.                 to do that. 
  26.             
  27.     Modifications: November 19, 1994 by SPDsoft for MacDP 1.0
  28.  
  29.  
  30. */
  31.  
  32. #define SHOW_IT
  33.  
  34. #include    <GestaltEqu.h>
  35. #include    <ImageCompression.h>
  36.  
  37. /************************************************
  38.  *
  39.  *    Function prototypes.
  40.  *
  41.  ************************************************/
  42.  
  43.  
  44.  
  45. char *
  46. MarkerDetect(char *data,short *width,short *height,long *hRes,long *vRes,short *depth);
  47.  
  48. void 
  49. SwallowHuffTable(char *data);
  50.  
  51. void 
  52. SwallowQuantTable(char *data);
  53.  
  54. ImageDescriptionHandle
  55. ScanJPEG(short originalFile,Ptr *data,OpenCPicParams *pictureHeader);
  56.  
  57. PicHandle
  58. ConvertFromJFIF(StringPtr name,short originalFile, CWindowPtr window );
  59.  
  60. PicHandle
  61. ConvertFromPict(StringPtr name,short originalFile, CWindowPtr w);
  62.  
  63. pascal void
  64. StdPixExtract(PixMap *src,Rect *srcRect,MatrixRecord matrix,short mode,RgnHandle mask,PixMap *matte,
  65.     Rect *matteRect,short flags);
  66.     
  67. pascal void GetPICTData ( Ptr dataPtr, short byteCount);
  68.  
  69.  
  70. /************************************************
  71.  *
  72.  *    Convert a JFIF file to a PICT file.
  73.  *
  74.  ************************************************/
  75.  
  76.  
  77.  
  78. PicHandle
  79. ConvertFromJFIF(StringPtr name,short originalFile, CWindowPtr window)
  80. {
  81.     OSErr    result = 0;
  82.     short compressedFile = 0;
  83.     OpenCPicParams    header;
  84.     Str31        newName;
  85.     long        l;
  86.     short        i;
  87.     char        zero=0;
  88.     MatrixRecord matrix;
  89.  
  90.     Ptr            data = nil;
  91.     ImageDescriptionHandle    desc = nil;
  92.     PicHandle    originalPicture = nil;
  93.  
  94.     
  95.     /************************************************
  96.      *
  97.      *    Extract the JPEG data if possible and create Image Description.
  98.      *
  99.      ************************************************/
  100.  
  101.     if ( (desc=ScanJPEG(originalFile,&data,&header)) == 0 ) {
  102.         result = -50;
  103.         goto done;
  104.     }
  105.  
  106.     originalPicture = OpenCPicture(&header);
  107.         
  108.         
  109.     /************************************************
  110.      *
  111.      * we have to use the FDecompressImage call to make sure that the accuracy
  112.      * param gets set to highQuality which ensures a better quality decode
  113.      * and real dithering when going to 8-bit screens.
  114.      *
  115.      ************************************************/
  116.         
  117.         
  118.     SetIdentityMatrix(&matrix);
  119.     
  120. /*SysBeep(1);    */
  121.     if ( (result=FDecompressImage(data,desc,((CGrafPtr)qd.thePort)->portPixMap,
  122.             &header.srcRect,&matrix,ditherCopy,(RgnHandle)nil,
  123.             (PixMapHandle)nil,(Rect *)nil,codecHighQuality,anyCodec,0,
  124.             (ICMDataProcRecordPtr)nil,(ICMProgressProcRecordPtr)nil)) ){
  125.         ClosePicture();
  126.         KillPicture((PicHandle)originalPicture);
  127.         originalPicture = nil;
  128.         goto done;
  129.     }
  130. /*SysBeep(1);    */
  131.  
  132.     ClosePicture();
  133.     
  134.     if ( GetHandleSize((Handle)originalPicture) == sizeof(Picture) ) {
  135.         KillPicture((PicHandle)originalPicture);
  136.         originalPicture = nil;
  137.         goto done;
  138.     }
  139.  
  140.  
  141. done:    
  142.     FSClose(originalFile);
  143.  
  144. /*    if ( originalPicture )*/
  145. /*        KillPicture(originalPicture);*/
  146.  
  147.     if ( data )
  148.         DisposPtr(data);
  149.     if ( desc ) 
  150.         DisposHandle((Handle)desc);
  151.  
  152.     return originalPicture;
  153. }
  154.  
  155.  
  156. /************************************************
  157.  
  158.     Scan a file for valid JPEG data, and fill in a picture header and ImageDescription
  159.     for it.
  160.  
  161. *************************************************/
  162.  
  163. ImageDescriptionHandle
  164. ScanJPEG(short originalFile,Ptr *data,OpenCPicParams *pictureHeader)
  165.  
  166. {
  167.     short w,h;
  168.     ImageDescriptionHandle desc;
  169.     long    l;
  170.     char    *bitStream,*scanData,*buffer;
  171.     long    hRes = 72L<<16,vRes = 72L<<16;
  172.     short    depth = 32;
  173.     
  174.     GetEOF(originalFile,&l);
  175.     if ( (buffer= NewPtr(l)) == nil ) {
  176.         return(0);
  177.     }
  178.     FSRead(originalFile,&l,buffer);
  179.     bitStream = buffer;
  180.     
  181.     if ( (desc = (ImageDescriptionHandle)NewHandle(sizeof(ImageDescription))) == nil ) {
  182.         return(0);
  183.     }
  184.     if ( (scanData=MarkerDetect(bitStream,&w,&h,&hRes,&vRes,&depth)) == 0 ) {
  185.         return(0);
  186.     }
  187.     (*desc)->idSize = sizeof(ImageDescription);
  188.     (*desc)->width = w;
  189.     (*desc)->height = h;
  190.     (*desc)->temporalQuality = 0;
  191.     (*desc)->spatialQuality = codecNormalQuality;
  192.     (*desc)->dataSize = l;
  193.     (*desc)->cType = 'jpeg';
  194.     (*desc)->version = 0;
  195.     (*desc)->revisionLevel = 0;
  196.     (*desc)->vendor = 0;
  197.     (*desc)->hRes = hRes;
  198.     (*desc)->vRes = vRes;
  199.     (*desc)->depth = depth;
  200.     (*desc)->clutID = -1;
  201.     BlockMove("\pPhoto",(*desc)->name,6);
  202.     SetRect(&pictureHeader->srcRect,0,0,w,h);
  203.     pictureHeader->version = -2;
  204.     pictureHeader->reserved1 = 0;
  205.     pictureHeader->reserved2 = 0;
  206.     pictureHeader->hRes = hRes;
  207.     pictureHeader->vRes = vRes;
  208.     *data = bitStream;
  209.     return(desc);
  210. }
  211.  
  212.  
  213.  
  214. /**********************************************************************
  215.  
  216.     JPEG specific stuff.
  217.     
  218. ***********************************************************************/
  219.  
  220. /*
  221.  
  222.     JPEG Marker code definitions.
  223.     
  224. */
  225.  
  226. #define    MARKER_PREFIX    0xff
  227. #define    MARKER_SOI    0xd8        /* start of image */
  228. #define    MARKER_SOF    0xc0        /* start of frame */
  229. #define    MARKER_DHT    0xc4        /* define Huffman table */
  230. #define    MARKER_EOI    0xd9        /* end of image */
  231. #define    MARKER_SOS    0xda        /* start of scan */
  232. #define    MARKER_DQT    0xdb        /* define quantization tables */
  233. #define    MARKER_DNL    0xdc        /* define quantization tables */
  234. #define    MARKER_DRI    0xdd        /* define Huffman table */
  235. #define    MARKER_COM    0xfe        /* comment */
  236. #define MARKER_APP0    0xe0        
  237.  
  238.  
  239. /**********************************************************************
  240.  
  241.     Read the quantization table from the JPEG bitstream.
  242.     
  243. ***********************************************************************/
  244.  
  245. void 
  246. SwallowQuantTable(char *data)
  247. {
  248.     long    i;
  249.     long    length,pm,nm;
  250.  
  251.     length = *(short *)data;            /* read length */
  252.     length -= 2;
  253.     data += 2;
  254.     while ( length ) {
  255.         nm= *data++;                    /* read precision and number */
  256.         pm = nm>>4;    
  257.         nm &= 0xf;
  258.         length--;
  259.         if ( pm ) {
  260.             for(i=0;i<64;i++) {
  261.                 length -= 2;
  262.                 data += 2;
  263.             }
  264.         } else {
  265.             for(i=0;i<64;i++) {
  266.                 length--;
  267.                 data++;
  268.             }
  269.         }
  270.     }    
  271. }
  272.  
  273. /**********************************************************************
  274.  
  275.     Read the huffman table from the JPEG bitstream.
  276.     
  277. ***********************************************************************/
  278.  
  279. void 
  280. SwallowHuffTable(char *data)
  281. {
  282.     short    i,tc,id;
  283.     long    length;
  284.     
  285.     unsigned char    bin[17];
  286.     unsigned char    val[256];
  287.  
  288.     bin[0] = 0;
  289.     length = *(short *)data;            /* read length */
  290.     data += 2;
  291.     length -= 2;
  292.     while ( length ) {
  293.         id=*data++;                /* read id */
  294.         length--;
  295.         if ( id != 0 && id != 1 && id != 0x10 && id != 0x11) {
  296.             return;
  297.         }
  298.         tc = 0;
  299.         for(i=0;i<16;i++) {
  300.             length--;
  301.             tc += (bin[i+1] = *data++);
  302.         }
  303.         for (i=0; i < tc; i++ ) {
  304.             length--;
  305.             val[i] = *data++;
  306.         }
  307.     }
  308. }
  309.     
  310.     
  311.     
  312. /**********************************************************************
  313.  
  314.     Scan the JPEG stream for the proper markers and fill in the image parameters
  315.     
  316.     returns nil if it cant comprehend the data, otherwise a pointer to the start
  317.     of the JPEG data.
  318.     
  319.     
  320.     It does a cursory check on the JPEG data to see if it's reasonable.
  321.     Check out the ISO JPEG spec if you really want to know what's going on here.
  322.     
  323. ***********************************************************************/
  324.  
  325. char *
  326. MarkerDetect(char *data,short *width,short *height,long *hRes,long *vRes,short *depth)
  327. {
  328.     short    frame_field_length;
  329.     short    data_precision;
  330.     short    scan_field_length;
  331.     short    number_component,scan_components;
  332.     short    c1,hv1,q1,c2,hv2,q2,c3,hv3,q3;
  333.     short    dac_t1, dac_t2, dac_t3;
  334.     unsigned char    c;
  335.     short    qtabledefn;
  336.     short    htabledefn;
  337.     short    status;
  338.     short    length;
  339.     short    i;
  340.     
  341.     c = *data++;
  342.     qtabledefn = 0;
  343.     htabledefn = 0;
  344.     status = 0;
  345.     while (c != (unsigned char)MARKER_SOS) {
  346.         while (c != (unsigned char)MARKER_PREFIX)
  347.             c = *data++;                        /* looking for marker prefix bytes */
  348.         while (c == (unsigned char)MARKER_PREFIX)
  349.             c = *data++;                        /* (multiple?) marker prefix bytes */
  350.         if (c == 0)
  351.             continue;                                    /* 0 is never a marker code */
  352.  
  353.         if (c == (unsigned char)MARKER_SOF) {
  354.  
  355.             frame_field_length = *(short *)data;
  356.             data += 2;
  357.             data_precision = *data++;
  358.             
  359.             if ( data_precision != 8 ) { 
  360.                 status = 2;
  361.             }
  362.  
  363.             *height = *(short *)data;
  364.             data += 2;
  365.             *width = *(short *)data;
  366.             data += 2;
  367.                         
  368.             number_component = *data++;
  369.             
  370.             switch ( number_component  ) {
  371.             case 3:
  372.                 c1 = *data++;
  373.                 hv1 = *data++;
  374.                 q1 = *data++;
  375.                 c2 = *data++;
  376.                 hv2 = *data++;
  377.                 q2 = *data++;
  378.                 c3 = *data++;
  379.                 hv3 = *data++;
  380.                 q3 = *data++;
  381.                 *depth = 32;
  382.                 break;
  383.             case 1:        
  384.                 c1 = *data++;
  385.                 hv1 = *data++;
  386.                 q1 = *data++;
  387.                 *depth = 40;
  388.                 break;
  389.             default:
  390.                 status = 3;
  391.                 break;
  392.             }
  393.             continue;
  394.         }
  395.     
  396.         if (c == (unsigned char)MARKER_SOS) {
  397.             short tn;
  398.             scan_field_length = *(short *)data;
  399.             data += 2;
  400.             scan_components = *data++;
  401.             for ( i=0; i < scan_components; i++ ) {
  402.                 unsigned char cn,dac_t;
  403.                 
  404.                 cn = *data++;
  405.                 dac_t = *data++;
  406.                 if ( cn == c1 ) {
  407.                     dac_t1 = dac_t;
  408.                 } else if ( cn == c2 ) {
  409.                     dac_t2 = dac_t;
  410.                 } else if ( cn == c3 ) {
  411.                     dac_t3 = dac_t;
  412.                 } else {    
  413.                     status = 29;
  414.                     break;
  415.                 }
  416.             }
  417.             switch ( tn=(dac_t1 & 0xf) )  {
  418.             case 0:
  419.             case 1:
  420.                 break;
  421.             case 0xf:
  422.                 break;
  423.             default:
  424.                 status = 33;
  425.                 break;
  426.             }
  427.             switch (  tn=(dac_t2 & 0xf) )  {
  428.             case 0:
  429.             case 1:
  430.                 break;
  431.             case 0xf:
  432.                 break;
  433.             default:
  434.                 status = 33;
  435.                 break;
  436.             }
  437.             switch (  tn=(dac_t3 & 0xf) )  {
  438.             case 0:
  439.             case 1:
  440.                 break;
  441.             case 0xf:
  442.                 break;
  443.             default:
  444.                 status = 33;
  445.                 break;
  446.             }
  447.  
  448.  
  449.             /*  Initialize the DC tables */
  450.             
  451.             switch (  tn=dac_t1 & 0xf0 )  {
  452.             case 0:
  453.             case 0x10:
  454.                 break;
  455.             case 0xf0:
  456.                 break;
  457.             default:
  458.                 status = 34;
  459.                 break;
  460.             }
  461.             switch (  tn=dac_t2 & 0xf0 )  {
  462.             case 0:
  463.             case 0x10:
  464.                 break;
  465.             case 0xf0:
  466.                 break;
  467.             default:
  468.                 status = 34;
  469.                 break;
  470.             }
  471.             switch (  tn=dac_t3 & 0xf0 )  {
  472.             case 0:
  473.             case 0x10:
  474.                 break;
  475.             case 0xf0:
  476.                 break;
  477.             default:
  478.                 status = 34;
  479.                 break;
  480.             }
  481.             if ( *data++ != 0 )  {
  482. //                status = 18;
  483.             }
  484.             if ( *data++ != 63 )  {
  485. //                status = 19;
  486.             }
  487.             if ( *data++ != 0 ) {
  488. //                status = 20;
  489.             }
  490.             if ( status )
  491.                 return(0);
  492.             else
  493.                 return(data);
  494.         }
  495.  
  496.         if (c == (unsigned char)MARKER_DQT) {
  497.             scan_field_length = *(short *)data;
  498.             SwallowQuantTable(data);
  499.             data += scan_field_length;
  500.             continue;
  501.         }
  502.         if (c == (unsigned char)MARKER_DHT) {
  503.             scan_field_length = *(short *)data;
  504.             SwallowHuffTable(data);
  505.             continue;
  506.         }
  507.         if (c == (unsigned char)MARKER_DRI) {
  508.             length = *(short *)data;            /* read length */
  509.             data += 2;
  510.             length = *(short *)data;            
  511.             data += 2;
  512.             continue;
  513.         }
  514.         if (c == (unsigned char)MARKER_DNL) {
  515.             length = *(short *)data;            /* read length */
  516.             data += 2;
  517.             length = *(short *)data;            
  518.             data += 2;
  519.             continue;
  520.         }
  521.         if (c >= (unsigned char)0xD0 && c <= (unsigned char)0xD7) {
  522.             continue;
  523.         }
  524.  
  525.         if (c == (unsigned char)MARKER_SOI || c == (unsigned char)MARKER_EOI)    /* image start, end marker */
  526.             continue;
  527.  
  528.         if ( (c >= (unsigned char)0xC1 && c <= (unsigned char)0xcF) || (c == (unsigned char)0xde) || (c == (unsigned char)0xdf) ) {
  529.             status = 12;
  530.             length = *(short *)data;            /* read length */
  531.             data += length;
  532.             continue;
  533.         }
  534.         if (c >= (unsigned char)MARKER_APP0 && c <= (unsigned char)0xEF) {
  535.             length = *(short *)data;            /* read length */
  536.             data += 2;
  537.             length -= 2;
  538.             if ( (c == (unsigned char)MARKER_APP0) && length > 5 ) { /* check for JFIF marker */
  539.                 char buf[5];
  540.                 buf[0] = *data++;
  541.                 buf[1] = *data++;
  542.                 buf[2] = *data++;
  543.                 buf[3] = *data++;
  544.                 buf[4] = *data++;
  545.                 length -= 5;
  546.                 
  547.                 if ( buf[0] == 'J' && buf[1] == 'F'  && buf[2] == 'I'  && buf[3] == 'F' ) {
  548.                     short    units;
  549.                     long    xres,yres;
  550.                     short    version;
  551.                     
  552.                     
  553.                     version = *(short *)data; data += 2;length -= 2;
  554.  
  555. #ifdef strict_version_check                    
  556.                     if ( version != 0x100 && version != 0x101 ) {
  557.                         status = 44;        // unknown JFIF version
  558.                         break;
  559.                     }
  560. #else
  561.                     if ( version < 0x100 ) {
  562.                         status = 44;        // unknown JFIF version
  563.                         break;
  564.                     }
  565. #endif                    
  566.                     units = *data++; length--;
  567.                     xres = *(short *)data; data += 2; length -= 2;
  568.                     yres = *(short *)data; data += 2; length -= 2;
  569.  
  570.                     switch ( units ) {
  571.                     case 0:            // no res, just aspect ratio
  572.                         *hRes = FixMul(72L<<16,xres<<16);
  573.                         *vRes = FixMul(72L<<16,yres<<16);
  574.                         break;
  575.                     case 1:            // dots per inch
  576.                         *hRes = xres<<16;
  577.                         *vRes = yres<<16;
  578.                         break;
  579.                     case 2:            // dots per centimeter (we convert to dpi )
  580.                         *hRes = FixMul(0x28a3d,xres<<16);
  581.                         *vRes = FixMul(0x28a3d,xres<<16);
  582.                         break;    
  583.                     default:
  584.                         break;
  585.                     }
  586.                     xres = *data++; length--;
  587.                     yres = *data++; length--;
  588.                     
  589.                     /* skip JFIF thumbnail */
  590.                     
  591.                     xres *= yres;
  592.                     data += xres*3; length -= xres*3;
  593.                     
  594.                     if (  length != 0 ) {
  595.                         status = 44;        // bad jfif marker
  596.                         break;
  597.                     }
  598.                 }
  599.             }
  600.             data += length;
  601.             continue;
  602.         }
  603.         if (c == (unsigned char)MARKER_COM) {
  604.             length = *(short *)data;            /* read length */
  605.             data += length;
  606.             continue;
  607.         }
  608.         if (c >= (unsigned char)0xf0 && c <= (unsigned char)0xfd) {
  609.             length = *(short *)data;            /* read length */
  610.             data += length;
  611.             continue;
  612.         }
  613.         if ( c == 0x1 )
  614.             continue;
  615.         if ( (c >= (unsigned char)0x2 && c <= (unsigned char)0xbF) ) {
  616.             length = *(short *)data;            /* read length */
  617.             status = 13;
  618.             data += length;
  619.             continue;
  620.         }
  621.     }
  622.     return(0);
  623. }
  624.  
  625.  
  626.  
  627.  
  628.  
  629. short extractionFile;
  630. OSErr extractionErr;
  631. short globalRef;
  632.  
  633. PicHandle
  634. ConvertFromPict(StringPtr name,short originalFile,CWindowPtr w)
  635. {
  636.     CQDProcs    cprocs;
  637.     CQDProcsPtr savedprocs;
  638.     CGrafPtr    savePort;
  639.     OSErr        result = 0;
  640.     PicHandle    thePic = nil, OutPict = nil;
  641.     long        longCount,myEOF,filePos;
  642.     Rect        destRect;
  643.     long        hRes = 72L<<16,
  644.                 vRes = 72L<<16;
  645.     
  646.     OpenCPicParams    Header;
  647.         
  648.     GetPort((GrafPtr *) &savePort);
  649.     SetPort((GrafPtr) w);
  650.     globalRef = originalFile;
  651.     
  652.     
  653.     thePic = (PicHandle)NewHandle(sizeof(Picture));
  654.  
  655.     result = GetEOF(originalFile,&myEOF);
  656.     if (result != noErr) goto done;
  657.  
  658.     result = SetFPos(originalFile,fsFromStart,512);    /*skip header*/
  659.     if (result != noErr) goto done;
  660.  
  661.     longCount = sizeof(Picture);
  662.     result = FSRead(originalFile,&longCount,(Ptr)*thePic);
  663.     if (result != noErr) goto done;
  664.     
  665.     
  666.     BlockMove(&(*thePic)->picFrame, &destRect, sizeof(Rect));
  667.     BlockMove(&destRect, &(Header.srcRect), sizeof(Rect));
  668.     Header.version = -2;
  669.     Header.reserved1 = 0;
  670.     Header.reserved2 = 0;
  671.     Header.hRes = hRes;
  672.     Header.vRes = vRes;
  673.     
  674.     OutPict=OpenCPicture(&Header);
  675.     savedprocs = (CQDProcsPtr) qd.thePort->grafProcs;
  676.     
  677.         SetStdCProcs(&cprocs);
  678.         cprocs.getPicProc = GetPICTData;
  679. //        cprocs.newProc1 = (Ptr)StdPixExtract;
  680.         qd.thePort->grafProcs = (QDProcsPtr) &cprocs;
  681.         
  682.  
  683.         DrawPicture( thePic, &destRect);
  684.         
  685.     
  686.     qd.thePort->grafProcs = (QDProcsPtr) savedprocs;
  687.     ClosePicture();
  688.     
  689.     if (EmptyRect(&(*OutPict)->picFrame))
  690.     {
  691.         SysBeep(1);
  692.         result = 1;
  693.     }
  694.                 
  695. done:
  696.     FSClose(originalFile);
  697.  
  698.     if(thePic)
  699.         DisposHandle((Handle)thePic);
  700.     thePic=nil;
  701.     
  702.     if (result!=noErr)
  703.     {    
  704.         if(OutPict)
  705.             DisposHandle((Handle)OutPict);
  706.         OutPict=nil;
  707.     }
  708.     SetPort((GrafPtr)savePort);
  709.     return(OutPict);
  710. }
  711.  
  712.  
  713. /*replacement for the QuickDraw bottleneck routine*/
  714.  
  715. pascal void GetPICTData ( Ptr dataPtr, short byteCount)
  716. {
  717.     OSErr     err;
  718.     long     longCount;
  719.  
  720.     longCount = byteCount;
  721.     err = FSRead(globalRef,&longCount,dataPtr);
  722.         /*can't check for an error because we don't know how to handle it*/
  723. }
  724.  
  725.  
  726. /************************************************************************************
  727.  
  728.     bottle neck proc to extract data from quicktime pict
  729.     
  730. *************************************************************************************/
  731.  
  732.  
  733. pascal void
  734. StdPixExtract(PixMap *src,Rect *srcRect,MatrixRecord matrix,short mode,RgnHandle mask,PixMap *matte,
  735.     Rect *matteRect,short flags) 
  736. {
  737.  
  738.  
  739. #pragma    unused(srcRect,matrix,matte,matteRect,flags,mode,mask)
  740.  
  741.     ImageDescriptionHandle    idh;
  742.     long buffSize;
  743.     ICMDataProcRecord dataProc;
  744.     ICMProgressProcRecord progressProc;
  745.     Ptr    data;
  746.     
  747.     long        lb,l;
  748.     short        i,m;
  749.     char         *buf,*abuf = 0,tbuf[32];
  750.  
  751.     
  752.     
  753.     /************************************************************
  754.     
  755.      first check to see if it's a compressed pict opcode  
  756.      
  757.     ************************************************************/
  758.     
  759.     if ( GetCompressedPixMapInfo(src,&idh,&data,&buffSize,&dataProc,&progressProc) == 0 ) {
  760.     
  761.     
  762.         /*******************************
  763.         
  764.          verify compression type 
  765.          
  766.          ********************************/
  767.         
  768.         
  769.         if (  (*idh)->cType != 'jpeg' ) {
  770.             extractionErr = paramErr;        // we only wanted jpeg
  771.             return;
  772.         }
  773.  
  774.  
  775.         l = (*idh)->dataSize;
  776.     
  777.  
  778.         /********************************
  779.         
  780.            make a JFIF header opcode in case the data doesn't have one -
  781.            QT JPEG always includes one but other JPEG compressors may not 
  782.            
  783.         ********************************/
  784.           
  785.     
  786.         {
  787.             buf = tbuf;
  788.             m = 0;
  789.             buf[m++] = MARKER_PREFIX;                // marker prefix
  790.             buf[m++] = MARKER_APP0;                // APP0 marker
  791.             buf[m++] = 0;                    // size word ( filled in later )
  792.             buf[m++] = 0;
  793.             buf[m++] = 'J';                    // tag 5 bytes
  794.             buf[m++] = 'F';
  795.             buf[m++] = 'I';
  796.             buf[m++] = 'F';
  797.             buf[m++] = 0;        
  798.             buf[m++] = 1;                    // version word
  799.             buf[m++] = 1;
  800.             buf[m++] = 1;                    // specify dpi
  801.             buf[m++] = (*idh)->hRes>>24;    // hres word
  802.             buf[m++] = (*idh)->hRes>>16;
  803.             buf[m++] = (*idh)->vRes>>24;    // vres word
  804.             buf[m++] = (*idh)->vRes>>16;
  805.             buf[m++] = 0;                    // thumbnail x 
  806.             buf[m++] = 0;                    // thumbnail y 
  807.         }
  808.         buf[2] = (m-2)>>8;                    // fill in size
  809.         buf[3] = (m-2);
  810.         i = 0;
  811.         
  812.         /********************************
  813.         
  814.         Scan the JPEG data till we get to the start of image marker.
  815.         
  816.         ********************************/
  817.         
  818.         
  819.         while ( data[i] == (char)MARKER_PREFIX ) {
  820.             if ( i++ > 1024 ) {
  821.                 extractionErr = -1;
  822.                 if ( abuf )
  823.                     DisposPtr(abuf);
  824.                 return;
  825.             }
  826.         }
  827.         if ( data[i++] != (char)MARKER_SOI ) { 
  828.             extractionErr = -1;
  829.             if ( abuf )
  830.                 DisposPtr(abuf);
  831.             return;
  832.         }
  833.         
  834.         /*******************************
  835.         
  836.         Write out all the data up to and including the start of image marker
  837.         
  838.         *******************************/
  839.         
  840.         lb = i;
  841.         if ( dataProc.dataProc ) {
  842.             if ( extractionErr = dataProc.dataProc(&data,lb,dataProc.dataRefCon))
  843.                 return;
  844.         }
  845.         if ( extractionErr = FSWrite(extractionFile,&lb,data))  {
  846.             if ( abuf )
  847.                 DisposPtr(abuf);
  848.             return;
  849.         }
  850.         
  851.         /*******************************
  852.         
  853.         Check to see if there is a JFIF marker in the data already
  854.         
  855.         *******************************/
  856.     
  857.         
  858.         if ( data[i] == (char)MARKER_PREFIX &&  data[i+1] == (char)MARKER_APP0 ) {    // already have JFIF marker in stream
  859.             data += i;
  860.             l -= i;
  861.             goto no_jfif_marker;
  862.         } else {
  863.             data += i;
  864.             l -= i;
  865.         }
  866.     
  867.         lb = m;
  868.         if ( extractionErr = FSWrite(extractionFile,&lb,buf))  {
  869.             if ( abuf )
  870.                 DisposPtr(abuf);
  871.             return;
  872.         }
  873. no_jfif_marker:
  874.         if ( abuf )
  875.             DisposPtr(abuf);
  876.     
  877.         /*******************************
  878.         
  879.         Read the rest of the JPEG data and write it into the output file.
  880.         
  881.         *******************************/
  882.     
  883.     
  884.         if (  dataProc.dataProc ) {
  885.             lb = buffSize;
  886.             while ( l > buffSize ) {
  887.                 if ( extractionErr = dataProc.dataProc(&data,lb,dataProc.dataRefCon))  {
  888.                     return;
  889.                 }
  890.                 if ( extractionErr = FSWrite(extractionFile,&lb,data)) {
  891.                     return;
  892.                 }
  893.                 data += lb;
  894.                 l -= lb;
  895.             }
  896.             if ( extractionErr = dataProc.dataProc(&data,l,dataProc.dataRefCon)) {
  897.                 return;
  898.             }
  899.             if ( extractionErr = FSWrite(extractionFile,&l,data)) {
  900.                 return;
  901.             }
  902.         } else {
  903.             if ( extractionErr = FSWrite(extractionFile,&l,data))
  904.                 return;
  905.         }
  906.     
  907.         
  908.  
  909.     } else {
  910.     
  911.         /*******************************
  912.         
  913.         Not compressed data - return error.
  914.         
  915.         *******************************/
  916.     
  917.  
  918.         extractionErr = paramErr;
  919.     }
  920. }
  921.  
  922.  
  923.