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