1 /*************************************************************
2 Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved.
3 PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research
4 Group. If you use this software, you agree to the following: This
5 program package is purely experimental, and is licensed "as is".
6 Permission is granted to use, modify, and distribute this program
7 without charge for any purpose, provided this license/ disclaimer
8 notice appears in the copies.  No warranty or maintenance is given,
9 either expressed or implied.  In no event shall the author(s) be
10 liable to you or a third party for any special, incidental,
11 consequential, or other damages, arising out of the use or inability
12 to use the program for any purpose (or the loss of data), even if we
13 have been advised of such possibilities.  Any public reference or
14 advertisement of this source code should refer to it as the Portable
15 Video Research Group (PVRG) code, and not by any author(s) (or
16 Stanford University) name.
17 *************************************************************/
18 /*
19 ************************************************************
20 jpeg.c
21 
22 This file contains the main calling routines for the JPEG coder.
23 
24 ************************************************************
25 */
26 
27 /*LABEL jpeg.c */
28 
29 /* Include files. */
30 
31 #include "tables.h"
32 #include "marker.h"
33 #include "globals.h"
34 #ifdef SYSV
35 #include <sys/fcntl.h>
36 #endif
37 #include <stdlib.h> /* exit */
38 #include <string.h> /* strlen */
39 
40 /*
41   Define the functions to be used with ANSI prototyping.
42   */
43 
44 /*PUBLIC*/
45 
46 static void JpegEncodeFrame();
47 static void JpegDecodeFrame();
48 static void JpegDecodeScan();
49 static void JpegLosslessDecodeScan();
50 static void Help();
51 
52 extern void PrintImage();
53 extern void PrintFrame();
54 extern void PrintScan();
55 extern void MakeImage();
56 extern void MakeFrame();
57 extern void MakeScanFrequency();
58 extern void MakeScan();
59 extern void MakeConsistentFileNames();
60 extern void CheckValidity();
61 extern int CheckBaseline();
62 extern void ConfirmFileSize();
63 extern void JpegQuantizationFrame();
64 extern void JpegDefaultHuffmanScan();
65 extern void JpegFrequencyScan();
66 extern void JpegCustomScan();
67 extern void JpegEncodeScan();
68 
69 extern void JpegLosslessFrequencyScan();
70 extern void JpegLosslessEncodeScan();
71 
72 /*PRIVATE*/
73 
74 /* These variables occur in the stream definition. */
75 
76 extern int CleartoResync;
77 extern int LastKnownResync;
78 extern int ResyncEnable;
79 extern int ResyncCount;
80 extern int EndofFile;
81 extern int EndofImage;
82 
83 /* Define the parameter passing structures. */
84 IMAGE *CImage=NULL;           /* Current Image variables structure */
85 FRAME *CFrame=NULL;           /* Current Frame variables structure */
86 SCAN *CScan=NULL;             /* Current Scan variables structure */
87 
88 /* Define the MDU counters. */
89 int CurrentMDU=0;             /* Holds the value of the current MDU */
90 int NumberMDU=0;              /* This number is the number of MDU's */
91 
92 /* Define Lossless info */
93 
94 int LosslessPredictorType=0;  /* The lossless predictor used */
95 int PointTransform=0;         /* This parameter affects the shifting in io.c */
96 
97 /* How we break things up */
98 
99 int ScanComponentThreshold=SCAN_COMPONENT_THRESHOLD;
100 
101 /* Define the support/utility variables.*/
102 int ErrorValue=0;             /* Holds error upon return */
103 int Loud=MUTE;                /* Loudness gives level of debug traces */
104 int HuffmanTrace=0;        /* When set, dumps Huffman statistics */
105 int Notify=1;                 /* When set, gives image size feedback */
106 int Robust=0;
107 static int LargeQ=0;          /* When set, large quantization is enabled */
108 
109 /* We default to the Chen DCT algorithm. */
110 vFunc *UseDct = ChenDct;       /* This is the DCT algorithm to use */
111 vFunc *UseIDct = ChenIDct;     /* This is the inverse DCT algorithm to use */
112 
113 /* Add some macros to ease readability. */
114 #define DefaultDct (*UseDct)
115 #define DefaultIDct (*UseIDct)
116 
117 /*START*/
118 
119 /*BFUNC
120 
121 main() is first called by the shell routine upon execution of the
122 program.
123 
124 EFUNC*/
125 
main(argc,argv)126 int main(argc,argv)
127      int argc;
128      char **argv;
129 {
130   BEGIN("main")
131   int i,ComponentIndex;
132   int Oracle=0;     /* Oracle means that we use the lexer interactively */
133 
134   MakeImage();      /* Construct the image structures */
135   MakeFrame();
136   MakeScan();
137 
138   if (argc == 1)    /* No arguments then print help info */
139     {
140       Help();
141       exit(-1);
142     }
143 
144   ComponentIndex=1;  /* Start with index 1 (Could be zero, but JFIF compat) */
145   for(i=1;i<argc;i++)  /* Else loop through all arguments. */
146     {
147     if (!strcmp(argv[i],"-JFIF"))
148       CImage->Jfif=1;
149     else if (!strcmp(argv[i],"-ci"))
150       ComponentIndex=atoi(argv[++i]);
151     else if (*(argv[i]) == '-')       /* Strip off first "dash" */
152       {
153       switch(*(++argv[i]))
154         {
155       case 'a':                      /* -a Reference DCT */
156         UseDct = ReferenceDct;
157         UseIDct = ReferenceIDct;
158         break;
159       case 'b':                      /* -b Lee DCT */
160         UseDct = LeeDct;
161         UseIDct = LeeIDct;
162         break;
163       case 'd':                      /* -d Decode */
164         CImage->JpegMode = J_DECODER;
165         break;
166       case 'k':                      /* -k Lossless mode */
167         CImage->JpegMode = J_LOSSLESS;
168         CFrame->Type=3;
169         LosslessPredictorType = atoi(argv[++i]);
170         break;
171       case 'f':
172         switch(*(++argv[i]))
173           {
174         case 'w':                 /* -fw Frame width */
175           CFrame->Width[ComponentIndex] =
176             atoi(argv[++i]);
177           break;
178         case 'h':                 /* -fh Frame height */
179           CFrame->Height[ComponentIndex] =
180             atoi(argv[++i]);
181           break;
182         default:
183           WHEREAMI();
184           printf("Illegal option: f%c.\n",
185             *argv[i]);
186           exit(ERROR_BOUNDS);
187           break;
188           }
189         break;
190       case 'i':
191         switch(*(++argv[i]))
192           {
193         case 'w':                /* -iw Image width */
194           CFrame->GlobalWidth = atoi(argv[++i]);
195           break;
196         case 'h':                /* -ih Image height */
197           CFrame->GlobalHeight = atoi(argv[++i]);
198           break;
199         default:
200           WHEREAMI();
201           printf("Illegal option: i%c.\n",
202             *argv[i]);
203           exit(ERROR_BOUNDS);
204           break;
205           }
206         break;
207       case 'h':                    /* -h horizontal frequency */
208         CFrame->hf[ComponentIndex] =
209           atoi(argv[++i]);
210         break;
211 #ifndef PRODUCTION_VERSION
212       case 'l':                    /* -l loudness for debugging */
213         Loud = atoi(argv[++i]);
214         break;
215 #endif
216       case 'n':                    /* Set non-interleaved mode */
217         ScanComponentThreshold=1;
218         break;
219       case 'o':                    /* -o Oracle mode (input parsing)*/
220         Oracle=1;
221         break;
222       case 'p':
223         CFrame->DataPrecision = atoi(argv[++i]);
224         if (!CFrame->Type) CFrame->Type = 1;
225         break;
226       case 'r':                    /* -r resynchronization */
227         CFrame->ResyncInterval = atoi(argv[++i]);
228         break;
229       case 'q':                    /* -q Q factor */
230         if (*(++argv[i])=='l') LargeQ=1;
231         CFrame->Q = atoi(argv[++i]);
232         break;
233       case 'v':                    /* -v vertical frequency */
234         CFrame->vf[ComponentIndex] = atoi(argv[++i]);
235         break;
236       case 's':                    /* -s stream file name */
237         CImage->StreamFileName = argv[++i];
238         break;
239       case 't':
240         PointTransform=atoi(argv[++i]);
241         break;
242 #ifndef PRODUCTION_VERSION
243       case 'x':                    /* -x trace */
244         HuffmanTrace = 1;
245         break;
246 #endif
247       case 'u':                    /* -u disable width/size output */
248         Notify=0;
249         break;
250       case 'y':
251         Robust=1;
252         break;
253       case 'z':                    /* -z use default Huffman */
254         CImage->JpegMode |= J_DEFAULTHUFFMAN;
255         break;
256       case 'g':                    /* -g GDCM secret option */
257         CFrame->tmpfile = atoi(argv[++i]); /* very bad programming but should work :) */
258         break;
259       default:
260         WHEREAMI();
261         printf("Illegal option in command line: %c.\n",
262           *argv[i]);
263         exit(ERROR_BOUNDS);
264         break;
265         }
266       }
267     else                               /* If not a "-" then a filename */
268       {
269       CFrame->cn[CFrame->GlobalNumberComponents++]= ComponentIndex;
270       if (!CFrame->vf[ComponentIndex])
271         CFrame->vf[ComponentIndex]=1;
272       if (!CFrame->hf[ComponentIndex])
273         CFrame->hf[ComponentIndex]=1;
274       CFrame->ComponentFileName[ComponentIndex] = argv[i];
275       ComponentIndex++;
276       }
277     }
278 
279   if (Oracle)            /* If Oracle set */
280     {
281       initparser();      /* Initialize interactive parser */
282       parser();          /* parse input from stdin */
283       exit(ErrorValue);
284     }
285 
286   /* Otherwise act on information */
287 
288   if (!(GetFlag(CImage->JpegMode,J_DECODER)) &&  /* Check for files */
289       (CFrame->GlobalNumberComponents == 0))
290     {
291       WHEREAMI();
292       printf("No component file specified.\n");
293       exit(ERROR_BOUNDS);
294     }
295   if (CImage->StreamFileName == NULL)            /* Check for stream name */
296     {
297     if (CFrame->ComponentFileName[CFrame->cn[0]])  /* If doesn't exist */
298       {                                            /* Create one. */
299       CImage->StreamFileName =
300         (char *) calloc(strlen(CFrame->ComponentFileName[CFrame->cn[0]])+6,
301           sizeof(char));
302       sprintf(CImage->StreamFileName,"%s.jpg",
303         CFrame->ComponentFileName[CFrame->cn[0]]);
304       }
305     else
306       {
307       WHEREAMI();
308       printf("No stream filename.\n");
309       exit(ERROR_BOUNDS);
310       }
311     }
312   if (GetFlag(CImage->JpegMode,J_DECODER))       /* If decoder flag set then */
313     {                                            /* decode frame. */
314       JpegDecodeFrame();
315     }
316   else
317     {
318     if (!(CFrame->GlobalWidth) || !(CFrame->GlobalHeight)) /* Dimensions ? */
319       {
320       WHEREAMI();
321       printf("Unspecified frame size.\n");
322       exit(ERROR_BOUNDS);
323       }
324     swopen(CImage->StreamFileName,0);          /* Open output file, index 0*/
325     JpegEncodeFrame();                         /* Encode the frame */
326     swclose();                                 /* Flush remaining bits */
327     }
328   /*exit(ErrorValue);*/
329   return(ErrorValue);
330 }
331 
332 /*BFUNC
333 
334 JpegEncodeFrame() handles the basic encoding of the routines provided that
335 CFrame and CImage are set up properly. It creates the appropriate
336 CScan to handle the intermediate variables.
337 
338 EFUNC*/
339 
JpegEncodeFrame()340 static void JpegEncodeFrame()
341 {
342   BEGIN("JpegEncodeFrame")
343   int i,CurrentComponent;
344 
345   CurrentComponent=0;           /* Write start of image, start of frame */
346   WriteSoi();
347   if (CImage->Jfif) WriteJfif(); /* Write JFIF marker if necessary */
348   MakeConsistentFrameSize();     /* Do it here when everything defined */
349   JpegQuantizationFrame();       /* Set up quantization matrices */
350   WriteSof();
351   if (CFrame->ResyncInterval)   /* If resync enabled put DRI marker */
352     {
353       WriteDri();
354     }
355   while(1)                      /* This loop breaks up a large number of */
356     {                           /* components into small scans */
357     if (CFrame->GlobalNumberComponents<=CurrentComponent)
358       {
359       break;                /* All encoded */
360       }
361     else if (CFrame->GlobalNumberComponents-CurrentComponent <=
362       ScanComponentThreshold)
363       {                       /* If less/equal to (SCT) components do it */
364       CScan->NumberComponents =
365         CFrame->GlobalNumberComponents-CurrentComponent;
366       for(i=0;CurrentComponent<CFrame->GlobalNumberComponents;
367         CurrentComponent++,i++)
368         {
369         CScan->ci[i]=CFrame->cn[CurrentComponent];
370         }
371       }
372     else
373       {                       /* Break into (SCT) componets */
374       CScan->NumberComponents = ScanComponentThreshold;
375       for(i=0;i<ScanComponentThreshold;CurrentComponent++,i++)
376         {
377         CScan->ci[i]=CFrame->cn[CurrentComponent];
378         }
379       }
380     CheckValidity();                  /* Check validity */
381     CheckBaseline();                  /* See if type is correct */
382 
383     if (Loud > MUTE)
384       {
385       PrintImage();
386       PrintFrame();
387       PrintScan();
388       }
389     ConfirmFileSize();                /* Does files on disk agree? */
390     if (GetFlag(CImage->JpegMode,J_LOSSLESS))
391       {
392       MakeIob(IOB_LINE,O_RDONLY,
393         ((CFrame->DataPrecision>8)?2:1));  /* Make IO read struct*/
394       JpegLosslessFrequencyScan();        /* Else make custom stables */
395       JpegCustomScan(CUSTOM_DO_DC);
396       WriteDht();                         /* write Huffman tables */
397       JpegLosslessEncodeScan();
398       }
399     else if (GetFlag(CImage->JpegMode,J_DEFAULTHUFFMAN))
400       {
401       MakeIob(IOB_BLOCK,O_RDONLY,
402         ((CFrame->DataPrecision>8)?2:1));  /* Make IO read struct */
403 
404       JpegDefaultHuffmanScan();     /* If default tables, then set up */
405       WriteDqt();                       /* Write out quantization */
406       WriteDht();                       /* and Huffman tables */
407       JpegEncodeScan();                 /* Encode the scan */
408       }
409     else
410       {
411       MakeIob(IOB_BLOCK,O_RDONLY,
412         ((CFrame->DataPrecision>8)?2:1));  /* Make IO read struct*/
413       JpegFrequencyScan();              /* Else make custom tables */
414       JpegCustomScan(CUSTOM_DO_AC|CUSTOM_DO_DC);
415       WriteDqt();                       /* Write out quantization */
416       WriteDht();                       /* and Huffman tables */
417       JpegEncodeScan();                 /* Encode the scan */
418       }
419     for(i=0;i<CScan->NumberComponents;i++)  /* Close all components */
420       {
421       InstallIob(i);
422       CloseIob();
423       }
424     }
425   WriteEoi();                              /* All finished, Write eoi */
426 }
427 
428 /*BFUNC
429 
430 JpegQuantizationFrame() sets up the default quantization matrices to be
431 used in the scan. Not to be used with user-specified quantization.
432 
433 EFUNC*/
434 
JpegQuantizationFrame()435 void JpegQuantizationFrame()
436 {
437   BEGIN("JpegQuantizationFrame")
438   int i;
439 
440   if (CFrame->Q)                    /* if Q  rescale quantization matrices */
441     CImage->QuantizationMatrices[0] =
442       ScaleMatrix(CFrame->Q,Q_PRECISION,LargeQ,LuminanceQuantization);
443   else
444     CImage->QuantizationMatrices[0] = LuminanceQuantization;
445 
446   CScan->sq[CScan->NumberQTablesSend++] = 0; /* Queue luminance to send */
447   if (CFrame->GlobalNumberComponents>1)
448     {
449     if (CFrame->Q)                 /* rescale quantization matrices */
450       CImage->QuantizationMatrices[1] =
451         ScaleMatrix(CFrame->Q,Q_PRECISION,LargeQ,ChrominanceQuantization);
452     else
453       CImage->QuantizationMatrices[1] = ChrominanceQuantization;
454     CScan->sq[CScan->NumberQTablesSend++] = 1; /* Queue table to send */
455     }
456   for(i=0;i<CFrame->GlobalNumberComponents;i++)
457     {
458     if (i%ScanComponentThreshold)
459       CFrame->tq[CFrame->cn[i]]=1; /* chrominance q for non-primaries */
460     else
461       CFrame->tq[CFrame->cn[i]]=0; /* luminance q starts each scan */
462     }
463 }
464 
465 /*BFUNC
466 
467 JpegDefaultHuffmanScan() creates the default tables for baseline use.
468 
469 EFUNC*/
470 
JpegDefaultHuffmanScan()471 void JpegDefaultHuffmanScan()
472 {
473   BEGIN("JpegDefaultScan")
474   int i;
475 
476   if (CFrame->DataPrecision>8)
477     {
478       WHEREAMI();
479       printf("Default tables attempted with precision > 8.\n");
480       exit(ERROR_BOUNDS);
481     }
482   MakeXhuff();                      /* Make luminance DC Huffman */
483   MakeEhuff();
484   SpecifiedHuffman(LuminanceDCBits,LuminanceDCValues);
485   SetDCHuffman(0);
486   MakeXhuff();                      /* Make luminance AC Huffman */
487   MakeEhuff();
488   SpecifiedHuffman(LuminanceACBits,LuminanceACValues);
489   SetACHuffman(0);
490   MakeXhuff();
491   MakeEhuff();
492   CScan->td[0] = 0;
493   CScan->ta[0] = 0;
494   CScan->sa[CScan->NumberACTablesSend++] = 0;  /* Queue to transmit table */
495   CScan->sd[CScan->NumberDCTablesSend++] = 0;
496   if(CScan->NumberComponents>1)     /* Make chrominance Huffman tables */
497     {                               /* Only if necessary */
498       SpecifiedHuffman(ChrominanceDCBits,ChrominanceDCValues);
499       SetDCHuffman(1);
500       MakeXhuff();
501       MakeEhuff();
502       SpecifiedHuffman(ChrominanceACBits,ChrominanceACValues);
503       SetACHuffman(1);
504       for(i=1;i<CScan->NumberComponents;i++)
505         {
506         CScan->td[i] = 1;
507         CScan->ta[i] = 1;
508         }
509       CScan->sa[CScan->NumberACTablesSend++] = 1;
510       CScan->sd[CScan->NumberDCTablesSend++] = 1;
511       CImage->NumberACTables = MAX(CImage->NumberACTables,2);
512       CImage->NumberDCTables = MAX(CImage->NumberDCTables,2);
513     }
514   else
515     {
516       CImage->NumberACTables = MAX(CImage->NumberACTables,1);
517       CImage->NumberDCTables = MAX(CImage->NumberDCTables,1);
518     }
519 }
520 
521 /*BFUNC
522 
523 JpegFrequencyScan() assembles the frequency statistics for the given
524 scan, making one AC Freq, DC Freq statistic per component specified.
525 This function should be used before making custom quantization tables.
526 
527 EFUNC*/
528 
JpegFrequencyScan()529 void JpegFrequencyScan()
530 {
531   BEGIN("JpegFrequencyScan")
532   int i,j,h,v,dohf,dovf;
533   int input[64],output[64];
534   int DCTBound,DCTShift;
535 
536   InstallIob(0);                 /* Zero out for fast single-component */
537   InstallPrediction(0);          /* operation. */
538   InstallFrequency(0);
539   CheckScan();
540   NumberMDU = CScan->MDUWide*CScan->MDUHigh;
541   ClearFrameFrequency();
542   ResetCodec();
543   DCTBound = ((CFrame->DataPrecision>8)?16383:1023);
544   DCTShift = ((CFrame->DataPrecision>8)?2048:128);
545   for(i=0;i<NumberMDU;i++)         /* Do for all MDU in image */
546     {
547     if ( i && (CFrame->ResyncInterval))
548       {
549       if (!(i % CFrame->ResyncInterval)) /* Resync the codec */
550         ResetCodec();
551       }
552     for(j=0;j<CScan->NumberComponents;j++)
553       {
554       InstallIob(j);
555       InstallPrediction(j);    /* Install statistics tables */
556       InstallFrequency(j);
557       if (CScan->NumberComponents==1)
558         dohf=dovf=1;
559       else
560         {
561         dohf = CFrame->hf[CScan->ci[j]];
562         dovf = CFrame->vf[CScan->ci[j]];
563         }
564       for(v=0;v<dovf;v++)  /* Do encoding */
565         {                                      /* and accum. stats */
566         for(h=0;h<dohf;h++)
567           {
568           ReadBlock(input);
569           PreshiftDctMatrix(input,DCTShift);
570           DefaultDct(input,output);
571           BoundDctMatrix(output,DCTBound);
572           Quantize(output,
573             CImage->
574             QuantizationMatrices[CFrame->
575             tq[CScan->ci[j]]]);
576           ZigzagMatrix(output,input);
577           FrequencyDC(*input);           /* Freq accumulates */
578           FrequencyAC(input);            /* stats w/o encoding */
579           }
580         }
581       }
582     }
583   for(i=0;i<CScan->NumberComponents;i++)  /* Rewind to start */
584     {
585       InstallIob(i);
586       RewindIob();
587     }
588 }
589 
590 /*BFUNC
591 
592 JpegCustomScan() assembles custom Huffman tables for the input.
593 It defaults to baseline unless FULLHUFFMAN flag is set.
594 
595 EFUNC*/
596 
JpegCustomScan(flags)597 void JpegCustomScan(flags)
598      int flags;
599 {
600   BEGIN("JpegCustomScan")
601   int i,Sumbits;
602 
603   if ((GetFlag(CImage->JpegMode,J_FULLHUFFMAN)) ||
604     (CScan->NumberComponents < 3))
605     {
606     for(i=0;i<CScan->NumberComponents;i++)
607       {
608       if (GetFlag(flags,CUSTOM_DO_DC))
609         {
610         MakeXhuff();
611         MakeEhuff();
612         MakeHuffman(CScan->DCFrequency[i]);
613         SetDCHuffman(i);
614         CScan->td[i] = i;
615         CScan->sd[CScan->NumberDCTablesSend++] = i;
616         }
617       if (GetFlag(flags,CUSTOM_DO_AC))
618         {
619         MakeXhuff();
620         MakeEhuff();
621         MakeHuffman(CScan->ACFrequency[i]);
622         SetACHuffman(i);
623         CScan->ta[i] = i;
624         CScan->sa[CScan->NumberACTablesSend++] = i;
625         }
626       InstallIob(i);
627       RewindIob();
628       }
629     CImage->NumberACTables = MAX(CImage->NumberACTables,
630       CScan->NumberComponents);
631     CImage->NumberDCTables = MAX(CImage->NumberDCTables,
632       CScan->NumberComponents);
633     }
634   else
635     {
636     if (GetFlag(flags,CUSTOM_DO_DC))
637       {
638       MakeXhuff();                   /* 0 Component has custom Huffman */
639       MakeEhuff();
640       MakeHuffman(CScan->DCFrequency[0]);
641       SetDCHuffman(0);
642       CScan->td[0] = 0;              /* 0 component uses tables 0 */
643       CScan->sd[CScan->NumberDCTablesSend++] = 0; /* Queue to send */
644       }
645     if (GetFlag(flags,CUSTOM_DO_AC))
646       {
647       MakeXhuff();
648       MakeEhuff();
649       MakeHuffman(CScan->ACFrequency[0]);
650       SetACHuffman(0);
651       CScan->ta[0] = 0;
652       CScan->sa[CScan->NumberACTablesSend++] = 0; /* Queue table send */
653       }
654     if (CScan->NumberComponents > 1)
655       {
656       if (GetFlag(flags,CUSTOM_DO_DC))
657         {
658         for(i=2;i<CScan->NumberComponents;i++) /* Rest share Huffman*/
659           {                                    /* Accum. frequencies */
660           AddFrequency(CScan->DCFrequency[1],CScan->DCFrequency[i]);
661           }
662         MakeXhuff();
663         MakeEhuff();
664         MakeHuffman(CScan->DCFrequency[1]);
665         SetDCHuffman(1);
666         for(i=1;i<CScan->NumberComponents;i++) /* Rest use table 1 */
667           CScan->td[i] = 1;
668         CScan->sd[CScan->NumberDCTablesSend++] = 1;/* Queue to send */
669         }
670       if (GetFlag(flags,CUSTOM_DO_AC))
671         {
672         for(i=2;i<CScan->NumberComponents;i++) /*Accum. frequencies */
673           {
674           AddFrequency(CScan->ACFrequency[1],CScan->ACFrequency[i]);
675           }
676         MakeXhuff();
677         MakeEhuff();
678         MakeHuffman(CScan->ACFrequency[1]);
679         SetACHuffman(1);
680         for(i=1;i<CScan->NumberComponents;i++) /* Rest use table 1 */
681           CScan->ta[i] = 1;
682         CScan->sa[CScan->NumberACTablesSend++] = 1;  /* Queue to send */
683         }
684       CImage->NumberACTables = MAX(CImage->NumberACTables,2);/*reset */
685       CImage->NumberDCTables = MAX(CImage->NumberDCTables,2);/* limits */
686       }
687     else
688       {
689       CImage->NumberACTables = MAX(CImage->NumberACTables,1); /* Reset */
690       CImage->NumberDCTables = MAX(CImage->NumberDCTables,1); /*  limits */
691       }
692     }
693   if (HuffmanTrace)     /* If trace flag, then dump out frequency tables */
694     {
695     Sumbits = 0;
696     for(i=0;i<CImage->NumberACTables;i++)
697       {
698       WHEREAMI();
699       printf("AC Code Frequency: Table %d\n",i);
700       PrintACEhuff(i);
701       Sumbits += SizeACEhuff(i);
702       }
703     for(i=0;i<CImage->NumberDCTables;i++)
704       {
705       WHEREAMI();
706       printf("DC Code Frequency: Table %d\n",i);
707       PrintDCEhuff(i);
708       Sumbits +=  SizeDCEhuff(i);
709       }
710     WHEREAMI();
711     printf("Total bits: %d  bytes: %d\n",
712       Sumbits,(Sumbits+7)/8);
713     }
714 }
715 
716 /*BFUNC
717 
718 JpegEncodeScan() encodes the scan that is given to it. We assume that
719 the quantization and the Huffman tables have already been specified.
720 
721 EFUNC*/
722 
JpegEncodeScan()723 void JpegEncodeScan()
724 {
725   BEGIN("JpegEncodeScan")
726   int i,j,h,v,dohf,dovf;
727   int input[64],output[64];
728   int DCTBound,DCTShift;
729 
730   InstallIob(0);
731   CheckScan();
732   NumberMDU = CScan->MDUWide*CScan->MDUHigh;
733   ClearFrameFrequency();
734   ResetCodec();
735   DCTBound = ((CFrame->DataPrecision>8)?16383:1023);
736   DCTShift = ((CFrame->DataPrecision>8)?2048:128);
737   ResyncCount=0;                /* Reset the resync counter for every scan */
738   if (CFrame->InsertDnl>0) /* If DNL is greater than 0, insert */
739     {                           /* into according Resync interval */
740     if  (!(CFrame->ResyncInterval))
741       WriteDnl();  /* Automatically write a dnl if no resync is enabled.*/
742     else                      /* If DNL > MDU, then put in last resync */
743       CFrame->InsertDnl = MAX(CFrame->InsertDnl,      /* interval */
744         NumberMDU/CFrame->ResyncInterval);
745     }
746   WriteSos();                  /* Start of Scan */
747   for(i=0;i<NumberMDU;i++)
748     {
749     if ( i && (CFrame->ResyncInterval))
750       {
751       if (!(i % CFrame->ResyncInterval)) /* Check for resync */
752         {
753         if ((i/CFrame->ResyncInterval)==CFrame->InsertDnl)
754           {
755           WriteDnl();                /* If resync matches use DNL */
756           CFrame->InsertDnl=0;       /* Mission accomplished. */
757           }
758         WriteResync();                 /* Write resync */
759         ResetCodec();
760         }
761       }
762     for(j=0;j<CScan->NumberComponents;j++)
763       {
764       if (Loud > MUTE)
765         {
766         WHEREAMI();
767         printf("[Pass 2 [Component:MDU] [%d:%d]]\n",j,i);
768         }
769       InstallIob(j);                    /* Install component j */
770       InstallPrediction(j);
771       if (CScan->NumberComponents==1)
772         dohf=dovf=1;
773       else
774         {
775         dohf = CFrame->hf[CScan->ci[j]];
776         dovf = CFrame->vf[CScan->ci[j]];
777         }
778       for(v=0;v<dovf;v++)  /* loop thru MDU */
779         {
780         for(h=0;h<dohf;h++)
781           {
782           ReadBlock(input);                /* Read in */
783           if (Loud > WHISPER)
784             {
785             WHEREAMI();
786             printf("Raw input:\n");
787             PrintMatrix(input);
788             }
789           PreshiftDctMatrix(input,DCTShift);        /* Shift */
790           DefaultDct(input,output);        /* DCT */
791           BoundDctMatrix(output,DCTBound); /* Bound, limit */
792           Quantize(output,                 /* Quantize */
793             CImage->
794             QuantizationMatrices[CFrame->
795             tq[CScan->ci[j]]]);
796           ZigzagMatrix(output,input);      /* Zigzag trace */
797           if (Loud > TALK)
798             {
799             WHEREAMI();
800             printf("Cooked Output:\n");
801             PrintMatrix(input);
802             }
803           UseDCHuffman(CScan->td[j]);
804           EncodeDC(*input);               /* Encode DC component */
805           UseACHuffman(CScan->ta[j]);
806           EncodeAC(input);                /* Encode AC component */
807           }
808         }
809       }
810     }
811   if (CFrame->InsertDnl==-2)    /* -2 is automatic DNL insertion */
812     {
813       WriteDnl();                 /* Put DNL here */
814       CFrame->InsertDnl=0;
815     }
816   for(i=0;i<CScan->NumberComponents;i++)          /* Rewind to start */
817     {
818       InstallIob(i);
819       RewindIob();
820     }
821 }
822 
823 /*BFUNC
824 
825 JpegLosslessFrequencyScan() accumulates the frequencies into the DC
826 frequency index.
827 
828 EFUNC*/
829 
JpegLosslessFrequencyScan()830 void JpegLosslessFrequencyScan()
831 {
832   BEGIN("JpegLosslessFrequencyScan")
833   int x,y,j,h,v,px;
834   int height,width,horfreq,value;
835   int MaxElem,CurrentElem,NumberElem;
836   int StartofLine=1,UseType=1;              /* Start with type 1 coding */
837   int *input;
838 
839   CheckScan();
840   for(j=0;j<CScan->NumberComponents;j++)          /* Rewind to start */
841     {
842       InstallIob(j);
843       RewindIob();
844     }
845   if (CScan->NumberComponents==1)       /* Calculate maximum number of */
846     MaxElem= LOSSLESSBUFFERSIZE/4;      /* elements can be loaded in */
847   else
848     {
849     MaxElem= LOSSLESSBUFFERSIZE/
850       ((CFrame->vf[CScan->ci[0]]+1)*(CFrame->hf[CScan->ci[0]]+1));
851     for(j=1;j<CScan->NumberComponents;j++)          /* Rewind to start */
852       {
853       x=LOSSLESSBUFFERSIZE/
854         ((CFrame->vf[CScan->ci[j]]+1)*(CFrame->hf[CScan->ci[j]]+1));
855       if (x < MaxElem) MaxElem=x;
856       }
857     }
858   CScan->SSS=LosslessPredictorType;
859   CScan->SAL=PointTransform;
860   ClearFrameFrequency();
861   InstallIob(0);             /* Set up values for fast non-interleaved mode */
862   InstallFrequency(0);
863   if (CScan->NumberComponents==1)
864     height=horfreq=1;
865   else
866     {
867       height=CFrame->vf[CScan->ci[0]];
868       horfreq=CFrame->hf[CScan->ci[0]];
869     }
870   NumberMDU = CScan->MDUWide*CScan->MDUHigh;
871   CurrentMDU=0;
872   if ((CFrame->ResyncInterval)&&(CFrame->ResyncInterval % CScan->MDUWide))
873     {
874       WHEREAMI();
875       printf("Resync Interval not an integer multiple of MDU's wide.\n");
876       printf("Proceeding anyways.\n");
877       if (MaxElem>=CFrame->ResyncInterval)
878         MaxElem=CFrame->ResyncInterval;       /* Reduce to resync interval */
879       else
880         MaxElem=1;                            /* Can't proceed quickly */
881     }
882   CurrentElem=NumberElem=0;
883   for(y=0;y<CScan->MDUHigh;y++)
884     {
885     for(x=0;x<CScan->MDUWide;x++)
886       {
887       if (CurrentMDU && (CFrame->ResyncInterval))
888         {
889         if (!(CurrentMDU % CFrame->ResyncInterval)) /* Check resync */
890           {
891           UseType=1;                     /* Reset codec */
892           for(j=0;j<CScan->NumberComponents;j++)
893             {
894             InstallIob(j);
895             LineResetBuffers();
896             }
897           }
898         }
899       if (!(CurrentMDU%CScan->MDUWide)&&(CurrentMDU)) /* Reset CScan type */
900         {
901         UseType=2;                           /* Start of line */
902         StartofLine=1;                       /* uses top pel predictor */
903         }
904       CurrentElem++;
905       if (CurrentElem>=NumberElem)
906         {
907         NumberElem = MIN((CScan->MDUWide-x),MaxElem);
908         CurrentElem=0;
909         for(j=0;j<CScan->NumberComponents;j++)
910           {
911           InstallIob(j);                    /* Install component j */
912           ReadLine(NumberElem,              /* Read in some elements*/
913             CScan->LosslessBuffer[j]);
914           }
915         }
916       if (CScan->NumberComponents==1)
917         {
918         width=horfreq*NumberElem+1;
919         input = &CScan->LosslessBuffer[0][CurrentElem];
920         if (Loud > NOISY)
921           {
922           WHEREAMI();
923           printf("[Pass 1 [Component:MDU:Total] [%d:%d:%d]]\n",
924             0,CurrentMDU,NumberMDU);
925           }
926         switch(UseType) /* Same as lossless coding predictor*/
927           {
928         case 1:
929           px = input[width];
930           break;
931         case 2:
932           px = input[1];
933           break;
934         case 3:
935           px = input[0];
936           break;
937         case 4:
938           px = input[width] + input[1] - input[0];
939           break;
940         case 5:
941           px = input[width] + ((input[1] - input[0])>>1);
942           break;
943         case 6:
944           px = input[1] + ((input[width] - input[0])>>1);
945           break;
946         case 7:
947           px = (input[1]+input[width])>>1;  /* No rounding */
948           break;
949         default:
950           WHEREAMI();
951           printf("Lossless mode %d not supported.\n",UseType);
952           break;
953           }
954         value=input[width+1]-px;
955         if (Loud > NOISY)
956           printf("IN=%d  PX=%d  FRE: %d\n",
957             input[width+1],px,value);
958         LosslessFrequencyDC(value);
959         }
960       else
961         {
962         for(j=0;j<CScan->NumberComponents;j++)
963           {
964           if (Loud > NOISY)
965             {
966             WHEREAMI();
967             printf("[Pass 1 [Component:MDU:Total] [%d:%d:%d]]\n",
968               j,CurrentMDU,NumberMDU);
969             }
970           InstallFrequency(j);
971           height=CFrame->vf[CScan->ci[j]];
972           horfreq=CFrame->hf[CScan->ci[j]];
973           width=horfreq*NumberElem+1;
974           input = &CScan->LosslessBuffer[j][CurrentElem*horfreq];
975           for(v=1;v<=height;v++)
976             {
977             for(h=1;h<=horfreq;h++)
978               {
979               switch(UseType) /* lossless coding predictor*/
980                 {
981               case 1:
982                 px = input[(v*(width))+h-1];
983                 break;
984               case 2:
985                 px = input[((v-1)*(width))+h];
986                 break;
987               case 3:
988                 px = input[((v-1)*(width))+h-1];
989                 break;
990               case 4:
991                 px = input[(v*(width))+h-1] +
992                   input[((v-1)*(width))+h] -
993                   input[((v-1)*(width))+h-1];
994                 break;
995               case 5:
996                 px = input[(v*(width))+h-1] +
997                   ((input[((v-1)*(width))+h] -
998                     input[((v-1)*(width))+h-1])>>1);
999                 break;
1000               case 6:
1001                 px = input[((v-1)*(width))+h] +
1002                   ((input[(v*(width))+h-1] -
1003                     input[((v-1)*(width))+h-1])>>1);
1004                 break;
1005               case 7:
1006                 px = (input[((v-1)*(width))+h] +
1007                   input[(v*(width))+h-1])>>1;
1008                 break;
1009               default:
1010                 WHEREAMI();
1011                 printf("Lossless mode: %d not supported.\n",
1012                   UseType);
1013                 break;
1014                 }
1015               value=input[(v*(width))+h]-px;
1016               if (Loud > NOISY)
1017                 printf("IN=%d  PX=%d  FRE: %d\n",
1018                   input[(v*(width))+h],px,value);
1019               LosslessFrequencyDC(value);
1020               }
1021             }
1022           }
1023         }
1024       CurrentMDU++;
1025       if (StartofLine)
1026         {
1027         UseType=CScan->SSS;
1028         StartofLine=0;
1029         }
1030       }
1031     }
1032   for(j=0;j<CScan->NumberComponents;j++)          /* Rewind to start */
1033     {
1034       InstallIob(j);
1035       RewindIob();
1036     }
1037 }
1038 
1039 /*BFUNC
1040 
1041 JpegEncodeLosslessScan() encodes the scan that is given to it by lossless
1042 techniques. The Huffman table should already be specified.
1043 
1044 EFUNC*/
1045 
JpegLosslessEncodeScan()1046 void JpegLosslessEncodeScan()
1047 {
1048   BEGIN("JpegEncodeLosslessScan")
1049   int x,y,j,h,v,px;
1050   int height,width,horfreq,value;
1051   int MaxElem,CurrentElem,NumberElem;
1052   int StartofLine=1,UseType=1;              /* Start with type 1 coding */
1053   int *input;
1054 
1055   CheckScan();
1056   for(j=0;j<CScan->NumberComponents;j++)    /* Important to rewind to start */
1057     {                                       /* for lossless coding... */
1058       InstallIob(j);
1059       RewindIob();
1060     }
1061   if (CScan->NumberComponents==1)       /* Calculate maximum number of */
1062     MaxElem= LOSSLESSBUFFERSIZE/4;      /* elements can be loaded in */
1063   else
1064     {
1065     MaxElem= LOSSLESSBUFFERSIZE/
1066       ((CFrame->vf[CScan->ci[0]]+1)*(CFrame->hf[CScan->ci[0]]+1));
1067     for(j=1;j<CScan->NumberComponents;j++)          /* Rewind to start */
1068       {
1069       x=LOSSLESSBUFFERSIZE/
1070         ((CFrame->vf[CScan->ci[j]]+1)*(CFrame->hf[CScan->ci[j]]+1));
1071       if (x < MaxElem) MaxElem=x;
1072       }
1073     }
1074   CScan->SSS=LosslessPredictorType;
1075   CScan->SAL=PointTransform;
1076   InstallIob(0);
1077   UseDCHuffman(CScan->td[0]);          /* Install DC table */
1078   if (CScan->NumberComponents==1)
1079     height=horfreq=1;
1080   else
1081     {
1082       height=CFrame->vf[CScan->ci[0]];
1083       horfreq=CFrame->hf[CScan->ci[0]];
1084     }
1085   NumberMDU = CScan->MDUWide*CScan->MDUHigh;
1086   ResyncCount=0;                /* Reset the resync counter for every scan */
1087   if (CFrame->InsertDnl>0) /* If DNL is greater than 0, insert */
1088     {                           /* into according Resync interval */
1089     if  (!(CFrame->ResyncInterval))
1090       WriteDnl();  /* Automatically write a dnl if no resync is enabled.*/
1091     else                      /* If DNL > MDU, then put in last resync */
1092       CFrame->InsertDnl = MAX(CFrame->InsertDnl,         /* interval */
1093         NumberMDU/CFrame->ResyncInterval);
1094     }
1095   WriteSos();                  /* Start of Scan */
1096   CurrentMDU=0;
1097   if ((CFrame->ResyncInterval)&&(CFrame->ResyncInterval % CScan->MDUWide))
1098     {
1099     WHEREAMI();
1100     printf("Resync Interval not an integer multiple of MDU's wide.\n");
1101     printf("Proceeding anyways.\n");
1102     if (MaxElem>=CFrame->ResyncInterval)
1103       MaxElem=CFrame->ResyncInterval;       /* Reduce to resync interval */
1104     else
1105       MaxElem=1;                            /* Can't proceed quickly */
1106     }
1107   CurrentElem=NumberElem=0;
1108   for(y=0;y<CScan->MDUHigh;y++)
1109     {
1110     for(x=0;x<CScan->MDUWide;x++)
1111       {
1112       if (CurrentMDU && (CFrame->ResyncInterval))
1113         {
1114         if (!(CurrentMDU % CFrame->ResyncInterval)) /* Check resync */
1115           {
1116           if ((CurrentMDU/CFrame->ResyncInterval)==CFrame->InsertDnl)
1117             {
1118             WriteDnl();              /* If resync matches use DNL */
1119             CFrame->InsertDnl=0;     /* Mission accomplished. */
1120             }
1121           WriteResync();                 /* Write resync */
1122           UseType=1;                     /* Reset codec */
1123           for(j=0;j<CScan->NumberComponents;j++)
1124             {
1125             InstallIob(j);
1126             LineResetBuffers();
1127             }
1128           }
1129         }
1130       if (!(CurrentMDU%CScan->MDUWide)&&(CurrentMDU)) /* Reset CScan type */
1131         {
1132         UseType=2;                           /* Start of line */
1133         StartofLine=1;                       /* uses top pel predictor */
1134         }
1135       CurrentElem++;
1136       if (CurrentElem>=NumberElem)
1137         {
1138         NumberElem = MIN((CScan->MDUWide-x),MaxElem);
1139         CurrentElem=0;
1140         for(j=0;j<CScan->NumberComponents;j++)
1141           {
1142           InstallIob(j);                    /* Install component j */
1143           ReadLine(NumberElem,              /* Read in some elements*/
1144             CScan->LosslessBuffer[j]);
1145           }
1146         }
1147       if (CScan->NumberComponents==1)
1148         {
1149         if (Loud > MUTE)
1150           {
1151           WHEREAMI();
1152           printf("[Pass 2 [Component:MDU:Total] [%d:%d:%d]]\n",
1153             0,CurrentMDU,NumberMDU);
1154           }
1155         input = &CScan->LosslessBuffer[0][CurrentElem];
1156         width=horfreq*NumberElem+1;
1157         switch(UseType) /* Same as lossless coding predictor*/
1158           {
1159         case 1:
1160           px = input[width];
1161           break;
1162         case 2:
1163           px = input[1];
1164           break;
1165         case 3:
1166           px = input[0];
1167           break;
1168         case 4:
1169           px = input[width] + input[1] - input[0];
1170           break;
1171         case 5:
1172           px = input[width] + ((input[1] - input[0])>>1);
1173           break;
1174         case 6:
1175           px = input[1] + ((input[width] - input[0])>>1);
1176           break;
1177         case 7:
1178           px = (input[1] + input[width])>>1;  /* No rounding */
1179           break;
1180         default:
1181           WHEREAMI();
1182           printf("Lossless mode %d not supported.\n",UseType);
1183           break;
1184           }
1185         value=input[width+1]-px;
1186         if (Loud > MUTE)
1187           printf("IN=%d  PX=%d  FRE: %d\n",
1188             input[width+1],px,value);
1189         LosslessEncodeDC(value);
1190         }
1191       else
1192         {
1193         for(j=0;j<CScan->NumberComponents;j++)
1194           {
1195           if (Loud > MUTE)
1196             {
1197             WHEREAMI();
1198             printf("[Pass 2 [Component:MDU] [%d:%d]]\n",
1199               j,CurrentMDU);
1200             }
1201           height=CFrame->vf[CScan->ci[j]];
1202           horfreq=CFrame->hf[CScan->ci[j]];
1203           width=horfreq*NumberElem+1;
1204           input = &CScan->LosslessBuffer[j][CurrentElem*horfreq];
1205           UseDCHuffman(CScan->td[j]);
1206           for(v=1;v<=height;v++)
1207             {
1208             for(h=1;h<=horfreq;h++)
1209               {
1210               switch(UseType)   /* Same as lossless predictor*/
1211                 {
1212               case 1:
1213                 px = input[(v*(width))+h-1];
1214                 break;
1215               case 2:
1216                 px = input[((v-1)*(width))+h];
1217                 break;
1218               case 3:
1219                 px = input[((v-1)*(width))+h-1];
1220                 break;
1221               case 4:
1222                 px = input[(v*(width))+h-1] +
1223                   input[((v-1)*(width))+h] -
1224                   input[((v-1)*(width))+h-1];
1225                 break;
1226               case 5:
1227                 px = input[(v*(width))+h-1] +
1228                   ((input[((v-1)*(width))+h] -
1229                     input[((v-1)*(width))+h-1])>>1);
1230                 break;
1231               case 6:
1232                 px = input[((v-1)*(width))+h] +
1233                   ((input[(v*(width))+h-1] -
1234                     input[((v-1)*(width))+h-1])>>1);
1235                 break;
1236               case 7:
1237                 px = (input[((v-1)*(width))+h] +
1238                   input[(v*(width))+h-1])>>1;
1239                 break;
1240               default:
1241                 WHEREAMI();
1242                 printf("Lossless mode %d not supported.\n",
1243                   UseType);
1244                 break;
1245                 }
1246               value=input[(v*(width))+h]-px;
1247               if (Loud > MUTE)
1248                 {
1249                 printf("IN=%d  PX=%d  ENC: %d\n",
1250                   input[(v*(width))+h],px,value);
1251                 }
1252               LosslessEncodeDC(value); /* Encode as DC component */
1253               }
1254             }
1255           }
1256         }
1257       CurrentMDU++;
1258       if (StartofLine)
1259         {
1260         UseType=CScan->SSS;
1261         StartofLine=0;
1262         }
1263       }
1264     }
1265   if (CFrame->InsertDnl==-2)    /* -2 is automatic DNL insertion */
1266     {
1267     WriteDnl();
1268     CFrame->InsertDnl=0;
1269     }
1270 
1271   for(j=0;j<CScan->NumberComponents;j++)          /* Rewind to start */
1272     {
1273     InstallIob(j);
1274     RewindIob();
1275     }
1276 }
1277 
1278 /*BFUNC
1279 
1280 JpegDecodeFrame(general,)
1281      ) is used to decode a file. In general; is used to decode a file. In general, CFrame should
1282 hold just enough information to set up the file structure; that is,
1283 which file is to be opened for what component.
1284 
1285 EFUNC*/
1286 
JpegDecodeFrame()1287 static void JpegDecodeFrame()
1288 {
1289   BEGIN("JpegDecodeFrame")
1290   int i;
1291 
1292   sropen(CImage->StreamFileName,0);   /* Zero index */
1293   if (ScreenAllMarker() < 0)          /* Do all markers pending */
1294     {
1295       WHEREAMI();
1296       printf("No initial marker found!\n");
1297       exit(-1);
1298     }
1299   while(1)
1300     {
1301     if (NumberMDU>=0)               /* If NumberMDU is positive proceed */
1302       {
1303       if (CurrentMDU >= NumberMDU) /* If all decoded */
1304         {
1305         if (Notify)             /* Print statistics */
1306           {
1307           printf("> GW:%d  GH:%d  R:%d\n",
1308             CFrame->GlobalWidth,
1309             CFrame->GlobalHeight,
1310             CFrame->ResyncInterval);
1311           }
1312         for(i=0;i<CScan->NumberComponents;i++)  /* Print Scan info */
1313           {
1314           if (Notify)
1315             {
1316             printf(">> C:%d  N:%s  W:%d  H:%d  hf:%d  vf:%d\n",
1317               CScan->ci[i],
1318               CFrame->ComponentFileName[CScan->ci[i]],
1319               CFrame->Width[CScan->ci[i]],
1320               CFrame->Height[CScan->ci[i]],
1321               CFrame->hf[CScan->ci[i]],
1322               CFrame->vf[CScan->ci[i]]);
1323             }
1324           InstallIob(i);
1325           FlushIob();                        /* Close image files */
1326           SeekEndIob();
1327           CloseIob();
1328           }
1329         CurrentMDU=0;
1330         if (ScreenAllMarker()<0)            /* See if any more images*/
1331           {
1332           WHEREAMI();
1333           printf("No trailing marker found!\n");
1334           exit(-1);
1335           }
1336         if ((EndofFile)||(EndofImage))      /* Nothing, then return */
1337           {
1338           srclose();
1339           break;
1340           }
1341         }
1342       }
1343     if (CFrame->Type==3)
1344       JpegLosslessDecodeScan();
1345     else
1346       JpegDecodeScan();
1347     }
1348 }
1349 
1350 /*BFUNC
1351 
1352 JpegLosslessDecodeScan() is used to losslessly decode a portion of the
1353 image called the scan.  This routine uses the internal lossless
1354 buffers to reduce the overhead in writing.  However, one must note
1355 that the overhead is mostly in the Huffman decoding.
1356 
1357 EFUNC*/
1358 
JpegLosslessDecodeScan()1359 static void JpegLosslessDecodeScan()
1360 {
1361   BEGIN("JpegLosslessDecodeScan")
1362   int j,v,h,value,px;
1363   int height,horfreq,width;
1364   int MaxElem,CurrentElem,NumberElem;
1365   int StartofLine=1,UseType=1;              /* Start with type 1 coding */
1366   int *input;
1367 
1368   PointTransform=CScan->SAL;
1369   for(j=0;j<CScan->NumberComponents;j++)    /* Important to rewind to start */
1370     {                                       /* for lossless coding... */
1371       InstallIob(j);
1372       RewindIob();
1373     }
1374   if (CScan->NumberComponents==1)       /* Calculate maximum number of */
1375     MaxElem= LOSSLESSBUFFERSIZE/4;      /* elements can be loaded in */
1376   else
1377     {
1378     MaxElem= LOSSLESSBUFFERSIZE/
1379       ((CFrame->vf[CScan->ci[0]]+1)*(CFrame->hf[CScan->ci[0]]+1));
1380     for(j=1;j<CScan->NumberComponents;j++)          /* Rewind to start */
1381       {
1382       v=LOSSLESSBUFFERSIZE/
1383         ((CFrame->vf[CScan->ci[j]]+1)*(CFrame->hf[CScan->ci[j]]+1));
1384       if (v < MaxElem) MaxElem=v;
1385       }
1386     }
1387   InstallIob(0);
1388   UseDCHuffman(CScan->td[0]);          /* Install DC table */
1389   if (CScan->NumberComponents==1)
1390     height=horfreq=1;
1391   else
1392     {
1393       height=CFrame->vf[CScan->ci[0]];
1394       horfreq=CFrame->hf[CScan->ci[0]];
1395     }
1396   if ((CFrame->ResyncInterval)&&(CFrame->ResyncInterval % CScan->MDUWide))
1397     {
1398       WHEREAMI();
1399       printf("Resync Interval not an integer multiple of MDU's wide.\n");
1400       printf("Proceeding anyways.\n");
1401       if (MaxElem>=CFrame->ResyncInterval)
1402         MaxElem=CFrame->ResyncInterval;       /* Reduce to resync interval */
1403       else
1404         MaxElem=1;                            /* Can't proceed quickly */
1405     }
1406   CurrentElem=NumberElem=0;
1407   while(1)
1408     {
1409     if ((NumberMDU<0)&&(!(CurrentMDU%CScan->MDUWide)))
1410       {
1411       if (CheckMarker()==0xdc)
1412         ScreenMarker();
1413       }
1414     if (NumberMDU>=0)               /* If NumberMDU is positive proceed */
1415       {
1416       if (CurrentMDU >= NumberMDU) /* If all decoded */
1417         return;
1418       }
1419 
1420     if (CFrame->ResyncInterval)                /* Flag to decoder stream */
1421       ResyncEnable = 1;
1422     if (CurrentMDU && (CFrame->ResyncInterval))
1423       {                                    /* If resync interval */
1424       if ((CurrentMDU % CFrame->ResyncInterval)==0)
1425         {
1426         if (!CleartoResync)               /* If not in error recovery*/
1427           ReadResync();                          /* read resync. */
1428         if (CleartoResync)
1429           {
1430           /*
1431           Clear until we have LastKnownResync:
1432           the offset is by 1 because we add the resync i%8
1433           _after_ we code the ith resync interval...
1434            */
1435           if (((CurrentMDU/CFrame->ResyncInterval)&0x07)==
1436             ((LastKnownResync+1)&0x07))
1437             CleartoResync = 0;   /* Finished with resync clearing */
1438           }
1439         UseType=1;                             /* Reset codec */
1440         for(j=0;j<CScan->NumberComponents;j++) /* reset line buffers */
1441           {                                    /* Type is previous pel */
1442           InstallIob(j);
1443           LineResetBuffers();
1444           }
1445         }
1446       }
1447     if (!(CurrentMDU%CScan->MDUWide)&&(CurrentMDU))  /* Reset CScan type */
1448       {
1449       UseType=2;                            /* Start of line */
1450       StartofLine=1;                        /* uses top pel predictor */
1451       }
1452 
1453     if (CurrentElem>=NumberElem)
1454       {
1455       NumberElem = MIN((CScan->MDUWide-(CurrentMDU%CScan->MDUWide)),
1456         MaxElem);
1457       CurrentElem=0;
1458       for(j=0;j<CScan->NumberComponents;j++)
1459         {
1460         InstallIob(j);                    /* Install component j */
1461         ReadPreambleLine(NumberElem,     /* Read in some elements*/
1462           CScan->LosslessBuffer[j]);
1463         }
1464       }
1465     if (CScan->NumberComponents==1)
1466       {
1467       width=horfreq*NumberElem+1;
1468       input = &CScan->LosslessBuffer[0][CurrentElem];
1469       switch(UseType) /* Same as lossless coding predictor*/
1470         {
1471       case 1:
1472         px = input[width];
1473         break;
1474       case 2:
1475         px = input[1];
1476         break;
1477       case 3:
1478         px = input[0];
1479         break;
1480       case 4:
1481         px = input[width] + input[1] - input[0];
1482         break;
1483       case 5:
1484         px = input[width] + ((input[1] - input[0])>>1);
1485         break;
1486       case 6:
1487         px = input[1] + ((input[width] - input[0])>>1);
1488         break;
1489       case 7:
1490         px = (input[1] + input[width])>>1;  /* No rounding */
1491         break;
1492       default:
1493         WHEREAMI();
1494         printf("Lossless mode %d not supported.\n",UseType);
1495         break;
1496         }
1497       if (CleartoResync)         /* If CleartoResync, flush */
1498         input[width+1] = 0;
1499       else
1500         {
1501         value = LosslessDecodeDC();
1502         input[width+1] = (value+px)&0xffff;
1503         if (Loud > MUTE)
1504           {
1505           printf("OUT=%d  PX=%d  VAL: %d\n",
1506             input[width+1],px,value);
1507           }
1508         }
1509       }
1510     else
1511       {
1512       for(j=0;j<CScan->NumberComponents;j++)   /* Decode MDU */
1513         {
1514         if (Loud > MUTE)
1515           {
1516           WHEREAMI();
1517           printf("[Decoder Pass [Component:MDU:#MDU] [%d:%d:%d]]\n",
1518             j,CurrentMDU,NumberMDU);
1519           }
1520         InstallIob(j);                     /* Install component */
1521         height=CFrame->vf[CScan->ci[j]];
1522         horfreq=CFrame->hf[CScan->ci[j]];
1523         width=horfreq*NumberElem+1;
1524         input = &CScan->LosslessBuffer[j][CurrentElem*horfreq];
1525         UseDCHuffman(CScan->td[j]);          /* Install DC table */
1526         for(v=1;v<=height;v++)
1527           {
1528           for(h=1;h<=horfreq;h++)
1529             {
1530             switch(UseType) /* Same as lossless coding predictor*/
1531               {
1532             case 1:
1533               px = input[(v*(width))+h-1];
1534               break;
1535             case 2:
1536               px = input[((v-1)*(width))+h];
1537               break;
1538             case 3:
1539               px = input[((v-1)*(width))+h-1];
1540               break;
1541             case 4:
1542               px = input[(v*(width))+h-1] +
1543                 input[((v-1)*(width))+h] -
1544                 input[((v-1)*(width))+h-1];
1545               break;
1546             case 5:
1547               px = input[(v*(width))+h-1] +
1548                 ((input[((v-1)*(width))+h] -
1549                   input[((v-1)*(width))+h-1])>>1);
1550               break;
1551             case 6:
1552               px = input[((v-1)*(width))+h] +
1553                 ((input[(v*(width))+h-1] -
1554                   input[((v-1)*(width))+h-1])>>1);
1555               break;
1556             case 7:
1557               px = (input[((v-1)*(width))+h] +
1558                 input[(v*(width))+h-1])>>1;
1559               break;
1560             default:
1561               WHEREAMI();
1562               printf("Lossless mode %d not supported.\n",
1563                 UseType);
1564               break;
1565               }
1566             if (CleartoResync)         /* If CleartoResync, flush */
1567               input[(v*(width))+h] = 0;
1568             else
1569               {
1570               value = LosslessDecodeDC();
1571               input[(v*(width))+h] = (value+px)&0xffff;
1572               if (Loud > MUTE)
1573                 {
1574                 printf("OUT=%d  PX=%d  VAL: %d\n",
1575                   input[(v*(width))+h],px,value);
1576                 }
1577               }
1578             }
1579           }
1580         }
1581       }
1582     CurrentElem++;
1583     if (CurrentElem>=NumberElem)
1584       {
1585       for(j=0;j<CScan->NumberComponents;j++)
1586         {
1587         InstallIob(j);                    /* Install component j */
1588         WriteLine(NumberElem,             /* Write out elements*/
1589           CScan->LosslessBuffer[j]);
1590         }
1591       }
1592     CurrentMDU++;
1593     if (StartofLine)
1594       {
1595       UseType=CScan->SSS;
1596       StartofLine=0;
1597       }
1598     }
1599 }
1600 
1601 /*BFUNC
1602 
1603 JpegDecodeScan() is used to decode a portion of the image called the
1604 scan.  Everything  is read upon getting to this stage.
1605 
1606 EFUNC*/
1607 
JpegDecodeScan()1608 static void JpegDecodeScan()
1609 {
1610   BEGIN("JpegDecodeScan")
1611   int j,v,h,dovf,dohf;
1612   int input[64],output[64];
1613   int IDCTBound,IDCTShift;
1614 
1615   while(1)
1616     {
1617     if ((NumberMDU<0)&&(!(CurrentMDU%CScan->MDUWide)))
1618       {
1619       if (CheckMarker()==0xdc)
1620         ScreenMarker();
1621       }
1622     if (NumberMDU>=0)               /* If NumberMDU is positive proceed */
1623       {
1624       if (CurrentMDU >= NumberMDU) /* If all decoded */
1625         return;
1626       }
1627     if (CFrame->ResyncInterval)                /* Flag to decoder stream */
1628       {
1629       ResyncEnable = 1;
1630       }
1631     if (CurrentMDU && (CFrame->ResyncInterval))
1632       {                                    /* If resync interval */
1633       if ((CurrentMDU % CFrame->ResyncInterval)==0)
1634         {
1635         if (!CleartoResync)               /* If not in error recovery*/
1636           {                               /* read resync. */
1637           ReadResync();
1638           }
1639         if (CleartoResync)
1640           {
1641           /*
1642           Clear until we have LastKnownResync:
1643           the offset is by 1 because we add the resync i%8
1644           _after_ we code the ith resync interval...
1645            */
1646           if (((CurrentMDU/CFrame->ResyncInterval)&0x07)==
1647             ((LastKnownResync+1)&0x07))
1648             {
1649             CleartoResync = 0;   /* Finished with resync clearing */
1650             }
1651           }
1652         ResetCodec();                /* Reset codec */
1653         }
1654       }
1655     IDCTBound=((CFrame->DataPrecision>8)?4095:255);
1656     IDCTShift=((CFrame->DataPrecision>8)?2048:128);
1657     for(j=0;j<CScan->NumberComponents;j++)   /* Decode MDU */
1658       {
1659       if (Loud > MUTE)
1660         {
1661         WHEREAMI();
1662         printf("[Decoder Pass [Component:MDU:#MDU] [%d:%d:%d]]\n",
1663           j,CurrentMDU,NumberMDU);
1664         }
1665       InstallPrediction(j);             /* Install component */
1666       InstallIob(j);
1667       if (CScan->NumberComponents==1) /* Check for non-interleaved mode */
1668         dohf=dovf=1;
1669       else
1670         {
1671         dohf = CFrame->hf[CScan->ci[j]];
1672         dovf = CFrame->vf[CScan->ci[j]];
1673         }
1674       for(v=0;v<dovf;v++) /* Do for blocks in MDU*/
1675         {
1676         for(h=0;h<dohf;h++)
1677           {
1678           if (CleartoResync)             /* CleartoResync, flush */
1679             ClearMatrix(input);
1680           else
1681             {
1682             UseDCHuffman(CScan->td[j]);  /* Install DC table */
1683             *input = DecodeDC();         /* Decode DC */
1684             UseACHuffman(CScan->ta[j]);  /* Install AC table */
1685             DecodeAC(input);             /* Decode AC */
1686             if (Loud > TALK)
1687               {
1688               printf("Cooked Input\n");
1689               PrintMatrix(input);
1690               }
1691             IZigzagMatrix(input,output);   /* Inverse zigzag */
1692             IQuantize(output,              /* Inverse quantize */
1693               CImage->
1694               QuantizationMatrices[CFrame->
1695               tq[CScan->ci[j]]]);
1696             DefaultIDct(output,input);     /* Inverse DCT */
1697             PostshiftIDctMatrix(input,IDCTShift);
1698             /* Shift (all positive)*/
1699             BoundIDctMatrix(input,IDCTBound); /* Bound */
1700             if (Loud > WHISPER)
1701               {
1702               printf("Raw Output\n");
1703               PrintMatrix(input);
1704               }
1705             }
1706           WriteBlock(input);                 /* Write out */
1707           }
1708         }
1709       }
1710     CurrentMDU++;
1711     }
1712 }
1713 
1714 /*BFUNC
1715 
1716 PrintImage() prints out the Image structure of the CURRENT image.  It
1717 is primarily used for debugging. The image structure consists of the
1718 data that is held to be fixed even though multiple scans (or multiple
1719 frames, even though it is not advertised as such by JPEG) are
1720 received.
1721 
1722 EFUNC*/
1723 
PrintImage()1724 void PrintImage()
1725 {
1726   BEGIN("PrintImage")
1727   int i;
1728 
1729   printf("*** Image ID: %p ***\n",(void*)CImage); /* %p should work ... */
1730   if (CImage)
1731     {
1732     if (CImage->StreamFileName)
1733       {
1734       printf("StreamFileName %s\n",(CImage->StreamFileName ?
1735           CImage->StreamFileName :
1736           "Null"));
1737       }
1738     printf("InternalMode: %d   ImageSequence: %d\n",
1739       CImage->JpegMode,CImage->ImageSequence);
1740     printf("NumberQuantizationMatrices %d\n",
1741       CImage->NumberQuantizationMatrices);
1742     for(i=0;i<CImage->NumberQuantizationMatrices;i++)
1743       {
1744       printf("Quantization Matrix [%d]\n",i);
1745       PrintMatrix(CImage->QuantizationMatrices[i]);
1746       }
1747     printf("NumberDCTables %d\n",
1748       CImage->NumberDCTables);
1749     for(i=0;i<CImage->NumberDCTables;i++)
1750       {
1751       printf("DC Huffman Table[%d]\n",i);
1752       UseDCHuffman(i);
1753       PrintHuffman();
1754       }
1755     printf("NumberACTables %d\n",
1756       CImage->NumberACTables);
1757     for(i=0;i<CImage->NumberACTables;i++)
1758       {
1759       printf("AC Huffman Table[%d]\n",i);
1760       UseACHuffman(i);
1761       PrintHuffman();
1762       }
1763     }
1764 }
1765 
1766 /*BFUNC
1767 
1768 PrintFrame() is used to print the information specific to loading in
1769 the frame. This corresponds roughly to the information received by the
1770 SOF marker code.
1771 
1772 EFUNC*/
1773 
PrintFrame()1774 void PrintFrame()
1775 {
1776   BEGIN("PrintFrame")
1777   int i;
1778 
1779   printf("*** Frame ID: %p *** (TYPE: %d)\n",(void*)CFrame,CFrame->Type);
1780   if (CFrame)
1781     {
1782     printf("DataPrecision: %d  ResyncInterval: %d\n",
1783       CFrame->DataPrecision,CFrame->ResyncInterval);
1784     printf("Height: %d   Width: %d\n",
1785       CFrame->GlobalHeight,CFrame->GlobalWidth);
1786     printf("BufferSize: %d  Image: %p\n",CFrame->BufferSize,(void*)CFrame->Image);
1787     printf("NumberComponents %d\n",
1788       CFrame->GlobalNumberComponents);
1789     for(i=0;i<CFrame->GlobalNumberComponents;i++)
1790       {
1791       printf("ComponentFileName %s\n",
1792         ((CFrame->ComponentFileName[CFrame->cn[i]]) ?
1793          CFrame->ComponentFileName[CFrame->cn[i]] : "Null"));
1794       printf("HorizontalFrequency: %d  VerticalFrequency: %d\n",
1795         CFrame->hf[CFrame->cn[i]],CFrame->vf[CFrame->cn[i]]);
1796       printf("Height: %d  Width: %d\n",
1797         CFrame->Height[CFrame->cn[i]],CFrame->Width[CFrame->cn[i]]);
1798       InstallIob(i);
1799       PrintIob();
1800       }
1801     }
1802 }
1803 
1804 /*BFUNC
1805 
1806 PrintScan() is used to print the information in the CScan structure.
1807 This roughly corresponds to the information received by the Scan
1808 marker code.
1809 
1810 EFUNC*/
1811 
PrintScan()1812 void PrintScan()
1813 {
1814   BEGIN("PrintScan")
1815   int i;
1816 
1817   printf("*** Scan ID: %p ***\n",(void*)CScan);
1818   if (CScan)
1819     {
1820     printf("NumberComponents %d\n",
1821       CScan->NumberComponents);
1822     for(i=0;i<CScan->NumberComponents;i++)
1823       {
1824       printf("Component: %d  Index: %d\n",
1825         i,CScan->ci[i]);
1826       printf("DC Huffman Table: %d  AC Huffman Table: %d\n",
1827         CScan->td[i],CScan->ta[i]);
1828       printf("LastDC: %d  Iob: %p\n",
1829         *(CScan->LastDC[i]),(void*)CScan->Iob[i]);
1830       }
1831     printf("NumberACSend: %d  NumberDCSend: %d  NumberQSend: %d\n",
1832       CScan->NumberACTablesSend,
1833       CScan->NumberDCTablesSend,
1834       CScan->NumberQTablesSend);
1835     }
1836 }
1837 
1838 /*BFUNC
1839 
1840 MakeImage() makes an image and puts it into the Current Image pointer
1841 (CImage). It initializes the structure appropriate to the JPEG initial
1842 specifications.
1843 
1844 EFUNC*/
1845 
MakeImage()1846 void MakeImage()
1847 {
1848   BEGIN("MakeImage")
1849 
1850   if (!(CImage = MakeStructure(IMAGE)))
1851     {
1852       WHEREAMI();
1853       printf("Cannot allocate memory for Image structure.\n");
1854       exit(ERROR_MEMORY);
1855     }
1856   CImage->StreamFileName = NULL;
1857   CImage->JpegMode = 0;
1858   CImage->Jfif=0;
1859   CImage->ImageSequence = -1;        /* First element in sequence is 0 */
1860   CImage->NumberQuantizationMatrices = 2;  /* Default # matrices is 2 */
1861   CImage->QuantizationMatrices[0] = LuminanceQuantization;
1862   CImage->QuantizationMatrices[1] = ChrominanceQuantization;
1863   CImage->NumberACTables = 0;       /* No tables defined yet */
1864   CImage->NumberDCTables = 0;
1865 }
1866 
1867 /*BFUNC
1868 
1869 MakeFrame() constructs a Frame Structure and puts it in the Current
1870 Frame pointer (CFrame).
1871 
1872 EFUNC*/
1873 
MakeFrame()1874 void MakeFrame()
1875 {
1876   BEGIN("MakeFrame")
1877   int i;
1878 
1879   if (!(CFrame = MakeStructure(FRAME)))
1880     {
1881       WHEREAMI();
1882       printf("Cannot allocate memory for Frame structure.\n");
1883       exit(ERROR_MEMORY);
1884     }
1885   CFrame->Type=0;                   /* Baseline type */
1886   CFrame->InsertDnl = 0;            /* Set to default position */
1887   CFrame->Q = 0;
1888   CFrame->tmpfile = 0;
1889   CFrame->GlobalHeight = 0;
1890   CFrame->GlobalWidth = 0;
1891   CFrame->DataPrecision = 8;         /* Default 8 precision */
1892   CFrame->ResyncInterval = 0;
1893   CFrame->GlobalNumberComponents = 0;
1894   for(i=0;i<MAXIMUM_COMPONENTS;i++)
1895     {
1896       CFrame->cn[i] = 0;           /* Clean out all slots */
1897       CFrame->hf[i] = 0;
1898       CFrame->vf[i] = 0;
1899       CFrame->tq[i] = 0;
1900       CFrame->Height[i] = 0;
1901       CFrame->Width[i] = 0;
1902       CFrame->ComponentFileName[i] = 0;
1903     }
1904   CFrame->BufferSize = BUFFERSIZE;
1905   CFrame->Image = CImage;
1906 }
1907 
1908 /*BFUNC
1909 
1910 MakeScanFrequency() constructs a set of scan information for the
1911 current variables. These frequency markers are used for creating the
1912 JPEG custom matrices.
1913 
1914 EFUNC*/
1915 
MakeScanFrequency()1916 void MakeScanFrequency()
1917 {
1918   BEGIN("MakeScanFrequency")
1919   int i;
1920 
1921   for(i=0;i<MAXIMUM_SOURCES;i++)
1922     {
1923     if (!(CScan->LastDC[i] = MakeStructure(int)))
1924       {
1925       WHEREAMI();
1926       printf("Cannot allocate LastDC integer store.\n");
1927       exit(ERROR_MEMORY);
1928       }
1929     if (!(CScan->ACFrequency[i] = (int *) calloc(257,sizeof(int))))
1930       {
1931       WHEREAMI();
1932       printf("Cannot allocate AC Frequency array.\n");
1933       exit(ERROR_MEMORY);
1934       }
1935     if (!(CScan->DCFrequency[i] = (int *) calloc(257,sizeof(int))))
1936       {
1937       WHEREAMI();
1938       printf("Cannot allocate DC Frequency array.\n");
1939       exit(ERROR_MEMORY);
1940       }
1941     }
1942 }
1943 
1944 /*BFUNC
1945 
1946 MakeScan() is used for creating the Scan structure which holds most of
1947 the information in the Scan marker code.
1948 
1949 EFUNC*/
1950 
MakeScan()1951 void MakeScan()
1952 {
1953   BEGIN("MakeScan")
1954   int i;
1955 
1956   if (!(CScan = MakeStructure(SCAN)))
1957     {
1958       WHEREAMI();
1959       printf("Cannot allocate memory for Scan structure.\n");
1960       exit(ERROR_MEMORY);
1961     }
1962   CScan->NumberACTablesSend = 0;    /* Install with default values */
1963   CScan->NumberDCTablesSend = 0;
1964   CScan->NumberComponents = 0;
1965   for(i=0;i<MAXIMUM_SOURCES;i++)
1966     {
1967       CScan->ci[i] = 0;
1968       CScan->ta[i] = 0;
1969       CScan->td[i] = 0;
1970       CScan->sa[i] = 0;
1971       CScan->sd[i] = 0;
1972       CScan->sq[i] = 0;
1973     }
1974   CScan->SSS=0;
1975   CScan->SSE=0;
1976   CScan->SAH=0;
1977   CScan->SAL=0;
1978   MakeScanFrequency();
1979 }
1980 
1981 /*BFUNC
1982 
1983 MakeConsistentFileNames() is used to construct consistent filenames
1984 for opening and closing of data storage. It is used primarily by the
1985 decoder when all the files may not necessarily be specified.
1986 
1987 EFUNC*/
1988 
MakeConsistentFileNames()1989 void MakeConsistentFileNames()
1990 {
1991   BEGIN("MakeConsistentFileNames")
1992   int i;
1993 
1994   for(i=0;i<CScan->NumberComponents;i++)
1995     {
1996     if (CImage->ImageSequence)  /* If in sequence, must add sequence */
1997       {                         /* identifier */
1998       CFrame->ComponentFileName[CScan->ci[i]] =
1999         (char *) calloc(strlen(CImage->StreamFileName)+16,sizeof(char));
2000       sprintf(CFrame->ComponentFileName[CScan->ci[i]],"%s.%d.%d",
2001         CImage->StreamFileName,CImage->ImageSequence,CScan->ci[i]);
2002       }
2003     else if (CFrame->ComponentFileName[CScan->ci[i]] == NULL)
2004       {                        /* Otherwise if none specified, create. */
2005       CFrame->ComponentFileName[CScan->ci[i]] =
2006         (char *) calloc(strlen(CImage->StreamFileName)+8,sizeof(char));
2007       sprintf(CFrame->ComponentFileName[CScan->ci[i]],"%s.%d",
2008         CImage->StreamFileName,CScan->ci[i]);
2009       }
2010     }
2011 }
2012 
2013 /*BFUNC
2014 
2015 CheckValidity() checks whether the current values in CFrame and CScan
2016 meet the internal specifications for correctness and the algorithm
2017 can guarantee completion.
2018 
2019 EFUNC*/
2020 
CheckValidity()2021 void CheckValidity()
2022 {
2023   BEGIN("CheckValidity")
2024   int i;
2025 
2026   ErrorValue = 0;           /* Check if within internal specs */
2027   InBounds(CFrame->GlobalWidth,0,MAXIMUM_IMAGE_WIDTH,"Bad Image Width");
2028   InBounds(CFrame->GlobalHeight,0,MAXIMUM_IMAGE_HEIGHT,"Bad Image Height");
2029   if (CFrame->Q<0)
2030     {
2031       WHEREAMI();
2032       printf("Q factor is negative - must be positive\n");
2033     }
2034   if ((CFrame->DataPrecision!=8)&&(CFrame->DataPrecision!=12))
2035     {
2036     if (CImage->JpegMode == J_LOSSLESS)
2037       {
2038       if (CFrame->DataPrecision<=16)
2039         printf("Precision type: %d\n",CFrame->DataPrecision);
2040       else
2041         printf("Caution: precision type: %d greater than 16.\n",
2042           CFrame->DataPrecision);
2043       }
2044     else
2045       printf("Caution: precision type: %d not 8 or 12.\n",
2046         CFrame->DataPrecision);
2047     }
2048   InBounds(CScan->NumberComponents,1,15,"Bad Number of Components");
2049   for(i=0;i<CScan->NumberComponents;i++)
2050     {
2051     InBounds(CFrame->Width[CScan->ci[i]],0,MAXIMUM_IMAGE_WIDTH,
2052       "Bad Frame Width");
2053     InBounds(CFrame->Height[CScan->ci[i]],0,MAXIMUM_IMAGE_HEIGHT,
2054       "Bad Frame Height");
2055     InBounds(CFrame->hf[CScan->ci[i]],1,MAXIMUM_HORIZONTAL_FREQUENCY,
2056       "Bad Horizontal Frequency");
2057     InBounds(CFrame->vf[CScan->ci[i]],1,MAXIMUM_VERTICAL_FREQUENCY,
2058       "Bad Vertical Frequency");
2059     }
2060   InBounds(LosslessPredictorType,0,7,"Bad Lossless Predictor Type");
2061   if (PointTransform)
2062     {
2063     if (!(LosslessPredictorType))
2064       {
2065       WHEREAMI();
2066       printf("Point Transform specified without lossless prediction.\n");
2067       printf("Shifting of input/output should be anticipated.\n");
2068       }
2069     else
2070       InBounds(PointTransform,0,14,"Bad Point Transform");
2071     }
2072   if (ErrorValue)
2073     {
2074     WHEREAMI();
2075     printf("Invalid input detected.\n");
2076     exit(ErrorValue);
2077     }
2078 }
2079 
2080 /*BFUNC
2081 
2082 CheckBaseline() checks whether the internal values meet JPEG Baseline
2083 specifications.
2084 
2085 EFUNC*/
2086 
CheckBaseline()2087 int CheckBaseline()
2088 {
2089   BEGIN("CheckBaseline")
2090   int i;
2091 
2092   ErrorValue = 0;         /* Check for JPEG specs */
2093   InBounds(CFrame->GlobalWidth,0,MAXIMUM_IMAGE_WIDTH,"Bad Image Width");
2094   InBounds(CFrame->GlobalHeight,0,MAXIMUM_IMAGE_HEIGHT,"Bad Image Height");
2095   if (CFrame->Q<0)
2096     {
2097       WHEREAMI();
2098       printf("Q factor is negative - must be positive\n");
2099     }
2100   InBounds(CScan->NumberComponents,1,4,"Bad Number of Components");
2101   for(i=0;i<CScan->NumberComponents;i++)
2102     {
2103     InBounds(CFrame->Width[CScan->ci[i]],0,MAXIMUM_IMAGE_WIDTH,
2104       "Bad Frame Width");
2105     InBounds(CFrame->Height[CScan->ci[i]],0,MAXIMUM_IMAGE_HEIGHT,
2106       "Bad Frame Height");
2107     InBounds(CFrame->hf[CScan->ci[i]],1,MAXIMUM_JPEG_HORIZONTAL_FREQUENCY,
2108       "Bad Horizontal Frequency");
2109     InBounds(CFrame->vf[CScan->ci[i]],1,MAXIMUM_JPEG_VERTICAL_FREQUENCY,
2110       "Bad Vertical Frequency");
2111     }
2112   if (ErrorValue)
2113     {
2114       printf("Caution: JPEG++ Mode.\n");
2115       ErrorValue = 0;
2116     }
2117   return 0;
2118 }
2119 
2120 /*BFUNC
2121 
2122 ConfirmFileSize() checks to see if the files used in the scan actually
2123 exist and correspond in size to the input given.
2124 
2125 EFUNC*/
2126 
ConfirmFileSize()2127 void ConfirmFileSize()
2128 {
2129   BEGIN("ConfirmFileSize")
2130   int i,FileSize;
2131   FILE *test;
2132 
2133   for(i=0;i<CScan->NumberComponents;i++)  /* Do for all components in scan*/
2134     {
2135     if (CFrame->ComponentFileName[CScan->ci[i]])
2136       {
2137       if ((test = fopen(CFrame->ComponentFileName[CScan->ci[i]],
2138             "rb")) == NULL)
2139         {
2140         WHEREAMI();
2141         printf("Cannot open filename %s\n",
2142           CFrame->ComponentFileName[CScan->ci[i]]);
2143         exit(ERROR_BOUNDS);
2144         }
2145       fseek(test,0,2);                /* Go to end */
2146       FileSize = ftell(test);         /* Find number of bytes */
2147       rewind(test);
2148       if (CFrame->Height[CScan->ci[i]] == 0)  /* Must have good dimens*/
2149         {
2150         if (CFrame->Width[CScan->ci[i]] == 0)
2151           {
2152           WHEREAMI();
2153           printf("Bad file specification in %s.\n",
2154             CFrame->ComponentFileName[CScan->ci[i]]);
2155           }
2156         else
2157           {
2158           CFrame->Height[CScan->ci[i]] = FileSize /
2159             (CFrame->Width[CScan->ci[i]]*
2160              ((CFrame->DataPrecision>8)?2:1));
2161           WHEREAMI();
2162           printf("Autosizing height to %d\n",
2163             CFrame->Height[CScan->ci[i]]);
2164           }
2165         }                                 /* Dimensions must conform */
2166       if (FileSize !=
2167         CFrame->Width[CScan->ci[i]] * CFrame->Height[CScan->ci[i]]*
2168         ((CFrame->DataPrecision>8)?2:1))
2169         {
2170         WHEREAMI();
2171         printf("File size conflict in %s, est: %d  act: %d \n",
2172           CFrame->ComponentFileName[CScan->ci[i]],
2173           CFrame->Width[CScan->ci[i]]*CFrame->Height[CScan->ci[i]]*
2174           ((CFrame->DataPrecision>8)?2:1),
2175           FileSize);
2176         exit(ERROR_BOUNDS);
2177         }
2178       fclose(test);
2179       }
2180     }
2181 }
2182 
2183 /*BFUNC
2184 
2185 Help() prints out general information regarding the use of this
2186 JPEG software.
2187 
2188 EFUNC*/
2189 
Help()2190 static void Help()
2191 {
2192   BEGIN("Help")
2193 
2194   printf("jpeg -iw ImageWidth -ih ImageHeight [-JFIF] [-q(l) Q-Factor]\n");
2195   printf("     [-a] [-b] [-d] [-k predictortype] [-n] [-o] [-y] [-z]\n");
2196   printf("     [-p PrecisionValue] [-t pointtransform]\n");
2197   printf("     [-r ResyncInterval] [-s StreamName]\n");
2198   printf("     [[-ci ComponentIndex1] [-fw FrameWidth1] [-fh FrameHeight1]\n");
2199   printf("      [-hf HorizontalFrequency1] [-vf VerticalFrequency1]\n");
2200   printf("      ComponentFile1]\n");
2201   printf("     [[-ci ComponentIndex2] [-fw FrameWidth2] [-fh FrameHeight2]\n");
2202   printf("      [-hf HorizontalFrequency2] [-vf VerticalFrequency2]\n");
2203   printf("      ComponentFile1]\n");
2204   printf("     ....\n\n");
2205   printf("-JFIF puts a JFIF marker. Don't change component indices.\n");
2206   printf("-a enables Reference DCT.\n");
2207   printf("-b enables Lee DCT.\n");
2208   printf("-d decoder enable.\n");
2209   printf("-[k predictortype] enables lossless mode.\n");
2210   printf("-q specifies quantization factor; -ql specifies can be long.\n");
2211   printf("-n enables non-interleaved mode.\n");
2212   printf("-[t pointtransform] is the number of bits for the PT shift.\n");
2213   printf("-o enables the Command Interpreter.\n");
2214   printf("-p specifies precision.\n");
2215   printf("-y run in robust mode against errors (cannot be used with DNL).\n");
2216   printf("-z uses default Huffman tables.\n");
2217 }
2218 
2219 /*END*/
2220