pvrg-jpeg-1.2.1/0000755000175000017500000000000011247511534012761 5ustar naolivnaolivpvrg-jpeg-1.2.1/jpeg.c0000644000175000017500000017163605725223001014061 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ /* ************************************************************ jpeg.c This file contains the main calling routines for the JPEG coder. ************************************************************ */ /*LABEL jpeg.c */ /* Include files. */ #include "tables.h" #include "globals.h" #ifdef SYSV #include #endif /* Define the functions to be used with ANSI prototyping. */ /*PUBLIC*/ int main(); static void JpegEncodeFrame(); static void JpegDecodeFrame(); static void JpegDecodeScan(); static void JpegLosslessDecodeScan(); static void Help(); extern void PrintImage(); extern void PrintFrame(); extern void PrintScan(); extern void MakeImage(); extern void MakeFrame(); extern void MakeScanFrequency(); extern void MakeScan(); extern void MakeConsistentFileNames(); extern void CheckValidity(); extern int CheckBaseline(); extern void ConfirmFileSize(); extern void JpegQuantizationFrame(); extern void JpegDefaultHuffmanScan(); extern void JpegFrequencyScan(); extern void JpegCustomScan(); extern void JpegEncodeScan(); extern void JpegLosslessFrequencyScan(); extern void JpegLosslessEncodeScan(); /*PRIVATE*/ /* These variables occur in the stream definition. */ extern int CleartoResync; extern int LastKnownResync; extern int ResyncEnable; extern int ResyncCount; extern int EndofFile; extern int EndofImage; /* Define the parameter passing structures. */ IMAGE *CImage=NULL; /* Current Image variables structure */ FRAME *CFrame=NULL; /* Current Frame variables structure */ SCAN *CScan=NULL; /* Current Scan variables structure */ /* Define the MDU counters. */ int CurrentMDU=0; /* Holds the value of the current MDU */ int NumberMDU=0; /* This number is the number of MDU's */ /* Define Lossless info */ int LosslessPredictorType=0; /* The lossless predictor used */ int PointTransform=0; /* This parameter affects the shifting in io.c */ /* How we break things up */ int ScanComponentThreshold=SCAN_COMPONENT_THRESHOLD; /* Define the support/utility variables.*/ int ErrorValue=0; /* Holds error upon return */ int Loud=MUTE; /* Loudness gives level of debug traces */ int HuffmanTrace=NULL; /* When set, dumps Huffman statistics */ int Notify=1; /* When set, gives image size feedback */ int Robust=0; static int LargeQ=0; /* When set, large quantization is enabled */ /* We default to the Chen DCT algorithm. */ vFunc *UseDct = ChenDct; /* This is the DCT algorithm to use */ vFunc *UseIDct = ChenIDct; /* This is the inverse DCT algorithm to use */ /* Add some macros to ease readability. */ #define DefaultDct (*UseDct) #define DefaultIDct (*UseIDct) /*START*/ /*BFUNC main() is first called by the shell routine upon execution of the program. EFUNC*/ int main(argc,argv) int argc; char **argv; { BEGIN("main"); int i,ComponentIndex; int Oracle=0; /* Oracle means that we use the lexer interactively */ MakeImage(); /* Construct the image structures */ MakeFrame(); MakeScan(); if (argc == 1) /* No arguments then print help info */ { Help(); exit(-1); } ComponentIndex=1; /* Start with index 1 (Could be zero, but JFIF compat) */ for(i=1;iJfif=1; else if (!strcmp(argv[i],"-ci")) ComponentIndex=atoi(argv[++i]); else if (*(argv[i]) == '-') /* Strip off first "dash" */ { switch(*(++argv[i])) { case 'a': /* -a Reference DCT */ UseDct = ReferenceDct; UseIDct = ReferenceIDct; break; case 'b': /* -b Lee DCT */ UseDct = LeeDct; UseIDct = LeeIDct; break; case 'd': /* -d Decode */ CImage->JpegMode = J_DECODER; break; case 'k': /* -k Lossless mode */ CImage->JpegMode = J_LOSSLESS; CFrame->Type=3; LosslessPredictorType = atoi(argv[++i]); break; case 'f': switch(*(++argv[i])) { case 'w': /* -fw Frame width */ CFrame->Width[ComponentIndex] = atoi(argv[++i]); break; case 'h': /* -fh Frame height */ CFrame->Height[ComponentIndex] = atoi(argv[++i]); break; default: WHEREAMI(); printf("Illegal option: f%c.\n", *argv[i]); exit(ERROR_BOUNDS); break; } break; case 'i': switch(*(++argv[i])) { case 'w': /* -iw Image width */ CFrame->GlobalWidth = atoi(argv[++i]); break; case 'h': /* -ih Image height */ CFrame->GlobalHeight = atoi(argv[++i]); break; default: WHEREAMI(); printf("Illegal option: i%c.\n", *argv[i]); exit(ERROR_BOUNDS); break; } break; case 'h': /* -h horizontal frequency */ CFrame->hf[ComponentIndex] = atoi(argv[++i]); break; #ifndef PRODUCTION_VERSION case 'l': /* -l loudness for debugging */ Loud = atoi(argv[++i]); break; #endif case 'n': /* Set non-interleaved mode */ ScanComponentThreshold=1; break; case 'o': /* -o Oracle mode (input parsing)*/ Oracle=1; break; case 'p': CFrame->DataPrecision = atoi(argv[++i]); if (!CFrame->Type) CFrame->Type = 1; break; case 'r': /* -r resynchronization */ CFrame->ResyncInterval = atoi(argv[++i]); break; case 'q': /* -q Q factor */ if (*(++argv[i])=='l') LargeQ=1; CFrame->Q = atoi(argv[++i]); break; case 'v': /* -v vertical frequency */ CFrame->vf[ComponentIndex] = atoi(argv[++i]); break; case 's': /* -s stream file name */ CImage->StreamFileName = argv[++i]; break; case 't': PointTransform=atoi(argv[++i]); break; #ifndef PRODUCTION_VERSION case 'x': /* -x trace */ HuffmanTrace = 1; break; #endif case 'u': /* -u disable width/size output */ Notify=0; break; case 'y': Robust=1; break; case 'z': /* -z use default Huffman */ CImage->JpegMode |= J_DEFAULTHUFFMAN; break; default: WHEREAMI(); printf("Illegal option in command line: %c.\n", *argv[i]); exit(ERROR_BOUNDS); break; } } else /* If not a "-" then a filename */ { CFrame->cn[CFrame->GlobalNumberComponents++]= ComponentIndex; if (!CFrame->vf[ComponentIndex]) CFrame->vf[ComponentIndex]=1; if (!CFrame->hf[ComponentIndex]) CFrame->hf[ComponentIndex]=1; CFrame->ComponentFileName[ComponentIndex] = argv[i]; ComponentIndex++; } } if (Oracle) /* If Oracle set */ { initparser(); /* Initialize interactive parser */ parser(); /* parse input from stdin */ exit(ErrorValue); } /* Otherwise act on information */ if (!(GetFlag(CImage->JpegMode,J_DECODER)) && /* Check for files */ (CFrame->GlobalNumberComponents == 0)) { WHEREAMI(); printf("No component file specified.\n"); exit(ERROR_BOUNDS); } if (CImage->StreamFileName == NULL) /* Check for stream name */ { if (CFrame->ComponentFileName[CFrame->cn[0]]) /* If doesn't exist */ { /* Create one. */ CImage->StreamFileName = (char *) calloc(strlen(CFrame->ComponentFileName[CFrame->cn[0]])+6, sizeof(char)); sprintf(CImage->StreamFileName,"%s.jpg", CFrame->ComponentFileName[CFrame->cn[0]]); } else { WHEREAMI(); printf("No stream filename.\n"); exit(ERROR_BOUNDS); } } if (GetFlag(CImage->JpegMode,J_DECODER)) /* If decoder flag set then */ { /* decode frame. */ JpegDecodeFrame(); } else { if (!(CFrame->GlobalWidth) || !(CFrame->GlobalHeight)) /* Dimensions ? */ { WHEREAMI(); printf("Unspecified frame size.\n"); exit(ERROR_BOUNDS); } swopen(CImage->StreamFileName,0); /* Open output file, index 0*/ JpegEncodeFrame(); /* Encode the frame */ swclose(); /* Flush remaining bits */ } exit(ErrorValue); } /*BFUNC JpegEncodeFrame() handles the basic encoding of the routines provided that CFrame and CImage are set up properly. It creates the appropriate CScan to handle the intermediate variables. EFUNC*/ static void JpegEncodeFrame() { BEGIN("JpegEncodeFrame"); int i,CurrentComponent; CurrentComponent=0; /* Write start of image, start of frame */ WriteSoi(); if (CImage->Jfif) WriteJfif(); /* Write JFIF marker if necessary */ MakeConsistentFrameSize(); /* Do it here when everything defined */ JpegQuantizationFrame(); /* Set up quantization matrices */ WriteSof(); if (CFrame->ResyncInterval) /* If resync enabled put DRI marker */ { WriteDri(); } while(1) /* This loop breaks up a large number of */ { /* components into small scans */ if (CFrame->GlobalNumberComponents<=CurrentComponent) { break; /* All encoded */ } else if (CFrame->GlobalNumberComponents-CurrentComponent <= ScanComponentThreshold) { /* If less/equal to (SCT) components do it */ CScan->NumberComponents = CFrame->GlobalNumberComponents-CurrentComponent; for(i=0;CurrentComponentGlobalNumberComponents; CurrentComponent++,i++) { CScan->ci[i]=CFrame->cn[CurrentComponent]; } } else { /* Break into (SCT) componets */ CScan->NumberComponents = ScanComponentThreshold; for(i=0;ici[i]=CFrame->cn[CurrentComponent]; } } CheckValidity(); /* Check validity */ CheckBaseline(); /* See if type is correct */ if (Loud > MUTE) { PrintImage(); PrintFrame(); PrintScan(); } ConfirmFileSize(); /* Does files on disk agree? */ if (GetFlag(CImage->JpegMode,J_LOSSLESS)) { MakeIob(IOB_LINE,O_RDONLY, ((CFrame->DataPrecision>8)?2:1)); /* Make IO read struct*/ JpegLosslessFrequencyScan(); /* Else make custom stables */ JpegCustomScan(CUSTOM_DO_DC); WriteDht(); /* write Huffman tables */ JpegLosslessEncodeScan(); } else if (GetFlag(CImage->JpegMode,J_DEFAULTHUFFMAN)) { MakeIob(IOB_BLOCK,O_RDONLY, ((CFrame->DataPrecision>8)?2:1)); /* Make IO read struct */ JpegDefaultHuffmanScan(); /* If default tables, then set up */ WriteDqt(); /* Write out quantization */ WriteDht(); /* and Huffman tables */ JpegEncodeScan(); /* Encode the scan */ } else { MakeIob(IOB_BLOCK,O_RDONLY, ((CFrame->DataPrecision>8)?2:1)); /* Make IO read struct*/ JpegFrequencyScan(); /* Else make custom tables */ JpegCustomScan(CUSTOM_DO_AC|CUSTOM_DO_DC); WriteDqt(); /* Write out quantization */ WriteDht(); /* and Huffman tables */ JpegEncodeScan(); /* Encode the scan */ } for(i=0;iNumberComponents;i++) /* Close all components */ { InstallIob(i); CloseIob(); } } WriteEoi(); /* All finished, Write eoi */ } /*BFUNC JpegQuantizationFrame() sets up the default quantization matrices to be used in the scan. Not to be used with user-specified quantization. EFUNC*/ void JpegQuantizationFrame() { BEGIN("JpegQuantizationFrame"); int i; if (CFrame->Q) /* if Q rescale quantization matrices */ CImage->QuantizationMatrices[0] = ScaleMatrix(CFrame->Q,Q_PRECISION,LargeQ,LuminanceQuantization); else CImage->QuantizationMatrices[0] = LuminanceQuantization; CScan->sq[CScan->NumberQTablesSend++] = 0; /* Queue luminance to send */ if (CFrame->GlobalNumberComponents>1) { if (CFrame->Q) /* rescale quantization matrices */ CImage->QuantizationMatrices[1] = ScaleMatrix(CFrame->Q,Q_PRECISION,LargeQ,ChrominanceQuantization); else CImage->QuantizationMatrices[1] = ChrominanceQuantization; CScan->sq[CScan->NumberQTablesSend++] = 1; /* Queue table to send */ } for(i=0;iGlobalNumberComponents;i++) { if (i%ScanComponentThreshold) CFrame->tq[CFrame->cn[i]]=1; /* chrominance q for non-primaries */ else CFrame->tq[CFrame->cn[i]]=0; /* luminance q starts each scan */ } } /*BFUNC JpegDefaultHuffmanScan() creates the default tables for baseline use. EFUNC*/ void JpegDefaultHuffmanScan() { BEGIN("JpegDefaultScan"); int i; if (CFrame->DataPrecision>8) { WHEREAMI(); printf("Default tables attempted with precision > 8.\n"); exit(ERROR_BOUNDS); } MakeXhuff(); /* Make luminance DC Huffman */ MakeEhuff(); SpecifiedHuffman(LuminanceDCBits,LuminanceDCValues); SetDCHuffman(0); MakeXhuff(); /* Make luminance AC Huffman */ MakeEhuff(); SpecifiedHuffman(LuminanceACBits,LuminanceACValues); SetACHuffman(0); MakeXhuff(); MakeEhuff(); CScan->td[0] = 0; CScan->ta[0] = 0; CScan->sa[CScan->NumberACTablesSend++] = 0; /* Queue to transmit table */ CScan->sd[CScan->NumberDCTablesSend++] = 0; if(CScan->NumberComponents>1) /* Make chrominance Huffman tables */ { /* Only if necessary */ SpecifiedHuffman(ChrominanceDCBits,ChrominanceDCValues); SetDCHuffman(1); MakeXhuff(); MakeEhuff(); SpecifiedHuffman(ChrominanceACBits,ChrominanceACValues); SetACHuffman(1); for(i=1;iNumberComponents;i++) { CScan->td[i] = 1; CScan->ta[i] = 1; } CScan->sa[CScan->NumberACTablesSend++] = 1; CScan->sd[CScan->NumberDCTablesSend++] = 1; CImage->NumberACTables = MAX(CImage->NumberACTables,2); CImage->NumberDCTables = MAX(CImage->NumberDCTables,2); } else { CImage->NumberACTables = MAX(CImage->NumberACTables,1); CImage->NumberDCTables = MAX(CImage->NumberDCTables,1); } } /*BFUNC JpegFrequencyScan() assembles the frequency statistics for the given scan, making one AC Freq, DC Freq statistic per component specified. This function should be used before making custom quantization tables. EFUNC*/ void JpegFrequencyScan() { BEGIN("JpegFrequencyScan"); int i,j,h,v,dohf,dovf; int input[64],output[64]; int DCTBound,DCTShift; InstallIob(0); /* Zero out for fast single-component */ InstallPrediction(0); /* operation. */ InstallFrequency(0); CheckScan(); NumberMDU = CScan->MDUWide*CScan->MDUHigh; ClearFrameFrequency(); ResetCodec(); DCTBound = ((CFrame->DataPrecision>8)?16383:1023); DCTShift = ((CFrame->DataPrecision>8)?2048:128); for(i=0;iResyncInterval)) { if (!(i % CFrame->ResyncInterval)) /* Resync the codec */ ResetCodec(); } for(j=0;jNumberComponents;j++) { InstallIob(j); InstallPrediction(j); /* Install statistics tables */ InstallFrequency(j); if (CScan->NumberComponents==1) dohf=dovf=1; else { dohf = CFrame->hf[CScan->ci[j]]; dovf = CFrame->vf[CScan->ci[j]]; } for(v=0;v QuantizationMatrices[CFrame-> tq[CScan->ci[j]]]); ZigzagMatrix(output,input); FrequencyDC(*input); /* Freq accumulates */ FrequencyAC(input); /* stats w/o encoding */ } } } } for(i=0;iNumberComponents;i++) /* Rewind to start */ { InstallIob(i); RewindIob(); } } /*BFUNC JpegCustomScan() assembles custom Huffman tables for the input. It defaults to baseline unless FULLHUFFMAN flag is set. EFUNC*/ void JpegCustomScan(flags) int flags; { BEGIN("JpegCustomScan"); int i,Sumbits; if ((GetFlag(CImage->JpegMode,J_FULLHUFFMAN)) || (CScan->NumberComponents < 3)) { for(i=0;iNumberComponents;i++) { if (GetFlag(flags,CUSTOM_DO_DC)) { MakeXhuff(); MakeEhuff(); MakeHuffman(CScan->DCFrequency[i]); SetDCHuffman(i); CScan->td[i] = i; CScan->sd[CScan->NumberDCTablesSend++] = i; } if (GetFlag(flags,CUSTOM_DO_AC)) { MakeXhuff(); MakeEhuff(); MakeHuffman(CScan->ACFrequency[i]); SetACHuffman(i); CScan->ta[i] = i; CScan->sa[CScan->NumberACTablesSend++] = i; } InstallIob(i); RewindIob(); } CImage->NumberACTables = MAX(CImage->NumberACTables, CScan->NumberComponents); CImage->NumberDCTables = MAX(CImage->NumberDCTables, CScan->NumberComponents); } else { if (GetFlag(flags,CUSTOM_DO_DC)) { MakeXhuff(); /* 0 Component has custom Huffman */ MakeEhuff(); MakeHuffman(CScan->DCFrequency[0]); SetDCHuffman(0); CScan->td[0] = 0; /* 0 component uses tables 0 */ CScan->sd[CScan->NumberDCTablesSend++] = 0; /* Queue to send */ } if (GetFlag(flags,CUSTOM_DO_AC)) { MakeXhuff(); MakeEhuff(); MakeHuffman(CScan->ACFrequency[0]); SetACHuffman(0); CScan->ta[0] = 0; CScan->sa[CScan->NumberACTablesSend++] = 0; /* Queue table send */ } if (CScan->NumberComponents > 1) { if (GetFlag(flags,CUSTOM_DO_DC)) { for(i=2;iNumberComponents;i++) /* Rest share Huffman*/ { /* Accum. frequencies */ AddFrequency(CScan->DCFrequency[1],CScan->DCFrequency[i]); } MakeXhuff(); MakeEhuff(); MakeHuffman(CScan->DCFrequency[1]); SetDCHuffman(1); for(i=1;iNumberComponents;i++) /* Rest use table 1 */ CScan->td[i] = 1; CScan->sd[CScan->NumberDCTablesSend++] = 1;/* Queue to send */ } if (GetFlag(flags,CUSTOM_DO_AC)) { for(i=2;iNumberComponents;i++) /*Accum. frequencies */ { AddFrequency(CScan->ACFrequency[1],CScan->ACFrequency[i]); } MakeXhuff(); MakeEhuff(); MakeHuffman(CScan->ACFrequency[1]); SetACHuffman(1); for(i=1;iNumberComponents;i++) /* Rest use table 1 */ CScan->ta[i] = 1; CScan->sa[CScan->NumberACTablesSend++] = 1; /* Queue to send */ } CImage->NumberACTables = MAX(CImage->NumberACTables,2);/*reset */ CImage->NumberDCTables = MAX(CImage->NumberDCTables,2);/* limits */ } else { CImage->NumberACTables = MAX(CImage->NumberACTables,1); /* Reset */ CImage->NumberDCTables = MAX(CImage->NumberDCTables,1); /* limits */ } } if (HuffmanTrace) /* If trace flag, then dump out frequency tables */ { Sumbits = 0; for(i=0;iNumberACTables;i++) { WHEREAMI(); printf("AC Code Frequency: Table %d\n",i); PrintACEhuff(i); Sumbits += SizeACEhuff(i); } for(i=0;iNumberDCTables;i++) { WHEREAMI(); printf("DC Code Frequency: Table %d\n",i); PrintDCEhuff(i); Sumbits += SizeDCEhuff(i); } WHEREAMI(); printf("Total bits: %d bytes: %d\n", Sumbits,(Sumbits+7)/8); } } /*BFUNC JpegEncodeScan() encodes the scan that is given to it. We assume that the quantization and the Huffman tables have already been specified. EFUNC*/ void JpegEncodeScan() { BEGIN("JpegEncodeScan"); int i,j,h,v,dohf,dovf; int input[64],output[64]; int DCTBound,DCTShift; InstallIob(0); CheckScan(); NumberMDU = CScan->MDUWide*CScan->MDUHigh; ClearFrameFrequency(); ResetCodec(); DCTBound = ((CFrame->DataPrecision>8)?16383:1023); DCTShift = ((CFrame->DataPrecision>8)?2048:128); ResyncCount=0; /* Reset the resync counter for every scan */ if (CFrame->InsertDnl>0) /* If DNL is greater than 0, insert */ { /* into according Resync interval */ if (!(CFrame->ResyncInterval)) WriteDnl(); /* Automatically write a dnl if no resync is enabled.*/ else /* If DNL > MDU, then put in last resync */ CFrame->InsertDnl = MAX(CFrame->InsertDnl, /* interval */ NumberMDU/CFrame->ResyncInterval); } WriteSos(); /* Start of Scan */ for(i=0;iResyncInterval)) { if (!(i % CFrame->ResyncInterval)) /* Check for resync */ { if ((i/CFrame->ResyncInterval)==CFrame->InsertDnl) { WriteDnl(); /* If resync matches use DNL */ CFrame->InsertDnl=0; /* Mission accomplished. */ } WriteResync(); /* Write resync */ ResetCodec(); } } for(j=0;jNumberComponents;j++) { if (Loud > MUTE) { WHEREAMI(); printf("[Pass 2 [Component:MDU] [%d:%d]]\n",j,i); } InstallIob(j); /* Install component j */ InstallPrediction(j); if (CScan->NumberComponents==1) dohf=dovf=1; else { dohf = CFrame->hf[CScan->ci[j]]; dovf = CFrame->vf[CScan->ci[j]]; } for(v=0;v WHISPER) { WHEREAMI(); printf("Raw input:\n"); PrintMatrix(input); } PreshiftDctMatrix(input,DCTShift); /* Shift */ DefaultDct(input,output); /* DCT */ BoundDctMatrix(output,DCTBound); /* Bound, limit */ Quantize(output, /* Quantize */ CImage-> QuantizationMatrices[CFrame-> tq[CScan->ci[j]]]); ZigzagMatrix(output,input); /* Zigzag trace */ if (Loud > TALK) { WHEREAMI(); printf("Cooked Output:\n"); PrintMatrix(input); } UseDCHuffman(CScan->td[j]); EncodeDC(*input); /* Encode DC component */ UseACHuffman(CScan->ta[j]); EncodeAC(input); /* Encode AC component */ } } } } if (CFrame->InsertDnl==-2) /* -2 is automatic DNL insertion */ { WriteDnl(); /* Put DNL here */ CFrame->InsertDnl=0; } for(i=0;iNumberComponents;i++) /* Rewind to start */ { InstallIob(i); RewindIob(); } } /*BFUNC JpegLosslessFrequencyScan() accumulates the frequencies into the DC frequency index. EFUNC*/ void JpegLosslessFrequencyScan() { BEGIN("JpegLosslessFrequencyScan"); int x,y,j,h,v,px; int height,width,horfreq,value; int MaxElem,CurrentElem,NumberElem; int StartofLine=1,UseType=1; /* Start with type 1 coding */ int *input; CheckScan(); for(j=0;jNumberComponents;j++) /* Rewind to start */ { InstallIob(j); RewindIob(); } if (CScan->NumberComponents==1) /* Calculate maximum number of */ MaxElem= LOSSLESSBUFFERSIZE/4; /* elements can be loaded in */ else { MaxElem= LOSSLESSBUFFERSIZE/ ((CFrame->vf[CScan->ci[0]]+1)*(CFrame->hf[CScan->ci[0]]+1)); for(j=1;jNumberComponents;j++) /* Rewind to start */ { x=LOSSLESSBUFFERSIZE/ ((CFrame->vf[CScan->ci[j]]+1)*(CFrame->hf[CScan->ci[j]]+1)); if (x < MaxElem) MaxElem=x; } } CScan->SSS=LosslessPredictorType; CScan->SAL=PointTransform; ClearFrameFrequency(); InstallIob(0); /* Set up values for fast non-interleaved mode */ InstallFrequency(0); if (CScan->NumberComponents==1) height=horfreq=1; else { height=CFrame->vf[CScan->ci[0]]; horfreq=CFrame->hf[CScan->ci[0]]; } NumberMDU = CScan->MDUWide*CScan->MDUHigh; CurrentMDU=0; if ((CFrame->ResyncInterval)&&(CFrame->ResyncInterval % CScan->MDUWide)) { WHEREAMI(); printf("Resync Interval not an integer multiple of MDU's wide.\n"); printf("Proceeding anyways.\n"); if (MaxElem>=CFrame->ResyncInterval) MaxElem=CFrame->ResyncInterval; /* Reduce to resync interval */ else MaxElem=1; /* Can't proceed quickly */ } CurrentElem=NumberElem=0; for(y=0;yMDUHigh;y++) { for(x=0;xMDUWide;x++) { if (CurrentMDU && (CFrame->ResyncInterval)) { if (!(CurrentMDU % CFrame->ResyncInterval)) /* Check resync */ { UseType=1; /* Reset codec */ for(j=0;jNumberComponents;j++) { InstallIob(j); LineResetBuffers(); } } } if (!(CurrentMDU%CScan->MDUWide)&&(CurrentMDU)) /* Reset CScan type */ { UseType=2; /* Start of line */ StartofLine=1; /* uses top pel predictor */ } CurrentElem++; if (CurrentElem>=NumberElem) { NumberElem = MIN((CScan->MDUWide-x),MaxElem); CurrentElem=0; for(j=0;jNumberComponents;j++) { InstallIob(j); /* Install component j */ ReadLine(NumberElem, /* Read in some elements*/ CScan->LosslessBuffer[j]); } } if (CScan->NumberComponents==1) { width=horfreq*NumberElem+1; input = &CScan->LosslessBuffer[0][CurrentElem]; if (Loud > NOISY) { WHEREAMI(); printf("[Pass 1 [Component:MDU:Total] [%d:%d:%d]]\n", 0,CurrentMDU,NumberMDU); } switch(UseType) /* Same as lossless coding predictor*/ { case 1: px = input[width]; break; case 2: px = input[1]; break; case 3: px = input[0]; break; case 4: px = input[width] + input[1] - input[0]; break; case 5: px = input[width] + ((input[1] - input[0])>>1); break; case 6: px = input[1] + ((input[width] - input[0])>>1); break; case 7: px = (input[1]+input[width])>>1; /* No rounding */ break; default: WHEREAMI(); printf("Lossless mode %d not supported.\n",UseType); break; } value=input[width+1]-px; if (Loud > NOISY) printf("IN=%d PX=%d FRE: %d\n", input[width+1],px,value); LosslessFrequencyDC(value); } else { for(j=0;jNumberComponents;j++) { if (Loud > NOISY) { WHEREAMI(); printf("[Pass 1 [Component:MDU:Total] [%d:%d:%d]]\n", j,CurrentMDU,NumberMDU); } InstallFrequency(j); height=CFrame->vf[CScan->ci[j]]; horfreq=CFrame->hf[CScan->ci[j]]; width=horfreq*NumberElem+1; input = &CScan->LosslessBuffer[j][CurrentElem*horfreq]; for(v=1;v<=height;v++) { for(h=1;h<=horfreq;h++) { switch(UseType) /* lossless coding predictor*/ { case 1: px = input[(v*(width))+h-1]; break; case 2: px = input[((v-1)*(width))+h]; break; case 3: px = input[((v-1)*(width))+h-1]; break; case 4: px = input[(v*(width))+h-1] + input[((v-1)*(width))+h] - input[((v-1)*(width))+h-1]; break; case 5: px = input[(v*(width))+h-1] + ((input[((v-1)*(width))+h] - input[((v-1)*(width))+h-1])>>1); break; case 6: px = input[((v-1)*(width))+h] + ((input[(v*(width))+h-1] - input[((v-1)*(width))+h-1])>>1); break; case 7: px = (input[((v-1)*(width))+h] + input[(v*(width))+h-1])>>1; break; default: WHEREAMI(); printf("Lossless mode: %d not supported.\n", UseType); break; } value=input[(v*(width))+h]-px; if (Loud > NOISY) printf("IN=%d PX=%d FRE: %d\n", input[(v*(width))+h],px,value); LosslessFrequencyDC(value); } } } } CurrentMDU++; if (StartofLine) { UseType=CScan->SSS; StartofLine=0; } } } for(j=0;jNumberComponents;j++) /* Rewind to start */ { InstallIob(j); RewindIob(); } } /*BFUNC JpegEncodeLosslessScan() encodes the scan that is given to it by lossless techniques. The Huffman table should already be specified. EFUNC*/ void JpegLosslessEncodeScan() { BEGIN("JpegEncodeLosslessScan"); int x,y,j,h,v,px; int height,width,horfreq,value; int MaxElem,CurrentElem,NumberElem; int StartofLine=1,UseType=1; /* Start with type 1 coding */ int *input; CheckScan(); for(j=0;jNumberComponents;j++) /* Important to rewind to start */ { /* for lossless coding... */ InstallIob(j); RewindIob(); } if (CScan->NumberComponents==1) /* Calculate maximum number of */ MaxElem= LOSSLESSBUFFERSIZE/4; /* elements can be loaded in */ else { MaxElem= LOSSLESSBUFFERSIZE/ ((CFrame->vf[CScan->ci[0]]+1)*(CFrame->hf[CScan->ci[0]]+1)); for(j=1;jNumberComponents;j++) /* Rewind to start */ { x=LOSSLESSBUFFERSIZE/ ((CFrame->vf[CScan->ci[j]]+1)*(CFrame->hf[CScan->ci[j]]+1)); if (x < MaxElem) MaxElem=x; } } CScan->SSS=LosslessPredictorType; CScan->SAL=PointTransform; InstallIob(0); UseDCHuffman(CScan->td[0]); /* Install DC table */ if (CScan->NumberComponents==1) height=horfreq=1; else { height=CFrame->vf[CScan->ci[0]]; horfreq=CFrame->hf[CScan->ci[0]]; } NumberMDU = CScan->MDUWide*CScan->MDUHigh; ResyncCount=0; /* Reset the resync counter for every scan */ if (CFrame->InsertDnl>0) /* If DNL is greater than 0, insert */ { /* into according Resync interval */ if (!(CFrame->ResyncInterval)) WriteDnl(); /* Automatically write a dnl if no resync is enabled.*/ else /* If DNL > MDU, then put in last resync */ CFrame->InsertDnl = MAX(CFrame->InsertDnl, /* interval */ NumberMDU/CFrame->ResyncInterval); } WriteSos(); /* Start of Scan */ CurrentMDU=0; if ((CFrame->ResyncInterval)&&(CFrame->ResyncInterval % CScan->MDUWide)) { WHEREAMI(); printf("Resync Interval not an integer multiple of MDU's wide.\n"); printf("Proceeding anyways.\n"); if (MaxElem>=CFrame->ResyncInterval) MaxElem=CFrame->ResyncInterval; /* Reduce to resync interval */ else MaxElem=1; /* Can't proceed quickly */ } CurrentElem=NumberElem=0; for(y=0;yMDUHigh;y++) { for(x=0;xMDUWide;x++) { if (CurrentMDU && (CFrame->ResyncInterval)) { if (!(CurrentMDU % CFrame->ResyncInterval)) /* Check resync */ { if ((CurrentMDU/CFrame->ResyncInterval)==CFrame->InsertDnl) { WriteDnl(); /* If resync matches use DNL */ CFrame->InsertDnl=0; /* Mission accomplished. */ } WriteResync(); /* Write resync */ UseType=1; /* Reset codec */ for(j=0;jNumberComponents;j++) { InstallIob(j); LineResetBuffers(); } } } if (!(CurrentMDU%CScan->MDUWide)&&(CurrentMDU)) /* Reset CScan type */ { UseType=2; /* Start of line */ StartofLine=1; /* uses top pel predictor */ } CurrentElem++; if (CurrentElem>=NumberElem) { NumberElem = MIN((CScan->MDUWide-x),MaxElem); CurrentElem=0; for(j=0;jNumberComponents;j++) { InstallIob(j); /* Install component j */ ReadLine(NumberElem, /* Read in some elements*/ CScan->LosslessBuffer[j]); } } if (CScan->NumberComponents==1) { if (Loud > MUTE) { WHEREAMI(); printf("[Pass 2 [Component:MDU:Total] [%d:%d:%d]]\n", 0,CurrentMDU,NumberMDU); } input = &CScan->LosslessBuffer[0][CurrentElem]; width=horfreq*NumberElem+1; switch(UseType) /* Same as lossless coding predictor*/ { case 1: px = input[width]; break; case 2: px = input[1]; break; case 3: px = input[0]; break; case 4: px = input[width] + input[1] - input[0]; break; case 5: px = input[width] + ((input[1] - input[0])>>1); break; case 6: px = input[1] + ((input[width] - input[0])>>1); break; case 7: px = (input[1] + input[width])>>1; /* No rounding */ break; default: WHEREAMI(); printf("Lossless mode %d not supported.\n",UseType); break; } value=input[width+1]-px; if (Loud > MUTE) printf("IN=%d PX=%d FRE: %d\n", input[width+1],px,value); LosslessEncodeDC(value); } else { for(j=0;jNumberComponents;j++) { if (Loud > MUTE) { WHEREAMI(); printf("[Pass 2 [Component:MDU] [%d:%d]]\n", j,CurrentMDU); } height=CFrame->vf[CScan->ci[j]]; horfreq=CFrame->hf[CScan->ci[j]]; width=horfreq*NumberElem+1; input = &CScan->LosslessBuffer[j][CurrentElem*horfreq]; UseDCHuffman(CScan->td[j]); for(v=1;v<=height;v++) { for(h=1;h<=horfreq;h++) { switch(UseType) /* Same as lossless predictor*/ { case 1: px = input[(v*(width))+h-1]; break; case 2: px = input[((v-1)*(width))+h]; break; case 3: px = input[((v-1)*(width))+h-1]; break; case 4: px = input[(v*(width))+h-1] + input[((v-1)*(width))+h] - input[((v-1)*(width))+h-1]; break; case 5: px = input[(v*(width))+h-1] + ((input[((v-1)*(width))+h] - input[((v-1)*(width))+h-1])>>1); break; case 6: px = input[((v-1)*(width))+h] + ((input[(v*(width))+h-1] - input[((v-1)*(width))+h-1])>>1); break; case 7: px = (input[((v-1)*(width))+h] + input[(v*(width))+h-1])>>1; break; default: WHEREAMI(); printf("Lossless mode %d not supported.\n", UseType); break; } value=input[(v*(width))+h]-px; if (Loud > MUTE) { printf("IN=%d PX=%d ENC: %d\n", input[(v*(width))+h],px,value); } LosslessEncodeDC(value); /* Encode as DC component */ } } } } CurrentMDU++; if (StartofLine) { UseType=CScan->SSS; StartofLine=0; } } } if (CFrame->InsertDnl==-2) /* -2 is automatic DNL insertion */ { WriteDnl(); CFrame->InsertDnl=0; } for(j=0;jNumberComponents;j++) /* Rewind to start */ { InstallIob(j); RewindIob(); } } /*BFUNC JpegDecodeFrame(general,) ) is used to decode a file. In general; is used to decode a file. In general, CFrame should hold just enough information to set up the file structure; that is, which file is to be opened for what component. EFUNC*/ static void JpegDecodeFrame() { BEGIN("JpegDecodeFrame"); int i; sropen(CImage->StreamFileName,0); /* Zero index */ if (ScreenAllMarker() < 0) /* Do all markers pending */ { WHEREAMI(); printf("No initial marker found!\n"); exit(-1); } while(1) { if (NumberMDU>=0) /* If NumberMDU is positive proceed */ { if (CurrentMDU >= NumberMDU) /* If all decoded */ { if (Notify) /* Print statistics */ { printf("> GW:%d GH:%d R:%d\n", CFrame->GlobalWidth, CFrame->GlobalHeight, CFrame->ResyncInterval); } for(i=0;iNumberComponents;i++) /* Print Scan info */ { if (Notify) { printf(">> C:%d N:%s W:%d H:%d hf:%d vf:%d\n", CScan->ci[i], CFrame->ComponentFileName[CScan->ci[i]], CFrame->Width[CScan->ci[i]], CFrame->Height[CScan->ci[i]], CFrame->hf[CScan->ci[i]], CFrame->vf[CScan->ci[i]]); } InstallIob(i); FlushIob(); /* Close image files */ SeekEndIob(); CloseIob(); } CurrentMDU=0; if (ScreenAllMarker()<0) /* See if any more images*/ { WHEREAMI(); printf("No trailing marker found!\n"); exit(-1); } if ((EndofFile)||(EndofImage)) /* Nothing, then return */ { srclose(); break; } } } if (CFrame->Type==3) JpegLosslessDecodeScan(); else JpegDecodeScan(); } } /*BFUNC JpegLosslessDecodeScan() is used to losslessly decode a portion of the image called the scan. This routine uses the internal lossless buffers to reduce the overhead in writing. However, one must note that the overhead is mostly in the Huffman decoding. EFUNC*/ static void JpegLosslessDecodeScan() { BEGIN("JpegLosslessDecodeScan"); int j,v,h,value,px; int height,horfreq,width; int MaxElem,CurrentElem,NumberElem; int StartofLine=1,UseType=1; /* Start with type 1 coding */ int *input; PointTransform=CScan->SAL; for(j=0;jNumberComponents;j++) /* Important to rewind to start */ { /* for lossless coding... */ InstallIob(j); RewindIob(); } if (CScan->NumberComponents==1) /* Calculate maximum number of */ MaxElem= LOSSLESSBUFFERSIZE/4; /* elements can be loaded in */ else { MaxElem= LOSSLESSBUFFERSIZE/ ((CFrame->vf[CScan->ci[0]]+1)*(CFrame->hf[CScan->ci[0]]+1)); for(j=1;jNumberComponents;j++) /* Rewind to start */ { v=LOSSLESSBUFFERSIZE/ ((CFrame->vf[CScan->ci[j]]+1)*(CFrame->hf[CScan->ci[j]]+1)); if (v < MaxElem) MaxElem=v; } } InstallIob(0); UseDCHuffman(CScan->td[0]); /* Install DC table */ if (CScan->NumberComponents==1) height=horfreq=1; else { height=CFrame->vf[CScan->ci[0]]; horfreq=CFrame->hf[CScan->ci[0]]; } if ((CFrame->ResyncInterval)&&(CFrame->ResyncInterval % CScan->MDUWide)) { WHEREAMI(); printf("Resync Interval not an integer multiple of MDU's wide.\n"); printf("Proceeding anyways.\n"); if (MaxElem>=CFrame->ResyncInterval) MaxElem=CFrame->ResyncInterval; /* Reduce to resync interval */ else MaxElem=1; /* Can't proceed quickly */ } CurrentElem=NumberElem=0; while(1) { if ((NumberMDU<0)&&(!(CurrentMDU%CScan->MDUWide))) { if (CheckMarker()==0xdc) ScreenMarker(); } if (NumberMDU>=0) /* If NumberMDU is positive proceed */ { if (CurrentMDU >= NumberMDU) /* If all decoded */ return; } if (CFrame->ResyncInterval) /* Flag to decoder stream */ ResyncEnable = 1; if (CurrentMDU && (CFrame->ResyncInterval)) { /* If resync interval */ if ((CurrentMDU % CFrame->ResyncInterval)==0) { if (!CleartoResync) /* If not in error recovery*/ ReadResync(); /* read resync. */ if (CleartoResync) { /* Clear until we have LastKnownResync: the offset is by 1 because we add the resync i%8 _after_ we code the ith resync interval... */ if (((CurrentMDU/CFrame->ResyncInterval)&0x07)== ((LastKnownResync+1)&0x07)) CleartoResync = 0; /* Finished with resync clearing */ } UseType=1; /* Reset codec */ for(j=0;jNumberComponents;j++) /* reset line buffers */ { /* Type is previous pel */ InstallIob(j); LineResetBuffers(); } } } if (!(CurrentMDU%CScan->MDUWide)&&(CurrentMDU)) /* Reset CScan type */ { UseType=2; /* Start of line */ StartofLine=1; /* uses top pel predictor */ } if (CurrentElem>=NumberElem) { NumberElem = MIN((CScan->MDUWide-(CurrentMDU%CScan->MDUWide)), MaxElem); CurrentElem=0; for(j=0;jNumberComponents;j++) { InstallIob(j); /* Install component j */ ReadPreambleLine(NumberElem, /* Read in some elements*/ CScan->LosslessBuffer[j]); } } if (CScan->NumberComponents==1) { width=horfreq*NumberElem+1; input = &CScan->LosslessBuffer[0][CurrentElem]; switch(UseType) /* Same as lossless coding predictor*/ { case 1: px = input[width]; break; case 2: px = input[1]; break; case 3: px = input[0]; break; case 4: px = input[width] + input[1] - input[0]; break; case 5: px = input[width] + ((input[1] - input[0])>>1); break; case 6: px = input[1] + ((input[width] - input[0])>>1); break; case 7: px = (input[1] + input[width])>>1; /* No rounding */ break; default: WHEREAMI(); printf("Lossless mode %d not supported.\n",UseType); break; } if (CleartoResync) /* If CleartoResync, flush */ input[width+1] = 0; else { value = LosslessDecodeDC(); input[width+1] = (value+px)&0xffff; if (Loud > MUTE) { printf("OUT=%d PX=%d VAL: %d\n", input[width+1],px,value); } } } else { for(j=0;jNumberComponents;j++) /* Decode MDU */ { if (Loud > MUTE) { WHEREAMI(); printf("[Decoder Pass [Component:MDU:#MDU] [%d:%d:%d]]\n", j,CurrentMDU,NumberMDU); } InstallIob(j); /* Install component */ height=CFrame->vf[CScan->ci[j]]; horfreq=CFrame->hf[CScan->ci[j]]; width=horfreq*NumberElem+1; input = &CScan->LosslessBuffer[j][CurrentElem*horfreq]; UseDCHuffman(CScan->td[j]); /* Install DC table */ for(v=1;v<=height;v++) { for(h=1;h<=horfreq;h++) { switch(UseType) /* Same as lossless coding predictor*/ { case 1: px = input[(v*(width))+h-1]; break; case 2: px = input[((v-1)*(width))+h]; break; case 3: px = input[((v-1)*(width))+h-1]; break; case 4: px = input[(v*(width))+h-1] + input[((v-1)*(width))+h] - input[((v-1)*(width))+h-1]; break; case 5: px = input[(v*(width))+h-1] + ((input[((v-1)*(width))+h] - input[((v-1)*(width))+h-1])>>1); break; case 6: px = input[((v-1)*(width))+h] + ((input[(v*(width))+h-1] - input[((v-1)*(width))+h-1])>>1); break; case 7: px = (input[((v-1)*(width))+h] + input[(v*(width))+h-1])>>1; break; default: WHEREAMI(); printf("Lossless mode %d not supported.\n", UseType); break; } if (CleartoResync) /* If CleartoResync, flush */ input[(v*(width))+h] = 0; else { value = LosslessDecodeDC(); input[(v*(width))+h] = (value+px)&0xffff; if (Loud > MUTE) { printf("OUT=%d PX=%d VAL: %d\n", input[(v*(width))+h],px,value); } } } } } } CurrentElem++; if (CurrentElem>=NumberElem) { for(j=0;jNumberComponents;j++) { InstallIob(j); /* Install component j */ WriteLine(NumberElem, /* Write out elements*/ CScan->LosslessBuffer[j]); } } CurrentMDU++; if (StartofLine) { UseType=CScan->SSS; StartofLine=0; } } } /*BFUNC JpegDecodeScan() is used to decode a portion of the image called the scan. Everything is read upon getting to this stage. EFUNC*/ static void JpegDecodeScan() { BEGIN("JpegDecodeScan"); int j,v,h,dovf,dohf; int input[64],output[64]; int IDCTBound,IDCTShift; while(1) { if ((NumberMDU<0)&&(!(CurrentMDU%CScan->MDUWide))) { if (CheckMarker()==0xdc) ScreenMarker(); } if (NumberMDU>=0) /* If NumberMDU is positive proceed */ { if (CurrentMDU >= NumberMDU) /* If all decoded */ return; } if (CFrame->ResyncInterval) /* Flag to decoder stream */ { ResyncEnable = 1; } if (CurrentMDU && (CFrame->ResyncInterval)) { /* If resync interval */ if ((CurrentMDU % CFrame->ResyncInterval)==0) { if (!CleartoResync) /* If not in error recovery*/ { /* read resync. */ ReadResync(); } if (CleartoResync) { /* Clear until we have LastKnownResync: the offset is by 1 because we add the resync i%8 _after_ we code the ith resync interval... */ if (((CurrentMDU/CFrame->ResyncInterval)&0x07)== ((LastKnownResync+1)&0x07)) { CleartoResync = 0; /* Finished with resync clearing */ } } ResetCodec(); /* Reset codec */ } } IDCTBound=((CFrame->DataPrecision>8)?4095:255); IDCTShift=((CFrame->DataPrecision>8)?2048:128); for(j=0;jNumberComponents;j++) /* Decode MDU */ { if (Loud > MUTE) { WHEREAMI(); printf("[Decoder Pass [Component:MDU:#MDU] [%d:%d:%d]]\n", j,CurrentMDU,NumberMDU); } InstallPrediction(j); /* Install component */ InstallIob(j); if (CScan->NumberComponents==1) /* Check for non-interleaved mode */ dohf=dovf=1; else { dohf = CFrame->hf[CScan->ci[j]]; dovf = CFrame->vf[CScan->ci[j]]; } for(v=0;vtd[j]); /* Install DC table */ *input = DecodeDC(); /* Decode DC */ UseACHuffman(CScan->ta[j]); /* Install AC table */ DecodeAC(input); /* Decode AC */ if (Loud > TALK) { printf("Cooked Input\n"); PrintMatrix(input); } IZigzagMatrix(input,output); /* Inverse zigzag */ IQuantize(output, /* Inverse quantize */ CImage-> QuantizationMatrices[CFrame-> tq[CScan->ci[j]]]); DefaultIDct(output,input); /* Inverse DCT */ PostshiftIDctMatrix(input,IDCTShift); /* Shift (all positive)*/ BoundIDctMatrix(input,IDCTBound); /* Bound */ if (Loud > WHISPER) { printf("Raw Output\n"); PrintMatrix(input); } } WriteBlock(input); /* Write out */ } } } CurrentMDU++; } } /*BFUNC PrintImage() prints out the Image structure of the CURRENT image. It is primarily used for debugging. The image structure consists of the data that is held to be fixed even though multiple scans (or multiple frames, even though it is not advertised as such by JPEG) are received. EFUNC*/ void PrintImage() { BEGIN("PrintImage"); int i; printf("*** Image ID: %x ***\n",CImage); if (CImage) { if (CImage->StreamFileName) { printf("StreamFileName %s\n",(CImage->StreamFileName ? CImage->StreamFileName : "Null")); } printf("InternalMode: %d ImageSequence: %d\n", CImage->JpegMode,CImage->ImageSequence); printf("NumberQuantizationMatrices %d\n", CImage->NumberQuantizationMatrices); for(i=0;iNumberQuantizationMatrices;i++) { printf("Quantization Matrix [%d]\n",i); PrintMatrix(CImage->QuantizationMatrices[i]); } printf("NumberDCTables %d\n", CImage->NumberDCTables); for(i=0;iNumberDCTables;i++) { printf("DC Huffman Table[%d]\n",i); UseDCHuffman(i); PrintHuffman(); } printf("NumberACTables %d\n", CImage->NumberACTables); for(i=0;iNumberACTables;i++) { printf("AC Huffman Table[%d]\n",i); UseACHuffman(i); PrintHuffman(); } } } /*BFUNC PrintFrame() is used to print the information specific to loading in the frame. This corresponds roughly to the information received by the SOF marker code. EFUNC*/ void PrintFrame() { BEGIN("PrintFrame"); int i; printf("*** Frame ID: %x *** (TYPE: %d)\n",CFrame,CFrame->Type); if (CFrame) { printf("DataPrecision: %d ResyncInterval: %d\n", CFrame->DataPrecision,CFrame->ResyncInterval); printf("Height: %d Width: %d\n", CFrame->GlobalHeight,CFrame->GlobalWidth); printf("BufferSize: %d Image: %x\n",CFrame->BufferSize,CFrame->Image); printf("NumberComponents %d\n", CFrame->GlobalNumberComponents); for(i=0;iGlobalNumberComponents;i++) { printf("ComponentFileName %s\n", ((CFrame->ComponentFileName[CFrame->cn[i]]) ? CFrame->ComponentFileName[CFrame->cn[i]] : "Null")); printf("HorizontalFrequency: %d VerticalFrequency: %d\n", CFrame->hf[CFrame->cn[i]],CFrame->vf[CFrame->cn[i]]); printf("Height: %d Width: %d\n", CFrame->Height[CFrame->cn[i]],CFrame->Width[CFrame->cn[i]]); InstallIob(i); PrintIob(); } } } /*BFUNC PrintScan() is used to print the information in the CScan structure. This roughly corresponds to the information received by the Scan marker code. EFUNC*/ void PrintScan() { BEGIN("PrintScan"); int i; printf("*** Scan ID: %x ***\n",CScan); if (CScan) { printf("NumberComponents %d\n", CScan->NumberComponents); for(i=0;iNumberComponents;i++) { printf("Component: %d Index: %d\n", i,CScan->ci[i]); printf("DC Huffman Table: %d AC Huffman Table: %d\n", CScan->td[i],CScan->ta[i]); printf("LastDC: %d Iob: %x\n", *(CScan->LastDC[i]),CScan->Iob[i]); } printf("NumberACSend: %d NumberDCSend: %d NumberQSend: %d\n", CScan->NumberACTablesSend, CScan->NumberDCTablesSend, CScan->NumberQTablesSend); } } /*BFUNC MakeImage() makes an image and puts it into the Current Image pointer (CImage). It initializes the structure appropriate to the JPEG initial specifications. EFUNC*/ void MakeImage() { BEGIN("MakeImage"); if (!(CImage = MakeStructure(IMAGE))) { WHEREAMI(); printf("Cannot allocate memory for Image structure.\n"); exit(ERROR_MEMORY); } CImage->StreamFileName = NULL; CImage->JpegMode = 0; CImage->Jfif=0; CImage->ImageSequence = -1; /* First element in sequence is 0 */ CImage->NumberQuantizationMatrices = 2; /* Default # matrices is 2 */ CImage->QuantizationMatrices[0] = LuminanceQuantization; CImage->QuantizationMatrices[1] = ChrominanceQuantization; CImage->NumberACTables = 0; /* No tables defined yet */ CImage->NumberDCTables = 0; } /*BFUNC MakeFrame() constructs a Frame Structure and puts it in the Current Frame pointer (CFrame). EFUNC*/ void MakeFrame() { BEGIN("MakeFrame"); int i; if (!(CFrame = MakeStructure(FRAME))) { WHEREAMI(); printf("Cannot allocate memory for Frame structure.\n"); exit(ERROR_MEMORY); } CFrame->Type=0; /* Baseline type */ CFrame->InsertDnl = 0; /* Set to default position */ CFrame->Q = 0; CFrame->GlobalHeight = 0; CFrame->GlobalWidth = 0; CFrame->DataPrecision = 8; /* Default 8 precision */ CFrame->ResyncInterval = 0; CFrame->GlobalNumberComponents = 0; for(i=0;icn[i] = 0; /* Clean out all slots */ CFrame->hf[i] = 0; CFrame->vf[i] = 0; CFrame->tq[i] = 0; CFrame->Height[i] = 0; CFrame->Width[i] = 0; } CFrame->BufferSize = BUFFERSIZE; CFrame->Image = CImage; } /*BFUNC MakeScanFrequency() constructs a set of scan information for the current variables. These frequency markers are used for creating the JPEG custom matrices. EFUNC*/ void MakeScanFrequency() { BEGIN("MakeScanFrequency"); int i; for(i=0;iLastDC[i] = MakeStructure(int))) { WHEREAMI(); printf("Cannot allocate LastDC integer store.\n"); exit(ERROR_MEMORY); } if (!(CScan->ACFrequency[i] = (int *) calloc(257,sizeof(int)))) { WHEREAMI(); printf("Cannot allocate AC Frequency array.\n"); exit(ERROR_MEMORY); } if (!(CScan->DCFrequency[i] = (int *) calloc(257,sizeof(int)))) { WHEREAMI(); printf("Cannot allocate DC Frequency array.\n"); exit(ERROR_MEMORY); } } } /*BFUNC MakeScan() is used for creating the Scan structure which holds most of the information in the Scan marker code. EFUNC*/ void MakeScan() { BEGIN("MakeScan"); int i; if (!(CScan = MakeStructure(SCAN))) { WHEREAMI(); printf("Cannot allocate memory for Scan structure.\n"); exit(ERROR_MEMORY); } CScan->NumberACTablesSend = 0; /* Install with default values */ CScan->NumberDCTablesSend = 0; CScan->NumberComponents = 0; for(i=0;ita[i] = 0; CScan->td[i] = 0; CScan->sa[i] = 0; CScan->sd[i] = 0; CScan->sq[i] = 0; } CScan->SSS=0; CScan->SSE=0; CScan->SAH=0; CScan->SAL=0; MakeScanFrequency(); } /*BFUNC MakeConsistentFileNames() is used to construct consistent filenames for opening and closing of data storage. It is used primarily by the decoder when all the files may not necessarily be specified. EFUNC*/ void MakeConsistentFileNames() { BEGIN("MakeConsistentFileNames"); int i; for(i=0;iNumberComponents;i++) { if (CImage->ImageSequence) /* If in sequence, must add sequence */ { /* identifier */ CFrame->ComponentFileName[CScan->ci[i]] = (char *) calloc(strlen(CImage->StreamFileName)+16,sizeof(char)); sprintf(CFrame->ComponentFileName[CScan->ci[i]],"%s.%d.%d", CImage->StreamFileName,CImage->ImageSequence,CScan->ci[i]); } else if (CFrame->ComponentFileName[CScan->ci[i]] == NULL) { /* Otherwise if none specified, create. */ CFrame->ComponentFileName[CScan->ci[i]] = (char *) calloc(strlen(CImage->StreamFileName)+8,sizeof(char)); sprintf(CFrame->ComponentFileName[CScan->ci[i]],"%s.%d", CImage->StreamFileName,CScan->ci[i]); } } } /*BFUNC CheckValidity() checks whether the current values in CFrame and CScan meet the internal specifications for correctness and the algorithm can guarantee completion. EFUNC*/ void CheckValidity() { BEGIN("CheckValidity"); int i; ErrorValue = 0; /* Check if within internal specs */ InBounds(CFrame->GlobalWidth,0,MAXIMUM_IMAGE_WIDTH,"Bad Image Width"); InBounds(CFrame->GlobalHeight,0,MAXIMUM_IMAGE_HEIGHT,"Bad Image Height"); if (CFrame->Q<0) { WHEREAMI(); printf("Q factor is negative - must be positive\n"); } if ((CFrame->DataPrecision!=8)&&(CFrame->DataPrecision!=12)) { if (CImage->JpegMode == J_LOSSLESS) { if (CFrame->DataPrecision<=16) printf("Precision type: %d\n",CFrame->DataPrecision); else printf("Caution: precision type: %d greater than 16.\n", CFrame->DataPrecision); } else printf("Caution: precision type: %d not 8 or 12.\n", CFrame->DataPrecision); } InBounds(CScan->NumberComponents,1,15,"Bad Number of Components"); for(i=0;iNumberComponents;i++) { InBounds(CFrame->Width[CScan->ci[i]],0,MAXIMUM_IMAGE_WIDTH, "Bad Frame Width"); InBounds(CFrame->Height[CScan->ci[i]],0,MAXIMUM_IMAGE_HEIGHT, "Bad Frame Height"); InBounds(CFrame->hf[CScan->ci[i]],1,MAXIMUM_HORIZONTAL_FREQUENCY, "Bad Horizontal Frequency"); InBounds(CFrame->vf[CScan->ci[i]],1,MAXIMUM_VERTICAL_FREQUENCY, "Bad Vertical Frequency"); } InBounds(LosslessPredictorType,0,7,"Bad Lossless Predictor Type"); if (PointTransform) { if (!(LosslessPredictorType)) { WHEREAMI(); printf("Point Transform specified without lossless prediction.\n"); printf("Shifting of input/output should be anticipated.\n"); } else InBounds(PointTransform,0,14,"Bad Point Transform"); } if (ErrorValue) { WHEREAMI(); printf("Invalid input detected.\n"); exit(ErrorValue); } } /*BFUNC CheckBaseline() checks whether the internal values meet JPEG Baseline specifications. EFUNC*/ int CheckBaseline() { BEGIN("CheckBaseline"); int i; ErrorValue = 0; /* Check for JPEG specs */ InBounds(CFrame->GlobalWidth,0,MAXIMUM_IMAGE_WIDTH,"Bad Image Width"); InBounds(CFrame->GlobalHeight,0,MAXIMUM_IMAGE_HEIGHT,"Bad Image Height"); if (CFrame->Q<0) { WHEREAMI(); printf("Q factor is negative - must be positive\n"); } InBounds(CScan->NumberComponents,1,4,"Bad Number of Components"); for(i=0;iNumberComponents;i++) { InBounds(CFrame->Width[CScan->ci[i]],0,MAXIMUM_IMAGE_WIDTH, "Bad Frame Width"); InBounds(CFrame->Height[CScan->ci[i]],0,MAXIMUM_IMAGE_HEIGHT, "Bad Frame Height"); InBounds(CFrame->hf[CScan->ci[i]],1,MAXIMUM_JPEG_HORIZONTAL_FREQUENCY, "Bad Horizontal Frequency"); InBounds(CFrame->vf[CScan->ci[i]],1,MAXIMUM_JPEG_VERTICAL_FREQUENCY, "Bad Vertical Frequency"); } if (ErrorValue) { printf("Caution: JPEG++ Mode.\n"); ErrorValue = 0; } } /*BFUNC ConfirmFileSize() checks to see if the files used in the scan actually exist and correspond in size to the input given. EFUNC*/ void ConfirmFileSize() { BEGIN("ConfirmFileSize"); int i,FileSize; FILE *test; for(i=0;iNumberComponents;i++) /* Do for all components in scan*/ { if (CFrame->ComponentFileName[CScan->ci[i]]) { if ((test = fopen(CFrame->ComponentFileName[CScan->ci[i]], "r")) == NULL) { WHEREAMI(); printf("Cannot open filename %s\n", CFrame->ComponentFileName[CScan->ci[i]]); exit(ERROR_BOUNDS); } fseek(test,0,2); /* Go to end */ FileSize = ftell(test); /* Find number of bytes */ rewind(test); if (CFrame->Height[CScan->ci[i]] == 0) /* Must have good dimens*/ { if (CFrame->Width[CScan->ci[i]] == 0) { WHEREAMI(); printf("Bad file specification in %s.\n", CFrame->ComponentFileName[CScan->ci[i]]); } else { CFrame->Height[CScan->ci[i]] = FileSize / (CFrame->Width[CScan->ci[i]]* ((CFrame->DataPrecision>8)?2:1)); WHEREAMI(); printf("Autosizing height to %d\n", CFrame->Height[CScan->ci[i]]); } } /* Dimensions must conform */ if (FileSize != CFrame->Width[CScan->ci[i]] * CFrame->Height[CScan->ci[i]]* ((CFrame->DataPrecision>8)?2:1)) { WHEREAMI(); printf("File size conflict in %s, est: %d act: %d \n", CFrame->ComponentFileName[CScan->ci[i]], CFrame->Width[CScan->ci[i]]*CFrame->Height[CScan->ci[i]]* ((CFrame->DataPrecision>8)?2:1), FileSize); exit(ERROR_BOUNDS); } fclose(test); } } } /*BFUNC Help() prints out general information regarding the use of this JPEG software. EFUNC*/ static void Help() { BEGIN("Help"); printf("jpeg -iw ImageWidth -ih ImageHeight [-JFIF] [-q(l) Q-Factor]\n"); printf(" [-a] [-b] [-d] [-k predictortype] [-n] [-o] [-y] [-z]\n"); printf(" [-p PrecisionValue] [-t pointtransform]\n"); printf(" [-r ResyncInterval] [-s StreamName]\n"); printf(" [[-ci ComponentIndex1] [-fw FrameWidth1] [-fh FrameHeight1]\n"); printf(" [-hf HorizontalFrequency1] [-vf VerticalFrequency1]\n"); printf(" ComponentFile1]\n"); printf(" [[-ci ComponentIndex2] [-fw FrameWidth2] [-fh FrameHeight2]\n"); printf(" [-hf HorizontalFrequency2] [-vf VerticalFrequency2]\n"); printf(" ComponentFile1]\n"); printf(" ....\n\n"); printf("-JFIF puts a JFIF marker. Don't change component indices.\n"); printf("-a enables Reference DCT.\n"); printf("-b enables Lee DCT.\n"); printf("-d decoder enable.\n"); printf("-[k predictortype] enables lossless mode.\n"); printf("-q specifies quantization factor; -ql specifies can be long.\n"); printf("-n enables non-interleaved mode.\n"); printf("-[t pointtransform] is the number of bits for the PT shift.\n"); printf("-o enables the Command Interpreter.\n"); printf("-p specifies precision.\n"); printf("-y run in robust mode against errors (cannot be used with DNL).\n"); printf("-z uses default Huffman tables.\n"); } /*END*/ pvrg-jpeg-1.2.1/leedct.c0000644000175000017500000002215505725223004014366 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ /* ************************************************************ leedct.c This is the Byeong Gi Lee algorithm from IEEE Trans. Accoustics, Speech, and Signal Processing, Vol ASSP-32, No. 6, December 1984, pp. 1243 -1245. ************************************************************ */ /*LABEL leedct.c */ /*PUBLIC*/ extern void LeeIDct(); extern void LeeDct(); /*PRIVATE*/ /* Standard Macros */ #define LS(r,s) ((r) << (s)) #define RS(r,s) ((r) >> (s)) /* Caution with rounding... */ #define MSCALE(expr) RS((expr),9) #define IDCTSCALE(x) (((x<0) ? (x-8) : (x+8))/16); #define DCTSCALE(x) (((x<0) ? (x-8) : (x+8))/16); /* Cos Table */ #define twoc1d4 724L #define twoc1d8 946L #define twoc3d8 392L #define twoc1d16 1004L #define twoc3d16 851L #define twoc5d16 569L #define twoc7d16 200L #define sqrt2 724L /* 1/Cos Table */ #define itwoc1d4 362L #define itwoc1d8 277L #define itwoc3d8 669L #define itwoc1d16 261L #define itwoc3d16 308L #define itwoc5d16 461L #define itwoc7d16 1312L #define isqrt2 362L #define x0 tx0 #define x1 tx1 #define x2 tx2 #define x3 tx3 #define x4 ex4 #define x5 ex5 #define x6 ex6 #define x7 ex7 #define r0 rx0 #define r1 rx1 #define r2 rx2 #define r3 rx3 #define s0 rx0 #define s1 rx1 #define s2 rx2 #define s3 rx3 #define f0 ex0 #define f1 ex1 #define f2 ex2 #define f3 ex3 #define g0 ex4 #define g1 ex5 #define g2 ex6 #define g3 ex7 #define b1 gx0 #define b2 gx0 #define b3 gx1 #define a1 gx2 #define a3 gx2 #define c1 gx2 #define c3 gx2 #define ihold gx1 /*START*/ /*BFUNC LeeIDct is implemented according to the inverse dct flow diagram in the paper. It takes two input arrays that must be defined before the call. EFUNC*/ void LeeIDct(x,y) int *x; int *y; { register int ex0,ex1,ex2,ex3,ex4,ex5,ex6,ex7; register int tx0,tx1,tx2,tx3; register int rx0,rx1,rx2,rx3; register int gx0,gx1,gx2; register int *iptr,*jptr; register int i; /* Do rows */ for(jptr=y,iptr=x,i=0;i<8;i++) { x0 = MSCALE(isqrt2*LS(*(iptr++),2)); x1 = LS(*(iptr++),2); x2 = LS(*(iptr++),2); x3 = LS(*(iptr++),2); x4 = LS(*(iptr++),2); x5 = LS(*(iptr++),2); x6 = LS(*(iptr++),2); x7 = LS(*(iptr++),2); a1 = MSCALE(itwoc1d4*x4); r0 = x0+a1; r1 = x0-a1; a3 = MSCALE(itwoc1d4*(x2+x6)); r2 = MSCALE(itwoc1d8*(x2+a3)); r3 = MSCALE(itwoc3d8*(x2-a3)); f0 = r0+r2; f1 = r1+r3; f2 = r0-r2; f3 = r1-r3; b1 = x3+x5; c1 = MSCALE(itwoc1d4*b1); s0 = x1+c1; s1 = x1-c1; b2 = x1+x3; b3 = x5+x7; c3 = MSCALE(itwoc1d4*(b2+b3)); s2 = MSCALE(itwoc1d8*(b2+c3)); s3 = MSCALE(itwoc3d8*(b2-c3)); g0 = MSCALE(itwoc1d16*(s0+s2)); g1 = MSCALE(itwoc3d16*(s1+s3)); g2 = MSCALE(itwoc7d16*(s0-s2)); g3 = MSCALE(itwoc5d16*(s1-s3)); *(jptr++) = f0+g0; *(jptr++) = f1+g1; *(jptr++) = f3+g3; *(jptr++) = f2+g2; *(jptr++) = f2-g2; *(jptr++) = f3-g3; *(jptr++) = f1-g1; *(jptr++) = f0-g0; } /* Do columns */ for(i=0;i<8;i++) { jptr = iptr = y+i; #ifdef PVERSION x0 = MSCALE(isqrt2*(*(iptr))); iptr += 8; x1 = *(iptr); iptr += 8; x2 = *(iptr); iptr += 8; x3 = *(iptr); iptr += 8; x4 = *(iptr); iptr += 8; x5 = *(iptr); iptr += 8; x6 = *(iptr); iptr += 8; x7 = *(iptr); #else #undef x1 #undef x2 #undef x3 #undef x4 #undef x5 #undef x6 #undef x7 #define x1 iptr[8] #define x2 iptr[16] #define x3 iptr[24] #define x4 iptr[32] #define x5 iptr[40] #define x6 iptr[48] #define x7 iptr[56] x0 = MSCALE(isqrt2*(*iptr)); #endif a1 = MSCALE(itwoc1d4*x4); r0 = x0+a1; r1 = x0-a1; a3 = MSCALE(itwoc1d4*(x2+x6)); r2 = MSCALE(itwoc1d8*(x2+a3)); r3 = MSCALE(itwoc3d8*(x2-a3)); f0 = r0+r2; f1 = r1+r3; f2 = r0-r2; f3 = r1-r3; b1 = x3+x5; c1 = MSCALE(itwoc1d4*b1); s0 = x1+c1; s1 = x1-c1; b2 = x1+x3; b3 = x5+x7; c3 = MSCALE(itwoc1d4*(b2+b3)); s2 = MSCALE(itwoc1d8*(b2+c3)); s3 = MSCALE(itwoc3d8*(b2-c3)); g0 = MSCALE(itwoc1d16*(s0+s2)); g1 = MSCALE(itwoc3d16*(s1+s3)); g2 = MSCALE(itwoc7d16*(s0-s2)); g3 = MSCALE(itwoc5d16*(s1-s3)); ihold = f0+g0; (*jptr) = IDCTSCALE(ihold); jptr += 8; ihold = f1+g1; (*jptr) = IDCTSCALE(ihold); jptr += 8; ihold = f3+g3; (*jptr) = IDCTSCALE(ihold); jptr += 8; ihold = f2+g2; (*jptr) = IDCTSCALE(ihold); jptr += 8; ihold = f2-g2; (*jptr) = IDCTSCALE(ihold); jptr += 8; ihold = f3-g3; (*jptr) = IDCTSCALE(ihold); jptr += 8; ihold = f1-g1; (*jptr) = IDCTSCALE(ihold); jptr += 8; ihold = f0-g0; (*jptr) = IDCTSCALE(ihold); } } #undef f0 #undef f1 #undef f2 #undef f3 #undef g0 #undef g1 #undef g2 #undef g3 #undef r0 #undef r1 #undef r2 #undef r3 #undef s0 #undef s1 #undef s2 #undef s3 #define f0 rx0 #define f1 rx1 #define f2 rx2 #define f3 rx3 #define r0 rx4 #define r1 rx5 #define r2 rx6 #define r3 rx7 #define g0 sx0 #define g1 sx1 #define g2 sx2 #define g3 sx3 #define s0 rx4 #define s1 rx5 #define s2 rx6 #define s3 rx7 /*BFUNC LeeDct is implemented by reversing the arrows in the inverse dct flow diagram. It takes two input arrays that must be defined before the call. EFUNC*/ void LeeDct(x,y) int *x; int *y; { register int rx0,rx1,rx2,rx3,rx4,rx5,rx6,rx7; register int sx0,sx1,sx2,sx3; register int hold,c2; register int *iptr,*jptr; #undef x0 #undef x1 #undef x2 #undef x3 #undef x4 #undef x5 #undef x6 #undef x7 #define x0 iptr[0] #define x1 iptr[1] #define x2 iptr[2] #define x3 iptr[3] #define x4 iptr[4] #define x5 iptr[5] #define x6 iptr[6] #define x7 iptr[7] for(jptr=y,iptr=x;iptr /*PUBLIC*/ extern void ReferenceDct(); extern void ReferenceIDct(); extern void TransposeMatrix(); extern void Quantize(); extern void IQuantize(); extern void PreshiftDctMatrix(); extern void PostshiftIDctMatrix(); extern void BoundDctMatrix(); extern void BoundIDctMatrix(); extern void ZigzagMatrix(); extern void IZigzagMatrix(); extern int *ScaleMatrix(); extern void PrintMatrix(); extern void ClearMatrix(); static void DoubleReferenceDct1D(); static void DoubleReferenceIDct1D(); static void DoubleTransposeMatrix(); /*PRIVATE*/ /* The transposition indices */ int transpose_index[] = /* Is a transpose map for matrix transp. */ {0, 8, 16, 24, 32, 40, 48, 56, 1, 9, 17, 25, 33, 41, 49, 57, 2, 10, 18, 26, 34, 42, 50, 58, 3, 11, 19, 27, 35, 43, 51, 59, 4, 12, 20, 28, 36, 44, 52, 60, 5, 13, 21, 29, 37, 45, 53, 61, 6, 14, 22, 30, 38, 46, 54, 62, 7, 15, 23, 31, 39, 47, 55, 63}; int zigzag_index[] = /* Is zig-zag map for matrix -> scan array */ {0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63}; int izigzag_index[] = {0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63}; /*Some definitions */ #define MakeMatrix() (int *) calloc(BLOCKSIZE,sizeof(int)) #define FixedMultiply(s,x,y) x = ((x * y) >> s); #define DCT_OFFSET 128 /*START*/ /*BFUNC ReferenceDct() does a reference DCT on the input (matrix) and output (new matrix). EFUNC*/ void ReferenceDct(matrix,newmatrix) int *matrix; int *newmatrix; { BEGIN("ReferenceDct"); int *mptr; double *sptr,*dptr; double sourcematrix[BLOCKSIZE],destmatrix[BLOCKSIZE]; for(sptr=sourcematrix,mptr=matrix;mptr 0 ? (*(sptr)+0.5):(*(sptr)-0.5)); } } /*BFUNC DoubleReferenceDCT1D() does a 8 point dct on an array of double input and places the result in a double output. EFUNC*/ static void DoubleReferenceDct1D(ivect,ovect) double *ivect; double *ovect; { BEGIN("DoubleReferenceDct1D"); double *mptr,*iptr,*optr; for(mptr=DctMatrix,optr=ovect;optr 0 ? (*(sptr)+0.5):(*(sptr)-0.5)); } } /*BFUNC DoubleReferenceIDct1D() does an 8 point inverse dct on ivect and puts the output in ovect. EFUNC*/ static void DoubleReferenceIDct1D(ivect,ovect) double *ivect; double *ovect; { BEGIN("DoubleReferenceIDct1D"); double *mptr,*iptr,*optr; for(mptr = IDctMatrix,optr=ovect;optr 0) /* Rounding is different for +/- coeffs */ { *mptr = (*mptr + *qmatrix/2)/ (*qmatrix); qmatrix++; } else { *mptr = (*mptr - *qmatrix/2)/ (*qmatrix); qmatrix++; } } } /*BFUNC IQuantize() takes an input matrix and does an inverse quantization and puts the output int qmatrix. EFUNC*/ void IQuantize(matrix,qmatrix) int *matrix; int *qmatrix; { BEGIN("IQuantize"); int *mptr; if (!qmatrix) { WHEREAMI(); printf("No quantization matrix specified!\n"); exit(ERROR_BOUNDS); } for(mptr=matrix;mptr 0) *mptr = Bound; } } /*BFUNC BoundIDctMatrix bounds the inverse dct matrix so that no pixel has a value greater than 255 (4095) or less than 0. EFUNC*/ void BoundIDctMatrix(matrix,Bound) int *matrix; int Bound; { BEGIN("BoundIDctMatrix"); int *mptr; for(mptr=matrix;mptr Bound) {*mptr = Bound;} } } /*BFUNC IZigzagMatrix() performs an inverse zig-zag translation on the input imatrix and places the output in omatrix. EFUNC*/ void IZigzagMatrix(imatrix,omatrix) int *imatrix; int *omatrix; { BEGIN("IZigzagMatrix"); int *tptr; for(tptr=zigzag_index;tptr Limit) *tptr = Limit; else if (*tptr < 1) *tptr = 1; } return(Temp); } /*BFUNC PrintMatrix() prints an 8x8 matrix in row/column form. EFUNC*/ void PrintMatrix(matrix) int *matrix; { BEGIN("PrintMatrix"); int i,j; if (matrix) { for(i=0;i #include #endif /* Functions which are local and which are exported. */ /*PUBLIC*/ static BUFFER *MakeXBuffer(); static void WriteXBuffer(); static void ReadXBuffer(); static void ReadResizeBuffer(); static void FlushBuffer(); static void BlockMoveTo(); static void ReadXBound(); static void WriteXBound(); static void LineMoveTo(); extern void ReadBlock(); extern void WriteBlock(); extern void ResizeIob(); extern void RewindIob(); extern void FlushIob(); extern void SeekEndIob(); extern void CloseIob(); extern void MakeIob(); extern void PrintIob(); extern void InstallIob(); extern void TerminateFile(); extern void ReadLine(); extern void ReadPreambleLine(); extern void WriteLine(); extern void LineResetBuffers(); /*PRIVATE*/ /* External variables */ extern int Loud; extern int PointTransform; /* Used for shifting the pels from the I/O */ extern IMAGE *CImage; extern FRAME *CFrame; extern SCAN *CScan; /* Internal variables. */ static IOBUF *Iob=NULL; /* Internal I/O buffer. */ static int BlockWidth = BLOCKWIDTH; /* Block width. */ static int BlockHeight = BLOCKHEIGHT; /* Block height. */ /* Buffer calculation information */ #define BufferIndex(i,iobuf) (iobuf)->blist[(i)] #define TrueBufferPos(buffer) (((buffer)->currentoffs - \ ((buffer)->tptr - (buffer)->bptr))/buffer->wsize) /*START*/ /*BFUNC MakeXBuffer() constructs a holding buffer for the stream input. It takes up a size passed into it and returns the appropriate buffer structure. EFUNC*/ static BUFFER *MakeXBuffer(nelem,wsize) int nelem; int wsize; { BEGIN("MakeXBuffer"); BUFFER *temp; if (!(temp = MakeStructure(BUFFER))) /* Make structure */ { WHEREAMI(); printf("Cannot allocate buffer structure.\n"); exit(ERROR_MEMORY); } temp->disable=0; /* Not disabled */ temp->wsize = wsize; /* Set up word size */ temp->size=nelem*wsize; /* Set up size, offset */ temp->currentoffs = 0; temp->streamoffs = 0; if (!(temp->space =(unsigned char *) /* Allocate buffer space */ calloc(temp->size+1,sizeof(unsigned char)))) { WHEREAMI(); printf("Cannot allocate buffer memory.\n"); exit(ERROR_MEMORY); } temp->tptr = temp->bptr = temp->space; return(temp); } /*BFUNC ResizeIob() is used to resize the Iob height and width to conform to that of the CScan. This is used for the dynamic Number-of-lines rescaling. EFUNC*/ void ResizeIob() { BEGIN("ResizeIob"); int index; for(index=0;indexNumberComponents;index++) { CScan->Iob[index]->width = CFrame->Width[CScan->ci[index]]; CScan->Iob[index]->height = CFrame->Height[CScan->ci[index]]; } } /*BFUNC MakeIob() is used to create an Iob structure for use in the CScan structure. An Iob consists of several Buffer structures with some additional sizing information. The input flags set up the parameters of the stream. EFUNC*/ void MakeIob(type,flags,wsize) int type; int flags; int wsize; { BEGIN("MakeIob"); int index,sofs; BUFFER **current; IOBUF *temp; for(index=0;indexNumberComponents;index++) /* Make IOBUF */ { /* For each component */ if (!(temp = MakeStructure(IOBUF))) { WHEREAMI(); printf("Cannot allocate IOBUF structure.\n"); exit(ERROR_MEMORY); } temp->linelastdefault=(1<<(CFrame->DataPrecision-PointTransform-1)); temp->type = type; temp->wsize = wsize; temp->hpos=0; temp->vpos=0; temp->width = CFrame->Width[CScan->ci[index]]; /* Set up widthxheight */ temp->height = CFrame->Height[CScan->ci[index]]; if (CScan->NumberComponents==1) { temp->hor = 1; /* For non-interleaved mode the freq */ temp->ver = 1; /* is always 1x1 */ } else { temp->hor = CFrame->hf[CScan->ci[index]]; /* and hf x vf */ temp->ver = CFrame->vf[CScan->ci[index]]; } switch(temp->type) { case IOB_BLOCK: /* BLOCK TYPE */ temp->num = temp->ver*BlockHeight; break; case IOB_LINE: /* LINE TYPE */ temp->num = temp->ver + 1; break; default: WHEREAMI(); printf("Illegal type specified: %d.\n",type); exit(ERROR_BOUNDS); } temp->flags = flags; /* and also flags */ if (!(temp->blist = /*Set up buffer list */ (BUFFER **) calloc(temp->num,sizeof(BUFFER *)))) { WHEREAMI(); printf("Cannot allocate Iob bufferlist.\n"); exit(ERROR_MEMORY); } if ((temp->file = /* Open file */ open(CFrame->ComponentFileName[CScan->ci[index]], flags,UMASK)) < 0) { WHEREAMI(); printf("Cannot open file %s.\n", CFrame->ComponentFileName[CScan->ci[index]]); exit(ERROR_INIT_FILE); } /* Make buffer for every line of component in MDU */ for(sofs=0,current=temp->blist;currentblist+temp->num;current++) { *current = MakeXBuffer(CFrame->BufferSize, wsize); (*current)->streamoffs = sofs; (*current)->iob = temp; (*current)->data_linelast = temp->linelastdefault; if (!temp->height || (current - temp->blist) < temp->height-1) { sofs += CFrame->Width[CScan->ci[index]]*wsize; } } CScan->Iob[index] = temp; } } /*BFUNC PrintIob() is used to print the current input buffer to the stdio stream. EFUNC*/ void PrintIob() { BEGIN("PrintIob"); if (Iob) { printf("*** Iob ID: %x ***\n",Iob); printf("Number of Buffers: %d Width: %d Height: %d\n", Iob->num,Iob->width,Iob->height); printf("hpos: %d vpos: %d hor-freq: %d ver-freq: %d\n", Iob->hpos,Iob->vpos,Iob->hor,Iob->ver); printf("filed: %d flags: %d BufferListId: %x\n", Iob->file,Iob->flags,Iob->blist); } else { printf("*** Iob ID: NULL ***\n"); } } /*BFUNC WriteXBuffer() writes out len elements from storage out to the buffer structure specified. This is can result in a multiple of len bytes being written out depending on the element structure. EFUNC*/ static void WriteXBuffer(len,storage,buffer) int len; int *storage; BUFFER *buffer; { BEGIN("WriteXBuffer"); int diff,wout; if (buffer->disable) { WHEREAMI(); printf("Attempting to write to disabled buffer!\n"); } /* printf("Writing:%d bytes\n",len);*/ diff = buffer->size - (buffer->bptr - buffer->space); /* Find room left */ diff = diff/buffer->wsize; /* Scale by element # */ if(len > diff) { /* Put as many elems in */ WriteXBuffer(diff,storage,buffer); /* If no room, then flush current */ FlushBuffer(buffer); /* buffer out to disk */ len -= diff; storage += diff; } switch(buffer->wsize) /* Because of compatibility differences between */ { /* UNIX implementations, we are forced to do this */ case 1: /* explicit ordering of bytes... */ while(len--) /* Write the rest of the buffer out to the disk */ { wout = *(storage++)<bptr++) = (unsigned char) wout; } break; case 2: while(len--) /* Write the rest of the buffer out to the disk */ { wout = *(storage++)<bptr++) = (unsigned char) (wout>>8)&0xff; *(buffer->bptr++) = (unsigned char) wout&0xff; } break; case 3: while(len--) /* Write the rest of the buffer out to the disk */ { wout = *(storage++)<bptr++) = (unsigned char) (wout>>16)&0xff; *(buffer->bptr++) = (unsigned char) (wout>>8)&0xff; *(buffer->bptr++) = (unsigned char) wout&0xff; } break; case 4: while(len--) /* Write the rest of the buffer out to the disk */ { wout = *(storage++)<bptr++) = (unsigned char) (wout>>24)&0xff; *(buffer->bptr++) = (unsigned char) (wout>>16)&0xff; *(buffer->bptr++) = (unsigned char) (wout>>8)&0xff; *(buffer->bptr++) = (unsigned char) wout&0xff; } break; default: WHEREAMI(); printf("Illegal word size in characters %d.\n",buffer->wsize); exit(ERROR_BOUNDS); break; } } /*BFUNC ReadXBuffer() is fetches len amount of elements into storage from the buffer structure. This may actually amount to an arbitrary number of characters depending on the word size. EFUNC*/ static void ReadXBuffer(len,storage,buffer) int len; int *storage; BUFFER *buffer; { BEGIN("ReadXBuffer"); int i,numchars,maxelem,rin; if (buffer->disable) { for(i=0;idata_linelast; return; } numchars = len*buffer->wsize; /* The following command recurses because */ /* it's slightly more efficient that way */ /* when the probability of recursion is */ /* negligible. */ while (numchars > buffer->size) /* We ask more than the buffer can handle */ { /* Inefficient for small buffer sizes */ maxelem = buffer->size/buffer->wsize; ReadXBuffer(maxelem, storage, buffer); /* Split up into several reads */ storage += maxelem; len -= maxelem; numchars -= maxelem*buffer->wsize; } if(numchars > (buffer->tptr - buffer->bptr)) /* If we request > bytes */ ReadResizeBuffer(numchars,buffer); /* Read those bytes in */ switch(buffer->wsize) /* Again, explicit input of bytes */ { case 1: while(len--) /* Now copy over to storage */ { rin = (int) *(buffer->bptr++); *(storage++) = rin >> PointTransform; } break; case 2: while(len--) /* Now copy over to storage */ { rin = (((int)*(buffer->bptr++))<<8); rin |= *(buffer->bptr++); *(storage++) = rin >> PointTransform; } break; case 3: while(len--) /* Now copy over to storage */ { rin = (((int)*(buffer->bptr++))<<16); rin |= (((int)*(buffer->bptr++))<<8); rin |= (*(buffer->bptr++)); *(storage++) = rin >> PointTransform; } break; case 4: while(len--) /* Now copy over to storage */ { rin = (((int)*(buffer->bptr++))<<24); rin |= (((int)*(buffer->bptr++))<<16); rin |= (((int)*(buffer->bptr++))<<8); rin |= (*(buffer->bptr++)); *(storage++) = rin >> PointTransform; } break; default: WHEREAMI(); printf("Illegal word size in characters %d.\n",buffer->wsize); exit(ERROR_BOUNDS); break; } #ifdef IO_DEBUG WHEREAMI(); printf("last read: %d",*(storage-1)); printf("\n"); #endif } /*BFUNC ReadResizeBuffer() reads len bytes from the stream and puts it into the buffer. EFUNC*/ static void ReadResizeBuffer(len,buffer) int len; BUFFER *buffer; { BEGIN("ReadResizeBuffer"); int retval,diff,location,amount; diff = buffer->tptr - buffer->bptr; /* Find out the current usage */ if (len > buffer->size-1) /* calculate if we can hold it */ { WHEREAMI(); printf("Length Request Too Large.\n"); exit(ERROR_PARAMETER); } #ifdef IO_DEBUG printf("SPACE: %x BPTR: %x DIFF: %d\n",buffer->space,buffer->bptr,diff); printf("ReadLseek %d\n",buffer->streamoffs+buffer->currentoffs); #endif memcpy(buffer->space,buffer->bptr,diff); /* Move buffer down. */ buffer->bptr = buffer->space; /* Reset pointers. */ buffer->tptr = buffer->space + diff; location = buffer->streamoffs+buffer->currentoffs; amount = buffer->size-(buffer->tptr - buffer->space); lseek(buffer->iob->file,location,L_SET); #ifdef IO_DEBUG printf("Read: Filed %d Buf: %x NBytes: %d\n", buffer->iob->file,buffer->tptr,amount); #endif if ((retval = read(buffer->iob->file, /* Do the read */ buffer->tptr, amount)) < 0) { WHEREAMI(); printf("Cannot Resize.\n"); exit(ERROR_READ); } #ifdef IO_DEBUG printf("ReadReturn numbytes %d\n",retval); #endif buffer->tptr += retval; /* Alter pointers */ buffer->currentoffs += retval; } /*BFUNC FlushBuffer() saves the rest of the bytes in the buffer out to the disk. EFUNC*/ static void FlushBuffer(buffer) BUFFER *buffer; { BEGIN("FlushBuffer"); int retval; #ifdef IO_DEBUG printf("WriteLseek %d\n",buffer->streamoffs+buffer->currentoffs); #endif lseek(buffer->iob->file,buffer->streamoffs+buffer->currentoffs,L_SET); if ((retval = write(buffer->iob->file, buffer->space, (buffer->bptr - buffer->space))) < 0) { WHEREAMI(); printf("Cannot flush buffer.\n"); exit(ERROR_WRITE); } buffer->currentoffs += (buffer->bptr - buffer->space); buffer->bptr = buffer->space; } /*BFUNC ReadBlock() is used to get a block from the current Iob. This function returns (for the JPEG case) 64 bytes in the store integer array. It is stored in row-major form; that is, the row index changes least rapidly. EFUNC*/ void ReadBlock(store) int *store; { BEGIN("ReadBlock"); int i,voffs; voffs = (Iob->vpos % Iob->ver)*BlockHeight; /* Find current v offset*/ #ifdef IO_DEBUG for(i=0;iblist[i]->Iob); } #endif for(i=voffs;iblist[i]->Iob); #endif ReadXBound(BlockWidth,store,Iob->blist[i]); /* get blockwidth elms */ store+=BlockWidth; /* Storage array & increment */ } /* by blockwidth */ if ((++Iob->hpos % Iob->hor)==0) /* Increment MDU block pos */ { if ((++Iob->vpos % Iob->ver) == 0) { if (Iob->hpos < CScan->MDUWide*Iob->hor) { Iob->vpos -= Iob->ver; } else { Iob->hpos = 0; /* If at end of raster width*/ BlockMoveTo(); /* Reload buffers from start */ } /* of next line. */ } else { Iob->hpos -= Iob->hor; } } } /*BFUNC WriteBlock() writes an array of data in the integer array pointed to by store out to the driver specified by the IOB. The integer array is stored in row-major form, that is, the first row of (8) elements, the second row of (8) elements.... EFUNC*/ void WriteBlock(store) int *store; { BEGIN("WriteBlock"); int i,voffs; voffs = (Iob->vpos % Iob->ver)*BlockHeight; /* Find vertical buffer offs. */ for(i=voffs;iheight || (((Iob->vpos/Iob->ver)*BlockHeight + i) < Iob->height)) { WriteXBound(BlockWidth,store,Iob->blist[i]); /* write Block elms */ store+=BlockWidth; /* Iob indexed by offset */ } } if ((++Iob->hpos % Iob->hor)==0) /* Increment block position */ { /* in MDU. */ if ((++Iob->vpos % Iob->ver) == 0) { if (Iob->hpos < CScan->MDUWide*Iob->hor) { Iob->vpos -= Iob->ver; } else { Iob->hpos = 0; /* If at end of image (width) */ FlushIob(); /* Flush current IOB and */ BlockMoveTo(); /* Move to next lower MDU line */ } } else { Iob->hpos -= Iob->hor; } } } /*BFUNC BlockMoveTo() is used to move to a specific vertical and horizontal location (block wise) specified by the current Iob. That means you set the current Iob parameters and then call BlockMoveTo(). EFUNC*/ static void BlockMoveTo() { BEGIN("BlockMoveTo"); int i,vertical,horizontal; if (Loud > MUTE) { WHEREAMI(); printf("%x Moving To [Horizontal:Vertical] [%d:%d] \n", Iob,Iob->hpos,Iob->vpos); } horizontal = Iob->hpos * BlockWidth; /* Calculate actual */ vertical = Iob->vpos * BlockHeight; /* Pixel position */ for(i=0;iver*BlockHeight;i++) { if (Iob->height) { vertical = ((vertical < Iob->height) ? vertical : Iob->height-1); } Iob->blist[i]->tptr = /* Reset pointer space */ Iob->blist[i]->bptr = /* To show no contents */ Iob->blist[i]->space; Iob->blist[i]->currentoffs = horizontal* Iob->wsize;/* reset h offset */ Iob->blist[i]->streamoffs = vertical * Iob->width * Iob->wsize; /* Reset v offset */ vertical++; } } /*BFUNC RewindIob() brings all the pointers to the start of the file. The reset does not flush the buffers if writing. EFUNC*/ void RewindIob() { BEGIN("RewindIob"); int i; switch(Iob->type) { case IOB_BLOCK: BlockWidth = BLOCKWIDTH; /* Block width. */ BlockHeight = BLOCKHEIGHT; /* Block height. */ for(i=0;iver*BlockHeight;i++) { Iob->blist[i]->tptr = Iob->blist[i]->bptr = Iob->blist[i]->space; Iob->blist[i]->currentoffs = 0; Iob->blist[i]->streamoffs = i * Iob->width * Iob->wsize; } Iob->hpos = Iob->vpos = 0; break; case IOB_LINE: Iob->linelastdefault=(1<<(CFrame->DataPrecision-PointTransform-1)); for(i= 0;iver+1;i++) { Iob->blist[i]->tptr = Iob->blist[i]->bptr = Iob->blist[i]->space; Iob->blist[i]->currentoffs = 0; if (!i) { Iob->blist[i]->streamoffs = 0; Iob->blist[i]->disable=1; } else { Iob->blist[i]->streamoffs = (i-1) * Iob->width * Iob->wsize; Iob->blist[i]->disable=0; } Iob->blist[i]->data_linelast = Iob->linelastdefault; } Iob->hpos = 0; Iob->vpos = -1; break; default: WHEREAMI(); printf("Bad IOB type: %d\n",Iob->type); break; } } /*BFUNC FlushIob() is used to flush all the buffers in the current Iob. This is done at the conclusion of a write on the current buffers. EFUNC*/ void FlushIob() { BEGIN("FlushIob"); int i; if (Loud > MUTE) printf("IOB: %x Flushing buffers\n",Iob); switch(Iob->type) { case IOB_BLOCK: for(i=0;iver*BlockHeight;i++) FlushBuffer(Iob->blist[i]); break; case IOB_LINE: Iob->blist[0]->data_linelast=Iob->linelastdefault; for(i=1;iver+1;i++) { Iob->blist[i]->data_linelast=Iob->linelastdefault; FlushBuffer(Iob->blist[i]); } break; default: WHEREAMI(); printf("Illegal IOB type: %d.\n",Iob->type); break; } } /*BFUNC SeekEndIob() is used to seek the end of all the buffers in the current Iob. This is done at the conclusion of a write, to avoid DNL problems. EFUNC*/ void SeekEndIob() { BEGIN("SeekEndIob"); int size,tsize; static char Terminator[] = {0x80,0x00}; size = lseek(Iob->file,0,2); tsize = Iob->width*Iob->height*Iob->wsize; if (size != tsize) { WHEREAMI(); printf("End not flush, making flush (actual: %d != target:%d)\n", size,tsize); if (sizefile,tsize-1,0L); /* Seek and terminate */ write(Iob->file,Terminator,1); } else if (size > tsize) { #ifdef NOTRUNCATE WHEREAMI(); printf("file is too large, only first %d bytes valid\n", tsize); #else ftruncate(Iob->file,tsize); /* simply truncate*/ #endif } } } /*BFUNC CloseIob() is used to close the current Iob. EFUNC*/ void CloseIob() { BEGIN("CloseIob"); close(Iob->file); } /*BFUNC ReadXBound() reads nelem elements of information from the specified buffer. It detects to see whether a load is necessary or not, or whether the current buffer is out of the image width bounds. EFUNC*/ static void ReadXBound(nelem,cstore,buffer) int nelem; int *cstore; BUFFER *buffer; { BEGIN("ReadXBound"); int i,diff; if ((diff = buffer->iob->width - TrueBufferPos(buffer)) <= nelem) { #ifdef IO_DEBUG printf("ReadBound: Trailing Edge Detected. Diff: %d\n",diff); #endif if (diff <= 0) { for(i=0;ioverflow; } else { ReadXBuffer(diff,cstore,buffer); buffer->overflow = (unsigned int) cstore[diff-1]; for(i=diff;iiob->width - TrueBufferPos(buffer)) <= nelem) { /* Diff is balance to write to disk */ if (diff > 0) /* Write balance out to disk */ WriteXBuffer(diff,cstore,buffer); } else /* If more than numberelem, then can put all */ WriteXBuffer(nelem,cstore,buffer); /* to the buffer. */ } /*BFUNC InstallIob() is used to install the Iob in the current scan as the real Iob. EFUNC*/ void InstallIob(index) int index; { BEGIN("InstallIob"); if (!(Iob = CScan->Iob[index])) { WHEREAMI(); printf("Warning, NULL Iob installed.\n"); } } /*BFUNC TerminateFile() is a function that ensures that the entire file defined by the Iob is properly flush with the filesize specifications. This function is used when some fatal error occurs. EFUNC*/ void TerminateFile() { BEGIN("TerminateFile"); int i,size; static char Terminator[] = {0x80,0x00}; if (CFrame->GlobalHeight) { printf("> GH:%d GW:%d R:%d\n", CFrame->GlobalHeight, CFrame->GlobalWidth, CFrame->ResyncInterval); for(i=0;iNumberComponents;i++) { if (CScan->Iob[i]) { printf(">> C:%d N:%s H:%d W:%d hf:%d vf:%d\n", CScan->ci[i], CFrame->ComponentFileName[CScan->ci[i]], CFrame->Height[CScan->ci[i]], CFrame->Width[CScan->ci[i]], CFrame->hf[CScan->ci[i]], CFrame->vf[CScan->ci[i]]); InstallIob(i); FlushIob(); size = lseek(CScan->Iob[i]->file,0,2); if (size != CFrame->Width[CScan->ci[i]]*CFrame->Height[CScan->ci[i]]* CScan->Iob[i]->wsize) { /* Terminate file */ lseek(CScan->Iob[i]->file, /* by seeking to end */ (CFrame->Width[CScan->ci[i]]* /* And writing byte */ CFrame->Height[CScan->ci[i]]* CScan->Iob[i]->wsize)-1, /* Making flush with */ 0L); /* Original size */ write(CScan->Iob[i]->file,Terminator,1); } } } } else { WHEREAMI(); printf("Unknown number of lines. Cannot flush file.\n"); } } /*BFUNC ReadLine() reads in the lines required by the lossless function. The array *store should be large enough to handle the line information read. In total, there should be (HORIZONTALFREQUENCY+1) * nelem (VERTICALFREQUENCY+1) elements in the *store array. This forms a matrix with each line consisting of: [PastPredictor 1 element] nelem* [HORIZONTALFREQUENCY elements] And there are (VERTICALFREQUENCY+1) of such lines in the matrix: Previous line (2**Precision-1) if beyond specifications of window Active line 1... ... Active line VERTICALFREQUENCY... EFUNC*/ void ReadLine(nelem,store) int nelem; int *store; { BEGIN("ReadLine"); int i; for(i=0;iver+1;i++) /* Use voffs to index into */ { /* Buffer list of IOB */ #ifdef IO_DEBUG printf("%d Iob %x\n",i,Iob->blist[i]->Iob); #endif *(store++)=Iob->blist[i]->data_linelast; ReadXBound(Iob->hor*nelem,store,Iob->blist[i]); store+=Iob->hor*nelem; Iob->blist[i]->data_linelast = *(store-1); } Iob->hpos += Iob->hor*nelem; if (Iob->hpos >= CScan->MDUWide*Iob->hor) { Iob->vpos += Iob->ver; Iob->hpos = 0; /* If at end of raster width*/ LineMoveTo(); /* Reload buffers from start */ } /* of next line. */ } /*BFUNC ReadPreambleLine() reads the first line of the *store array for the WriteLine() companion command. It reads it so that prediction can be accomplished with minimum effort and storage. This command is executed before decoding a particular line for the prediction values; WriteLine() is called after the decoding is done. EFUNC*/ void ReadPreambleLine(nelem,store) int nelem; int *store; { BEGIN("ReadPreambleLine"); int i; int preamblelength=1; for(i=0;iver+1;i++) /* Use voffs to index into */ { /* Buffer list of IOB */ #ifdef IO_DEBUG printf("%d Iob %x\n",i,Iob->blist[i]->Iob); #endif if (iblist[i]->data_linelast; ReadXBound(Iob->hor*nelem,store,Iob->blist[i]); store+=Iob->hor*nelem; Iob->blist[i]->data_linelast = *(store-1); } else { *(store) = Iob->blist[i]->data_linelast; store += Iob->hor*nelem+1; } } } /*BFUNC WriteLine() is used to write a particular line out to the IOB. The line must be of the proper form in the array for this function to work. In total, there should be (HORIZONTALFREQUENCY+1) * nelem (VERTICALFREQUENCY+1) elements in the *store array. This forms a matrix with each line consisting of: [PastPredictor 1 element] nelem* [HORIZONTALFREQUENCY elements] And there are (VERTICALFREQUENCY+1) of such lines in the matrix: Previous line (2**Precision-1) if beyond specifications of window Active line 1... ... Active line VERTICALFREQUENCY... EFUNC*/ void WriteLine(nelem,store) int nelem; int *store; { BEGIN("WriteLine"); int i; store += Iob->hor*nelem+1; /* Get rid of first line */ for(i=1;iver+1;i++) /* Use voffs to index into */ { /* Buffer list of IOB */ #ifdef IO_DEBUG printf("WriteLine: %d Store: %d Iobblist: %x\n", i,*(store+1),Iob->blist[i]); #endif WriteXBound(Iob->hor*nelem,store+1,Iob->blist[i]); store+=(Iob->hor*nelem)+1; Iob->blist[i]->data_linelast = *(store-1); } Iob->hpos += Iob->hor*nelem; if (Iob->hpos >= CScan->MDUWide*Iob->hor) { Iob->vpos += Iob->ver; Iob->hpos = 0; /* If at end of raster width*/ FlushIob(); /* Flush current IOB and */ LineMoveTo(); /* Reload buffers from start */ } /* of next line. */ } /*BFUNC LineResetBuffers() resets all of the line buffers to the (2\^DataPrecision-1) state. The previous state is the default prediction. This commmand is used for resynchronization. The implementation here does a trivial resetting. EFUNC */ extern void LineResetBuffers() { BEGIN("LineResetBuffers"); int i; if (Iob->type!=IOB_LINE) { WHEREAMI(); printf("Attempting to line reset a non-line buffer!\n"); exit(ERROR_PARAMETER); } for(i=0;iver+1;i++) Iob->blist[i]->data_linelast = Iob->linelastdefault; } /*BFUNC LineMoveTo() is used to move to a specific vertical and horizontal location (line wise) specified by the current Iob. That means you set the current Iob parameters and then call LineMoveTo(). EFUNC*/ static void LineMoveTo() { BEGIN("LineMoveTo"); int i,vertical,horizontal; if (Loud > MUTE) { WHEREAMI(); printf("%x Moving To [Horizontal:Vertical] [%d:%d] \n", Iob,Iob->hpos,Iob->vpos); } horizontal = Iob->hpos; vertical = Iob->vpos; for(i=0;iver+1;i++) { /* Reset last element read */ if (vertical<0) { Iob->blist[i]->disable=1; continue; } Iob->blist[i]->disable=0; Iob->blist[i]->data_linelast=Iob->linelastdefault; if (Iob->height) { vertical = ((vertical < Iob->height) ? vertical : Iob->height-1); } Iob->blist[i]->tptr = /* Reset pointer space */ Iob->blist[i]->bptr = /* To show no contents */ Iob->blist[i]->space; Iob->blist[i]->currentoffs = horizontal* Iob->wsize; /* Reset h offset */ Iob->blist[i]->streamoffs = vertical * Iob->width * Iob->wsize; /* Reset v offset */ vertical++; } } /*END*/ pvrg-jpeg-1.2.1/tables.h0000644000175000017500000001114205725222777014417 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ /* ************************************************************ tables.h This file contains the default huffman and quantization tables. ************************************************************ */ #ifndef TABLES_DONE #define TABLES_DONE static int LuminanceQuantization[] = { 16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92, 49, 64, 78, 87, 103, 121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99}; static int ChrominanceQuantization[] = { 17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}; static int LuminanceDCBits[] = { 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static int LuminanceDCValues[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b}; static int ChrominanceDCBits[] = { 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; static int ChrominanceDCValues[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b}; static int LuminanceACBits[] = { 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d}; static int LuminanceACValues[] = { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa}; static int ChrominanceACBits[] = { 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77}; static int ChrominanceACValues[] = { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa}; #endif pvrg-jpeg-1.2.1/system.h0000644000175000017500000000713605725222777014501 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ /* ************************************************************ system.h This file contains the miscellaneous definitions for running the JPEG coder. ************************************************************ */ #ifndef SYSTEM_DONE #define SYSTEM_DONE #include #define IOB_BLOCK 0 #define IOB_LINE 1 #define IOB_OVERSAMPLEBLOCK 2 #define BUFFER struct io_buffer #define IOBUF struct io_buffer_list #define XHUFF struct huffman_standard_structure #define EHUFF struct huffman_encoder #define DHUFF struct huffman_decoder BUFFER { unsigned int overflow; /* The last buffer character on line overflow */ int data_linelast; /* The last element read out for line buffering */ int disable; /* Stream is disabled! */ int wsize; /* Element word size in characters */ int size; /* Size of buffer in characters */ long currentoffs; /* Current offset from left edge of image */ long streamoffs; /* Stream offset (the pixel index of left edge) */ unsigned char *space; /* Space is the raw buffer pointer */ unsigned char *bptr; /* Current base pointer of buffer */ unsigned char *tptr; /* Current top pointer of buffer */ IOBUF *iob; /* References own IOB */ }; IOBUF { int type; /* Iob type */ int num; /* Number of buffers */ int wsize; /* Element word size in characters */ int hpos; /* Current block position in image */ int vpos; int hor; /* Sampling frequency */ int ver; int width; /* Width and height of image */ int height; int file; /* File descriptor */ int flags; /* File mode flags */ int linelastdefault; /* Last line element default */ BUFFER **blist; /* A list of buffers */ }; /* XHUFF contains all the information that needs be transmitted */ /* EHUFF and DHUFF are derivable from XHUFF */ XHUFF { int bits[36]; /* Bit-length frequency (indexed on length */ int huffval[257]; /* Huffman value index */ }; /* Encoder tables */ EHUFF { int ehufco[257]; /* Encoder huffman code indexed on code word */ int ehufsi[257]; /* Encoder huffman code-size indexed on code word */ }; /* Decoder tables */ DHUFF { int ml; /* Maximum length */ int maxcode[36]; /* Max code for a given bit length -1 if no codes */ int mincode[36]; /* Min code for a given bit length */ int valptr[36]; /* First index (of min-code) for a given bit-length */ }; #endif pvrg-jpeg-1.2.1/SETUP0000644000175000017500000000505105725223012013600 0ustar naolivnaolivJPEG version 1.2 1) Printing documentation: Documentation is in the PostScript file doc.ps. It is about 50 pages long. 2) Making the program. The makefile should be setup for most UNIX systems as is. Simply type "make" in the source code directory. For SYSV only libraries, substitute the first line in the makefile #DEFINES = -DSYSV -DNOTRUNCATE for #DEFINES which allows for SYSV libraries to be used instead. The NOTRUNCATE flag avoids the lack of the ftruncate() call used in io.c. Caution: For the compilation, the lexer.l file should be older than the lexer.c file otherwise many machines will try and lex the lexer.l file (thus clobbering potentially the lexer.c file). In general, the tar will take out the lexer.l file first (it's specified to do that), so there shouldn't be any problems unless the directory is _copied_ and then remade, in which case, the lexer.c file will be older because is lexically of lesser value than lexer.l. This is a potential bug. 3) Testing the program. Two small test files are nonint.jpg and blkint.jpg. If you wish to extract them, type jpeg -d -s nonint.jpg jpeg -d -s blkint.jpg The resulting files should be in nonint.jpg.1 nonint.jpg.2 nonint.jpg.3 blkint.jpg.1 blkint.jpg.2 blkint.jpg.3 These files are raw raster-scan component files 128x128 for the Y (.1), 64x128 for the U(.2) and V(.3). 4) Displaying the decompressed files. The decompressed *.1 *.2 *.3 files may be displayed through the program "cv" which may be obtained by anonymous ftp from havefun.stanford.edu:pub/cv/CVv1.1.tar.Z. If the program is in your current directory search-path, type cv -iw 128 -ih 128 nonint.jpg -SF or cv -iw 128 -ih 128 blkint.jpg -SF 5) Recompressing the sample files Use the following commands to recompress the nonint.jpg.* component files into the nonint.jpg2 file: jpeg -iw 128 -ih 128 -n -hf 2 nonint.jpg.1 nonint.jpg.2 nonint.jpg.3 \ -s nonint2.jpg Use the following commands to recompress the blkint.jpg.* component files into the blkint.jpg2 file: jpeg -iw 128 -ih 128 -hf 2 blkint.jpg.1 blkint.jpg.2 blkint.jpg.3 \ -s blkint2.jpg Surprisingly, recompressing and decompressing the blkint should yield the same result. (The nonint files will not yield the same result - but very close - since the non-interleaved mode defaults to using the LUMINANCE quantization matrix for the first color component of each scan.) See the documentation for more details on other parameters. 6) Some short interpreted programs for the encoder: (See Chapter 4 of the documentation behind these programs). test.huff test.3stream test.q pvrg-jpeg-1.2.1/stream.c0000644000175000017500000005757105725223006014435 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ /* ************************************************************ stream.c This file is used for management of bit-aligned files. ************************************************************ */ /*LABEL stream.c */ /* Include files */ #include "globals.h" #include "marker.h" #include "stream.h" /*PUBLIC*/ extern void initstream(); extern void pushstream(); extern void popstream(); extern void bpushc(); extern int bgetc(); extern void bputc(); extern void mropen(); extern void mrclose(); extern void mwopen(); extern void swbytealign(); extern void mwclose(); extern long mwtell(); extern long mrtell(); extern void mwseek(); extern void mrseek(); extern int megetb(); extern void meputv(); extern int megetv(); extern int DoMarker(); extern int ScreenMarker(); extern void Resync(); extern void WriteResync(); extern int ReadResync(); extern int ScreenAllMarker(); extern int DoAllMarker(); static int pgetc(); /*PRIVATE*/ /* External values */ extern int ErrorValue; extern IMAGE *CImage; extern int Robust; /* Whether to ignore scan markers and such */ /* Masks */ int bit_set_mask[] = { /* This is 2^i at ith position */ 0x00000001,0x00000002,0x00000004,0x00000008, 0x00000010,0x00000020,0x00000040,0x00000080, 0x00000100,0x00000200,0x00000400,0x00000800, 0x00001000,0x00002000,0x00004000,0x00008000, 0x00010000,0x00020000,0x00040000,0x00080000, 0x00100000,0x00200000,0x00400000,0x00800000, 0x01000000,0x02000000,0x04000000,0x08000000, 0x10000000,0x20000000,0x40000000,0x80000000}; int lmask[] = { /* This is 2^{i+1}-1 */ 0x00000001,0x00000003,0x00000007,0x0000000f, 0x0000001f,0x0000003f,0x0000007f,0x000000ff, 0x000001ff,0x000003ff,0x000007ff,0x00000fff, 0x00001fff,0x00003fff,0x00007fff,0x0000ffff, 0x0001ffff,0x0003ffff,0x0007ffff,0x000fffff, 0x001fffff,0x003fffff,0x007fffff,0x00ffffff, 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff, 0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff}; #ifdef __OLD int umask[] = { /* This is -1 XOR 2^{i+1}-1 */ 0xfffffffe,0xfffffffc,0xfffffff8,0xfffffff0, 0xffffffe0,0xffffffc0,0xffffff80,0xffffff00, 0xfffffe00,0xfffffc00,0xfffff800,0xfffff000, 0xffffe000,0xffffc000,0xffff8000,0xffff0000, 0xfffe0000,0xfffc0000,0xfff80000,0xfff00000, 0xffe00000,0xffc00000,0xff800000,0xff000000, 0xfe000000,0xfc000000,0xf8000000,0xf0000000, 0xe0000000,0xc0000000,0x80000000,0x00000000}; #endif /* Internally kept variables for global flag communication */ int CleartoResync=0; /* Return black blocks until last Resync reached*/ int ResyncEnable=0; /* This enables the resync feature */ int ResyncCount=0; /* This is the resync marker count */ int LastKnownResync=0; /* This is the index of the next Resync */ int EndofFile=0; /* End of file means read stream exhausted */ int EndofImage=0; /* End of image means EOI image marker found */ /* Static variables that keep internal state. */ static FILE *swout; static FILE *srin; static unsigned int current_write_byte; static unsigned int current_read_byte; static unsigned int marker_read_byte; static int read_position; static int write_position; static int InResync=0; /* Stack of variables to handle multiple streams. */ static int Stack_Stream_Current= -1; static int Stack_Stream_Active[NUMBER_OF_STREAMS]; static int Stack_Stream_CleartoResync[NUMBER_OF_STREAMS]; static int Stack_Stream_ResyncEnable[NUMBER_OF_STREAMS]; static int Stack_Stream_ResyncCount[NUMBER_OF_STREAMS]; static int Stack_Stream_LastKnownResync[NUMBER_OF_STREAMS]; static int Stack_Stream_EndofFile[NUMBER_OF_STREAMS]; static int Stack_Stream_EndofImage[NUMBER_OF_STREAMS]; static FILE * Stack_Stream_swout[NUMBER_OF_STREAMS]; static FILE * Stack_Stream_srin[NUMBER_OF_STREAMS]; static unsigned int Stack_Stream_current_write_byte[NUMBER_OF_STREAMS]; static unsigned int Stack_Stream_current_read_byte[NUMBER_OF_STREAMS]; static unsigned int Stack_Stream_marker_read_byte[NUMBER_OF_STREAMS]; static int Stack_Stream_read_position[NUMBER_OF_STREAMS]; static int Stack_Stream_write_position[NUMBER_OF_STREAMS]; /*START*/ /* STACK STREAM LIBRARY */ /*BFUNC initstream() initializes all of the stream variables-- especially the stack. Not necessary to call unless you wish to use more than one stream variable. EFUNC*/ void initstream() { BEGIN("initstream"); int i; Stack_Stream_Current= -1; for(i=0;i=0) pushstream(); CleartoResync=Stack_Stream_CleartoResync[index]; ResyncEnable=Stack_Stream_ResyncEnable[index]; ResyncCount=Stack_Stream_ResyncCount[index]; LastKnownResync=Stack_Stream_LastKnownResync[index]; EndofFile=Stack_Stream_EndofFile[index]; EndofImage=Stack_Stream_EndofImage[index]; swout=Stack_Stream_swout[index]; srin=Stack_Stream_srin[index]; current_write_byte=Stack_Stream_current_write_byte[index]; current_read_byte=Stack_Stream_current_read_byte[index]; marker_read_byte=Stack_Stream_marker_read_byte[index]; read_position=Stack_Stream_read_position[index]; write_position=Stack_Stream_write_position[index]; } /* THAT'S ALL FOR THE STACK STREAM LIBRARY! */ /* BUFFER LIBRARY */ /*BFUNC brtell() is used to find the location in the read stream. EFUNC*/ int brtell() {BEGIN("brtell");return(ftell(srin));} /*BFUNC brseek() is used to find the location in the read stream. EFUNC*/ int brseek(offset,ptr) int offset; int ptr; {BEGIN("brseek");return(fseek(srin,offset,ptr));} /*BFUNC bpushc() is used to unget a character value from the current stream. EFUNC*/ void bpushc(value) int value; {BEGIN("bpushc");ungetc(value,srin);} /*BFUNC bgetc() gets a character from the stream. It is byte aligned and bypasses bit buffering. EFUNC*/ int bgetc() {BEGIN("bgetc");return(getc(srin));} /*BFUNC bgetw() gets a msb word from the stream. EFUNC*/ int bgetw() {BEGIN("bgetw"); int fu; fu=getc(srin); return ((fu << 8)| getc(srin));} /*BFUNC bputc() puts a character into the stream. It is byte aligned and bypasses the bit buffering. EFUNC*/ void bputc(c) int c; {BEGIN("bputc");putc(c,swout);} /* PROTECTED MARKER GETS AND FETCHES */ /*BFUNC pgetc() gets a character onto the stream but it checks to see if there are any marker conflicts. EFUNC*/ static int pgetc() { BEGIN("pgetc"); int temp; if (CleartoResync) /* If cleartoresync do not read from stream */ { return(0); } if ((temp = bgetc())==MARKER_MARKER) /* If MARKER then */ { if ((temp = bgetc())) /* if next is not 0xff, then marker */ { WHEREAMI(); printf("Unanticipated marker detected.\n"); if (!ResyncEnable) DoAllMarker(); /* If no resync enabled */ } /* could be marker */ else { return(MARKER_MARKER); /* else truly 0xff */ } } return(temp); } /*BMACRO pputc(stream,) ) puts a value onto the stream; puts a value onto the stream, appending an extra '0' if it matches the marker code. EMACRO*/ #define pputc(val) {bputc(val); if (val==MARKER_MARKER) bputc(0);} /* MAIN ROUTINES */ /*BFUNC mropen() opens a given filename as the input read stream. EFUNC*/ void mropen(filename,index) char *filename; int index; { BEGIN("mropen"); if (Stack_Stream_Active[index]) { WHEREAMI(); printf("%s cannot be opened because %d stream slot filled.\n", filename,index); exit(ERROR_BOUNDS); } if (Stack_Stream_Current!=index) pushstream(); current_read_byte=0; read_position = -1; if ((srin = fopen(filename,"r"))==NULL) { WHEREAMI(); printf("Cannot read input file %s.\n", filename); exit(ERROR_INIT_FILE); } CleartoResync=0; ResyncEnable=0; ResyncCount=0; LastKnownResync=0; EndofFile=0; EndofImage=1; /* We start after "virtual" end of previous image */ Stack_Stream_Current= index; Stack_Stream_Active[index]=1; } /*BFUNC mrclose() closes the input read stream. EFUNC*/ void mrclose() { BEGIN("mrclose"); fclose(srin); srin=NULL; if (swout==NULL) { Stack_Stream_Active[Stack_Stream_Current]=0; Stack_Stream_Current= -1; } } /*BFUNC mwopen() opens the stream for writing. Note that reading and writing can occur simultaneously because the read and write routines are independently buffered. EFUNC*/ void mwopen(filename,index) char *filename; int index; { BEGIN("mwopen"); if (Stack_Stream_Active[index]) { WHEREAMI(); printf("%s cannot be opened because %d stream slot filled.\n", filename,index); exit(ERROR_BOUNDS); } if ((Stack_Stream_Current!=index)) pushstream(); current_write_byte=0; write_position=7; if ((swout = fopen(filename,"w+"))==NULL) { WHEREAMI(); printf("Cannot open output file %s.\n",filename); exit(ERROR_INIT_FILE); } Stack_Stream_Current= index; Stack_Stream_Active[index]=1; } /*BFUNC swbytealign() flushes the current bit-buffered byte out to the stream. This is used before marker codes. EFUNC*/ void swbytealign() { BEGIN("swbytealign"); if (write_position !=7) { current_write_byte |= lmask[write_position]; pputc(current_write_byte); write_position=7; current_write_byte=0; } } /*BFUNC mwclose() closes the stream that has been opened for writing. EFUNC*/ void mwclose() { BEGIN("mwclose"); swbytealign(); fclose(swout); swout=NULL; if (srin==NULL) { Stack_Stream_Active[Stack_Stream_Current]=0; Stack_Stream_Current= -1; } } /*BFUNC mwtell() returns the bit position on the write stream. EFUNC*/ long mwtell() { BEGIN("mwtell"); return((ftell(swout)<<3) + (7 - write_position)); } /*BFUNC mrtell() returns the bit position on the read stream. EFUNC*/ long mrtell() { BEGIN("mrtell"); return((ftell(srin)<<3) - (read_position+1)); } /*BFUNC mwseek returns the bit position on the write stream. EFUNC*/ void mwseek(distance) long distance; { BEGIN("mwseek"); int length; if (write_position!=7) /* Must flush out current byte */ { putc(current_write_byte,swout); } fseek(swout,0,2L); /* Find end */ length = ftell(swout); fseek(swout,((distance+7)>>3),0L); if ((length<<3) <= distance) /* Make sure we read clean stuff */ { current_write_byte = 0; write_position = 7 - distance & 0x7; } else { current_write_byte = getc(swout); /* if within bounds, then read byte */ write_position = 7 - (distance & 0x7); fseek(swout,((distance+7)>>3),0L); /* Reset seek pointer for write */ } } /*BFUNC mrseek() jumps to a bit position on the read stream. EFUNC*/ void mrseek(distance) long distance; { BEGIN("mrseek"); fseek(srin,(distance>>3),0L); /* Go to location */ current_read_byte = bgetc(); /* read byte in */ read_position = 7 - (distance % 8); } /*BFUNC megetb() gets a bit from the read stream. EFUNC*/ int megetb() { BEGIN("megetb"); if (read_position < 0) { current_read_byte = pgetc(); read_position=7; } if (current_read_byte&bit_set_mask[read_position--]) { return(1); } return(0); } /*BFUNC meputv() puts n bits from b onto the writer stream. EFUNC*/ void meputv(n,b) int n; int b; { BEGIN("meputv"); int p; n--; b &= lmask[n]; p = n - write_position; if (!p) /* Can do parallel save immediately */ { current_write_byte |= b; pputc(current_write_byte); current_write_byte = 0; write_position = 7; return; } else if (p < 0) /* if can fit, we have to shift byte */ { p = -p; current_write_byte |= (b << p); write_position = p-1; return; } current_write_byte |= (b >> p); /* cannot fit. we must do putc's */ pputc(current_write_byte); /* Save off remainder */ while(p > 7) /* Save off bytes while remaining > 7 */ { p -= 8; current_write_byte = (b >> p) & lmask[7]; pputc(current_write_byte); } if (!p) /* If zero then reset position */ { write_position = 7; current_write_byte = 0; } else /* Otherwise reset write byte buffer */ { write_position = 8-p; current_write_byte = (b << write_position) & lmask[7]; write_position--; } } /*BFUNC megetv() gets n bits from the read stream and returns it. EFUNC*/ int megetv(n) int n; { BEGIN("megetv"); int p,rv; n--; p = n-read_position; while(p > 0) { if (read_position>23) /* If byte buffer contains almost entire word */ { rv = (current_read_byte << p); /* Manipulate buffer */ current_read_byte = pgetc(); /* Change read bytes */ rv |= (current_read_byte >> (8-p)); read_position = 7-p; return(rv & lmask[n]); /* Can return pending residual val */ } current_read_byte = (current_read_byte << 8) | pgetc(); read_position += 8; /* else shift in new information */ p -= 8; } if (!p) /* If position is zero */ { read_position = -1; /* Can return current byte */ return(current_read_byte & lmask[n]); } p = -p; /* Else reverse position and shift */ read_position = p-1; return((current_read_byte >> p) & lmask[n]); } /*BFUNC DoMarker() performs marker analysis. We assume that the Current Marker head has been read (0xFF) plus top information is at marker\_read\_byte. EFUNC*/ int DoMarker() { BEGIN("DoMarker"); int i,hin,lon,marker,length; current_read_byte = 0; read_position= -1; /* Make sure we are byte-flush. */ while(marker_read_byte==MARKER_FIL) /* Get rid of FIL markers */ { #ifdef VERSION_1.0 if ((marker_read_byte = bgetc())!=MARKER_MARKER) { WHEREAMI(); printf("Unknown FIL marker. Bypassing.\n"); ErrorValue = ERROR_MARKER; return(0); } #endif marker_read_byte = bgetc(); } lon = marker_read_byte & 0x0f; /* Segregate between hi and lo */ hin = (marker_read_byte>>4) & 0x0f; /* nybbles for the marker read byte */ marker = marker_read_byte; if (InResync) { if ((marker <0xd0)||(marker>0xd7)) { WHEREAMI(); printf("Illegal resync marker found.\n"); return(0); } } switch(hin) /* Pretty much self explanatory */ { case 0x0c: /* Frame Style Marker */ switch(lon) { case 0x04: ReadDht(); break; case 0x00: case 0x01: case 0x03: ReadSof(lon); break; case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: WHEREAMI(); printf("Arithmetic coding not supported.\n"); length = bgetw(); for(i=2;i 7) { switch(lon) { case 0x08: /* Start of Image */ EndofImage=0; /* If End of Image occurs */ CImage->ImageSequence++; /* reset, and increment sequence */ break; case 0x09: /* End of Image */ EndofImage=1; break; case 0x0a: ResyncCount=0; /* SOS clears the resync count */ ReadSos(); break; case 0x0b: ReadDqt(); break; case 0x0c: ReadDnl(); break; case 0x0d: ReadDri(); break; default: WHEREAMI(); printf("Hierarchical markers found.\n"); length = bgetw(); for(i=2;i= 0) { if ((ValueRead & MARKER_RSC_MASK)!=MARKER_RSC) /* Strange marker found */ { if (ValueRead != MARKER_DNL) /* DNL only other possibility */ { /* actually excluded, never reached */ WHEREAMI(); /* 11/19/91 ACH */ printf("Non-Resync marker found for resync.\n"); printf("Trying again.\n"); } } else { ValueRead = ValueRead & 0x07; /* If so, then check resync count */ if (ValueRead != ResyncCount) { WHEREAMI(); printf("Bad resync counter. No search done.\n"); } ResyncCount = (ResyncCount+1)&0x07; /* Flush spurious markers. */ while((ValueRead = ScreenMarker()) >= 0); InResync=0; return(0); } } WHEREAMI(); printf("Anticipated resync not found.\n"); Resync(); InResync=0; return(-1); } /*BFUNC ScreenAllMarker() looks for all the markers on the stream. It returns a 0 if a marker has been found, -1 if no markers exist. EFUNC*/ int ScreenAllMarker() { BEGIN("ScreenAllMarker"); if (ScreenMarker()<0) { return(-1); } while(ScreenMarker()>=0); /* Flush out all markers */ return(0); } /*BFUNC DoAllMarker() is the same as ScreenAllMarker except we assume that the prefix markerbyte (0xff) has been read and the second byte of the prefix is in the marker\_byte variable. It returns a -1 if there is an error in reading the marker. EFUNC*/ int DoAllMarker() { BEGIN("DoAllMarker"); if (DoMarker()<0) { return(-1); } while(ScreenMarker()>=0); /* Flush out all markers */ return(0); } /*END*/ pvrg-jpeg-1.2.1/chendct.c0000644000175000017500000002052005725223003014527 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ /* ************************************************************ chendct.c A simple DCT algorithm that seems to have fairly nice arithmetic properties. W. H. Chen, C. H. Smith and S. C. Fralick "A fast computational algorithm for the discrete cosine transform," IEEE Trans. Commun., vol. COM-25, pp. 1004-1009, Sept 1977. ************************************************************ */ /*LABEL chendct.c */ /*PUBLIC*/ extern void ChenDct(); extern void ChenIDct(); /*PRIVATE*/ /* Standard Macros */ #define NO_MULTIPLY #ifdef NO_MULTIPLY #define LS(r,s) ((r) << (s)) #define RS(r,s) ((r) >> (s)) /* Caution with rounding... */ #else #define LS(r,s) ((r) * (1 << (s))) #define RS(r,s) ((r) / (1 << (s))) /* Correct rounding */ #endif #define MSCALE(expr) RS((expr),9) /* Cos constants */ #define c1d4 362L #define c1d8 473L #define c3d8 196L #define c1d16 502L #define c3d16 426L #define c5d16 284L #define c7d16 100L /* VECTOR_DEFINITION makes the temporary variables vectors. Useful for machines with small register spaces. */ #ifdef VECTOR_DEFINITION #define a0 a[0] #define a1 a[1] #define a2 a[2] #define a3 a[3] #define b0 b[0] #define b1 b[1] #define b2 b[2] #define b3 b[3] #define c0 c[0] #define c1 c[1] #define c2 c[2] #define c3 c[3] #endif /*START*/ /*BFUNC ChenDCT() implements the Chen forward dct. Note that there are two input vectors that represent x=input, and y=output, and must be defined (and storage allocated) before this routine is called. EFUNC*/ void ChenDct(x,y) int *x; int *y; { register int i; register int *aptr,*bptr; #ifdef VECTOR_DEFINITION register int a[4]; register int b[4]; register int c[4]; #else register int a0,a1,a2,a3; register int b0,b1,b2,b3; register int c0,c1,c2,c3; #endif /* Loop over columns */ for(i=0;i<8;i++) { aptr = x+i; bptr = aptr+56; a0 = LS((*aptr+*bptr),2); c3 = LS((*aptr-*bptr),2); aptr += 8; bptr -= 8; a1 = LS((*aptr+*bptr),2); c2 = LS((*aptr-*bptr),2); aptr += 8; bptr -= 8; a2 = LS((*aptr+*bptr),2); c1 = LS((*aptr-*bptr),2); aptr += 8; bptr -= 8; a3 = LS((*aptr+*bptr),2); c0 = LS((*aptr-*bptr),2); b0 = a0+a3; b1 = a1+a2; b2 = a1-a2; b3 = a0-a3; aptr = y+i; *aptr = MSCALE(c1d4*(b0+b1)); aptr[32] = MSCALE(c1d4*(b0-b1)); aptr[16] = MSCALE((c3d8*b2)+(c1d8*b3)); aptr[48] = MSCALE((c3d8*b3)-(c1d8*b2)); b0 = MSCALE(c1d4*(c2-c1)); b1 = MSCALE(c1d4*(c2+c1)); a0 = c0+b0; a1 = c0-b0; a2 = c3-b1; a3 = c3+b1; aptr[8] = MSCALE((c7d16*a0)+(c1d16*a3)); aptr[24] = MSCALE((c3d16*a2)-(c5d16*a1)); aptr[40] = MSCALE((c3d16*a1)+(c5d16*a2)); aptr[56] = MSCALE((c7d16*a3)-(c1d16*a0)); } for(i=0;i<8;i++) { /* Loop over rows */ aptr = y+LS(i,3); bptr = aptr+7; c3 = RS((*(aptr)-*(bptr)),1); a0 = RS((*(aptr++)+*(bptr--)),1); c2 = RS((*(aptr)-*(bptr)),1); a1 = RS((*(aptr++)+*(bptr--)),1); c1 = RS((*(aptr)-*(bptr)),1); a2 = RS((*(aptr++)+*(bptr--)),1); c0 = RS((*(aptr)-*(bptr)),1); a3 = RS((*(aptr)+*(bptr)),1); b0 = a0+a3; b1 = a1+a2; b2 = a1-a2; b3 = a0-a3; aptr = y+LS(i,3); *aptr = MSCALE(c1d4*(b0+b1)); aptr[4] = MSCALE(c1d4*(b0-b1)); aptr[2] = MSCALE((c3d8*b2)+(c1d8*b3)); aptr[6] = MSCALE((c3d8*b3)-(c1d8*b2)); b0 = MSCALE(c1d4*(c2-c1)); b1 = MSCALE(c1d4*(c2+c1)); a0 = c0+b0; a1 = c0-b0; a2 = c3-b1; a3 = c3+b1; aptr[1] = MSCALE((c7d16*a0)+(c1d16*a3)); aptr[3] = MSCALE((c3d16*a2)-(c5d16*a1)); aptr[5] = MSCALE((c3d16*a1)+(c5d16*a2)); aptr[7] = MSCALE((c7d16*a3)-(c1d16*a0)); } /* We have an additional factor of 8 in the Chen algorithm. */ for(i=0,aptr=y;i<64;i++,aptr++) *aptr = (((*aptr<0) ? (*aptr-4) : (*aptr+4))/8); } /*BFUNC ChenIDCT() implements the Chen inverse dct. Note that there are two input vectors that represent x=input, and y=output, and must be defined (and storage allocated) before this routine is called. EFUNC*/ void ChenIDct(x,y) int *x; int *y; { register int i; register int *aptr; #ifdef VECTOR_DEFINITION register int a[4]; register int b[4]; register int c[4]; #else register int a0,a1,a2,a3; register int b0,b1,b2,b3; register int c0,c1,c2,c3; #endif /* Loop over columns */ for(i=0;i<8;i++) { aptr = x+i; b0 = LS(*aptr,2); aptr += 8; a0 = LS(*aptr,2); aptr += 8; b2 = LS(*aptr,2); aptr += 8; a1 = LS(*aptr,2); aptr += 8; b1 = LS(*aptr,2); aptr += 8; a2 = LS(*aptr,2); aptr += 8; b3 = LS(*aptr,2); aptr += 8; a3 = LS(*aptr,2); /* Split into even mode b0 = x0 b1 = x4 b2 = x2 b3 = x6. And the odd terms a0 = x1 a1 = x3 a2 = x5 a3 = x7. */ c0 = MSCALE((c7d16*a0)-(c1d16*a3)); c1 = MSCALE((c3d16*a2)-(c5d16*a1)); c2 = MSCALE((c3d16*a1)+(c5d16*a2)); c3 = MSCALE((c1d16*a0)+(c7d16*a3)); /* First Butterfly on even terms.*/ a0 = MSCALE(c1d4*(b0+b1)); a1 = MSCALE(c1d4*(b0-b1)); a2 = MSCALE((c3d8*b2)-(c1d8*b3)); a3 = MSCALE((c1d8*b2)+(c3d8*b3)); b0 = a0+a3; b1 = a1+a2; b2 = a1-a2; b3 = a0-a3; /* Second Butterfly */ a0 = c0+c1; a1 = c0-c1; a2 = c3-c2; a3 = c3+c2; c0 = a0; c1 = MSCALE(c1d4*(a2-a1)); c2 = MSCALE(c1d4*(a2+a1)); c3 = a3; aptr = y+i; *aptr = b0+c3; aptr += 8; *aptr = b1+c2; aptr += 8; *aptr = b2+c1; aptr += 8; *aptr = b3+c0; aptr += 8; *aptr = b3-c0; aptr += 8; *aptr = b2-c1; aptr += 8; *aptr = b1-c2; aptr += 8; *aptr = b0-c3; } /* Loop over rows */ for(i=0;i<8;i++) { aptr = y+LS(i,3); b0 = *(aptr++); a0 = *(aptr++); b2 = *(aptr++); a1 = *(aptr++); b1 = *(aptr++); a2 = *(aptr++); b3 = *(aptr++); a3 = *(aptr); /* Split into even mode b0 = x0 b1 = x4 b2 = x2 b3 = x6. And the odd terms a0 = x1 a1 = x3 a2 = x5 a3 = x7. */ c0 = MSCALE((c7d16*a0)-(c1d16*a3)); c1 = MSCALE((c3d16*a2)-(c5d16*a1)); c2 = MSCALE((c3d16*a1)+(c5d16*a2)); c3 = MSCALE((c1d16*a0)+(c7d16*a3)); /* First Butterfly on even terms.*/ a0 = MSCALE(c1d4*(b0+b1)); a1 = MSCALE(c1d4*(b0-b1)); a2 = MSCALE((c3d8*b2)-(c1d8*b3)); a3 = MSCALE((c1d8*b2)+(c3d8*b3)); /* Calculate last set of b's */ b0 = a0+a3; b1 = a1+a2; b2 = a1-a2; b3 = a0-a3; /* Second Butterfly */ a0 = c0+c1; a1 = c0-c1; a2 = c3-c2; a3 = c3+c2; c0 = a0; c1 = MSCALE(c1d4*(a2-a1)); c2 = MSCALE(c1d4*(a2+a1)); c3 = a3; aptr = y+LS(i,3); *(aptr++) = b0+c3; *(aptr++) = b1+c2; *(aptr++) = b2+c1; *(aptr++) = b3+c0; *(aptr++) = b3-c0; *(aptr++) = b2-c1; *(aptr++) = b1-c2; *(aptr) = b0-c3; } /* Retrieve correct accuracy. We have additional factor of 16 that must be removed. */ for(i=0,aptr=y;i<64;i++,aptr++) *aptr = (((*aptr<0) ? (*aptr-8) : (*aptr+8)) /16); } /*END*/ pvrg-jpeg-1.2.1/globals.h0000644000175000017500000001610005725222774014564 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ /* ************************************************************ globals.h This file contains the global includes and other definitions. ************************************************************ */ #ifndef GLOBAL_DONE #define GLOBAL_DONE #include #include "prototypes.h" #include "param.h" #include "system.h" /* Map stream functions to those used in stream.c (MSB) */ /* Makes for easy alterations for least-significant bit non-JPEG defns. */ #define sropen mropen #define srclose mrclose #define swopen mwopen #define swclose mwclose #define sgetb megetb #define sgetv megetv #define sputv meputv #define swtell mwtell #define srtell mrtell #define swseek mwseek #define srseek mrseek #define IMAGE struct Image_Definition #define FRAME struct Frame_Definition #define SCAN struct Scan_Definition #define MUTE 0 #define WHISPER 1 #define TALK 2 #define NOISY 3 #define SCREAM 4 /* The defined flag for encoding/decoding. */ #define J_DECODER 1 #define J_FULLHUFFMAN 2 #define J_DEFAULTHUFFMAN 4 #define J_LOSSLESS 8 /* Some flags for JpegCustomScan() */ #define CUSTOM_DO_DC 1 #define CUSTOM_DO_AC 2 /* Error flags */ #define ERROR_NONE 0 #define ERROR_BOUNDS 1 /*Input Values out of bounds */ #define ERROR_HUFFMAN_READ 2 /*Huffman Decoder finds bad code */ #define ERROR_HUFFMAN_ENCODE 3 /*Undefined value in encoder */ #define ERROR_MARKER 4 /*Error Found in Marker */ #define ERROR_INIT_FILE 5 /*Cannot initialize files */ #define ERROR_UNRECOVERABLE 6 /*No recovery mode specified */ #define ERROR_PREMATURE_EOF 7 /*End of file unexpected */ #define ERROR_MARKER_STRUCTURE 8 /*Bad Marker Structure */ #define ERROR_WRITE 9 /*Cannot write output */ #define ERROR_READ 10 /*Cannot write input */ #define ERROR_PARAMETER 11 /*System Parameter Error */ #define ERROR_MEMORY 12 /*Memory exceeded */ typedef int iFunc(); typedef void vFunc(); /* A flag obtaining macro */ #define GetFlag(value,flag) (((value) & (flag)) ? 1:0) /* MAX and MIN macros */ #define MAX(x,y) ((x > y) ? x:y) #define MIN(x,y) ((x > y) ? y:x) /* BEGIN is used to start most routines. It sets up the Routine Name */ /* which is used in the WHEREAMI() macro */ #define BEGIN(name) static char RoutineName[]= name /* WHEREAMI prints out current location in code. */ #define WHEREAMI() printf("F>%s:R>%s:L>%d: ",\ __FILE__,RoutineName,__LINE__) /* InBounds is used to test whether a value is in or out of bounds. */ #define InBounds(var,lo,hi,str)\ {if (((var) < (lo)) || ((var) > (hi)))\ {WHEREAMI(); printf("%s in %d\n",(str),(var));ErrorValue=ERROR_BOUNDS;}} /* MakeStructure makes the named structure */ #define MakeStructure(named_st) ((named_st *) malloc(sizeof(named_st))) IMAGE { char *StreamFileName; /* Name of compressed stream file */ int JpegMode; /* Mode of JPEG encoder */ int Jfif; /* If set, automatically drop JFIF marker */ int ImageSequence; /* Index in image sequence */ int NumberQuantizationMatrices; /* Number of quantization matrices */ int *QuantizationMatrices[MAXIMUM_DEVICES]; /* Pointers to q-matrices */ int NumberACTables; /* Number of AC Huffman tables */ DHUFF *ACDhuff[MAXIMUM_DEVICES]; /* Decoder huffman tables */ EHUFF *ACEhuff[MAXIMUM_DEVICES]; /* Encoder huffman tables */ XHUFF *ACXhuff[MAXIMUM_DEVICES]; /* Transmittable huffman tables */ int NumberDCTables; /* Number of DC Huffman tables */ DHUFF *DCDhuff[MAXIMUM_DEVICES]; /* Decoder huffman tables */ EHUFF *DCEhuff[MAXIMUM_DEVICES]; /* Encoder huffman tables */ XHUFF *DCXhuff[MAXIMUM_DEVICES]; /* Transmittable huffman tables */ }; FRAME { int Type; /* SOF(X) where X is type (4 bits) */ char *ComponentFileName[MAXIMUM_COMPONENTS]; /* image component file names */ int InsertDnl; /* DNL flag (-2 = AUTO) (-1 = ENABLE) (>0 ) */ int Q; /* Q Factor (0 disables) */ int DataPrecision; /* Data Precision (not used) */ int GlobalHeight; /* Dimensions of overall image */ int GlobalWidth; int ResyncInterval; /* Resync interval (0 disables) */ int GlobalNumberComponents; /* Global number of components */ int cn[MAXIMUM_COMPONENTS]; /* Translation index used */ int hf[MAXIMUM_COMPONENTS]; /* Horizontal frequency */ int vf[MAXIMUM_COMPONENTS]; /* Vertical frequency */ int tq[MAXIMUM_COMPONENTS]; /* Quantization table used by */ int Width[MAXIMUM_COMPONENTS]; /* Dimensions of component files */ int Height[MAXIMUM_COMPONENTS]; int BufferSize; /* Buffer sizes used */ int Maxv, Maxh; /* Max Sampling Freq */ int MDUWide, MDUHigh; /* Number MDU wide */ IMAGE *Image; }; SCAN { int NumberComponents; /* Number of components in scan */ int SSS; /* Spectral Selection Start (not used) */ int SSE; /* Spectral Selection End (not used) */ int SAH; /* Spectral approximation (not used) */ int SAL; /* Spectral approximation (not used) */ int *LastDC[MAXIMUM_SOURCES]; /* LastDC DPCM predictor */ int *ACFrequency[MAXIMUM_SOURCES]; /* Frequency charts for custom huffman */ int *DCFrequency[MAXIMUM_SOURCES]; /* table building */ int LosslessBuffer[MAXIMUM_SOURCES][LOSSLESSBUFFERSIZE]; int MDUWide, MDUHigh; /* a integer buffer for lossless coding */ IOBUF *Iob[MAXIMUM_SOURCES]; /* IOB per scan index */ int ci[MAXIMUM_SOURCES]; /* Index */ int ta[MAXIMUM_SOURCES]; /* AC Tables for that scan index */ int td[MAXIMUM_SOURCES]; /* DC Tables for scan index */ int NumberACTablesSend; /* Number of tables to send */ int NumberDCTablesSend; int NumberQTablesSend; int sa[MAXIMUM_SOURCES]; /* AC table indices to send */ int sd[MAXIMUM_SOURCES]; /* DC table indices to send */ int sq[MAXIMUM_SOURCES]; /* Quantization table indices to send */ }; #endif pvrg-jpeg-1.2.1/param.h0000644000175000017500000000755205725222776014256 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ /* ************************************************************ param.h The basic system parameters are kept here. ************************************************************ */ #ifndef PARAM_DONE #define PARAM_DONE /* This is the general definition for the size and width of the JPEG blocks. Do not change. */ #define BLOCKSIZE 64 #define BLOCKWIDTH 8 #define BLOCKHEIGHT 8 /* Definitions for JPEG and internal compatibility. */ #define MAXIMUM_HORIZONTAL_FREQUENCY 15 #define MAXIMUM_VERTICAL_FREQUENCY 15 #define MAXIMUM_JPEG_HORIZONTAL_FREQUENCY 4 #define MAXIMUM_JPEG_VERTICAL_FREQUENCY 4 #define MINIMUM_BUFFERSIZE 16 #define MAXIMUM_UNSIGNED16 65535 #define MAXIMUM_RESYNC_INTERVAL 65535 #define MAXIMUM_BUFFERSIZE 65535 #define MAXIMUM_IMAGE_HEIGHT 65535 #define MAXIMUM_IMAGE_WIDTH 65535 /* Devices: Number of active devices operating at one time. Quantization tables, huffman tables, etc. are all devices. */ #define MAXIMUM_DEVICES 16 /* Sources: Number of active sources in stream at one time. A source is one interleave possibility. */ #define MAXIMUM_SOURCES 16 /* Components: Number of components that can be active per frame. A component consists of one complete plane of the image. */ #define MAXIMUM_COMPONENTS 256 /* Q value as defined by archaic and now defunct F-Factor: Used to rescale quantization matrices. */ #define Q_PRECISION 50 /* Scan component threshold is the maximum number of components put in per scan */ #define SCAN_COMPONENT_THRESHOLD 4 /* Mask to be used for creating files. */ #define UMASK 0666 /* Octal */ /* Buffersize is used as the default I/O buffer. A smaller size ensures less storage space. A larger size requires more storage space. 256 seems like a good number for smaller machines, but for machines with greater than 0.5 MB of memory, 1024 would be better because it reduces on the number of seeks necessary. Helpful for macro-sized words such as 16 bit or 24 bit to have a proper multiple of such word. */ #define BUFFERSIZE 256 /* Lossless Buffersize is a variable that is kept for the lossless streams. It can be any positive number, though a larger number will speed up the processing of information. A large number also will cause (MAXIMUM_SOURCES)*(LOSSLESSBUFFERSIZE)*sizeof(int) storage consumption. To ensure proper operation, this should be equivalent to the BUFFERSIZE variable * dimensions of the scan frequencies so that two fetches are not required for filling the lossless buffer. (It would make having the upper buffer useless). The minimum number is (MAX_HF+1)*(MAX_VF+1) */ #define LOSSLESSBUFFERSIZE 289 /* Number of streams is the number of active read/write streams possible. For all jpeg operations, this value is 1.*/ #define NUMBER_OF_STREAMS 1 #define ISO_DCT #define LEE_DCT #endif pvrg-jpeg-1.2.1/test.3stream0000644000175000017500000000116105725223007015236 0ustar naolivnaoliv/* This program sends a 128x128 file blkint.jpg.1, 64x128 file blkint.jpg.2, 64x128 file blkint.jpg.3, to the compressed file output.jpg. The define-number of lines marker is also enabled. */ STREAMNAME "output.jpg" COMPONENT [0 ["blkint.jpg.1" 2 1 0]] COMPONENT [1 ["blkint.jpg.2" 1 1 0]] COMPONENT [2 ["blkint.jpg.3" 1 1 0]] SCAN [0 [0 0] 1 [0 0]2 [0 0]] IMAGEWIDTH 128 IMAGEHEIGHT 128 SCANDNL AUTO QUANTIZATION 0 LUMINANCEDEFAULT QSEND 0 OPENSTREAM WRITESOI WRITEFRAME OPENSCAN ACSPEC 0 LUMINANCEDEFAULT DCSPEC 0 LUMINANCEDEFAULT ACSEND 0 DCSEND 0 WRITEHUFFMAN WRITEQUANTIZATION WRITESCAN CLOSESCAN WRITEEOI CLOSESTREAM pvrg-jpeg-1.2.1/makefile0000644000175000017500000000314705725223006014464 0ustar naolivnaoliv########################################################### # The makefile for the JPEG program. # There should be no changes for most UNIX compilers. ########################################################### # # For sysv substitute the following terms: # SYSV allows for SYSV system IO calls. NOTRUNCATE allows # for UNIX emulators without the ftruncate() call. # #DEFINES = -DSYSV -DNOTRUNCATE # DEFINES = JFLAGS = -O DEFS = system.h globals.h prototypes.h param.h BASELINE = jpeg.o codec.o huffman.o io.o chendct.o leedct.o lexer.o marker.o stream.o transform.o .c.o: cc $(JFLAGS) $(DEFINES) -c $*.c .c.ln: lint -c $*.c all: jpeg clean: rm *.o jpeg jpeg: $(BASELINE) cc $(DEFINES) $(JFLAGS) $(BASELINE) -lm -o jpeg jpeg.o: jpeg.c $(DEFS) tables.h codec.o: codec.c $(DEFS) huffman.o: huffman.c $(DEFS) stream.h io.o: io.c $(DEFS) chendct.o: chendct.c $(DEFS) leedct.o: leedct.c $(DEFS) lexer.o: lexer.c $(DEFS) tables.h stream.h marker.o: marker.c $(DEFS) marker.h stream.h stream.o: stream.c $(DEFS) marker.h stream.h transform.o: transform.c dct.h $(DEFS) lcheck: jpeg.ln codec.ln huffman.ln io.ln chendct.ln leedct.ln lexer.ln marker.ln stream.ln transform.ln lint jpeg.ln codec.ln huffman.ln io.ln chendct.ln leedct.ln lexer.ln marker.ln stream.ln transform.ln # # Should you wish to modify the interpreter # modify this portion here. # # Make sure that you move the first comment from the start to # within the braces %{ /* */ %} in lexer.l, # otherwise it will give you a error (definitions too long). # # Caution: Sometimes -ll is required. # # #lexer.c: lexer.l # lex lexer.l # mv lex.yy.c lexer.c # pvrg-jpeg-1.2.1/blkint.jpg0000644000175000017500000000552305725223007014752 0ustar naolivnaoliv   (1#%(:3=<9387@H\N@DWE78PmQW_bghg>Mqypdx\egc//cB8BBccccccccccccccccccccccccccccccccccccccccccccccccc! }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?gp=jܺ-;w;; 8](.h`\wD P4=ƶky P 8UIzla£z fXM-ӊlQ 6NJ[4e?-&U{  !<e%ful-YX9Q/t5E'e2aJ mjчQ/N vgi p?Jt1?` HӞ"Ot`VhՃ*48RgQ9YY~jleSsH2r9SjRG Vi{)jƋ fIdU^勮Yq=vn2p=佊_zfmچa~hͥQJI$[ *L2IfcYOJ{U=`2qQNB|zrV`.#u#`~۷ڐ2YΠTT{ nD31*G",މ[Ѷ@S=˧j%xgҭ:"G4S* wiŐa]3*\v9S;GqW-ȉ, 2pim*^y~qd#;{&r3Re2[zU4Ie߁53՚vBl07Rs$@Fi'23Pp)T9<R(%ĦUv=FPLL\qY#xkY} lppjV$C)#/}caL}Xe-mI(Ow?}k&{Tyj>Ѳ^U@YD4C{q) g;[)NN7fv!\0Ϛ"GVjn݆ҴD#O(> ᳊͔AoR+ pϥG %Gu?ֱ[+3}jqh$9SY=ΘBvpt"j5Drݹ$c9֝-hNΞn:̹BU=:%=;54uC0}kYlDw2p8aXAY=eM@'2Q[8ȏTuskxbɕ1 r{:{Kdz PynZ@]n>B1jBڒ2 V^r=,e(r%*S*^[jIˍڴ-H5j*'c1W #;Xe;gdonªZJ>!lXR7|lՕ+ԶbJVCqI5ܠy n0Ê%_sY@wW"|' +Vڒj۽tu`E[ӽ2st "3o v;aT-ءpsj.[:TrFx:7 xFڹۙkb+v-&ZJLq-))K( P\"dvg54hK05s=]}F@zfUcnE$V< ǴV$'!ðBƒS=4dgw9LO,H3 -i3`1R*; T5%%UM fGa֮qWA6URFrL q|"Q^ ď=5f;/D e[4C.mRw bVSjQcPb&$r142j5FEURĞK=1R7Jn @2?)$##՛64S+g5iB81Hsr=I5Z7wsьd3?޿AQr(jCԕcO>*rp4Ck1LG=MZW !{N).ŕLcT&Ḟ$M#qQ%tT5wUIG`δPz).:BDJDq#J0 zUҖH7s*3ڶL%+u$R1U5J[]x;pvrg-jpeg-1.2.1/lexer.c0000644000175000017500000012245305725223004014247 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ # include "stdio.h" # define U(x) ((x)&0377) # define NLSTATE yyprevious=YYNEWLINE # define BEGIN yybgin = yysvec + 1 + # define INITIAL 0 # define YYLERR yysvec # define YYSTATE (yyestate-yysvec-1) # define YYOPTIM 1 # define YYLMAX 200 # define output(c) putc(c,yyout) # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) # define unput(c) {yytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytchar;} # define yymore() (yymorfg=1) # define ECHO fprintf(yyout, "%s",yytext) # define REJECT { nstr = yyreject(); goto yyfussy;} int yyleng; extern char yytext[]; int yymorfg; extern char *yysptr, yysbuf[]; int yytchar; FILE *yyin ={stdin}, *yyout ={stdout}; extern int yylineno; struct yysvf { struct yywork *yystoff; struct yysvf *yyother; int *yystops;}; struct yysvf *yyestate; extern struct yysvf yysvec[], *yybgin; /*LABEL lexer.c */ /* Redefine the yywrap so that we don't have to worry about lex library */ # define yywrap() (1) static char *ReservedWords[] = { /* Token names */ "COMPONENT", "SCAN", "QUANTIZATION", "DCSPEC", "ACCUSTOM", "DCCUSTOM", "PRINTSCAN", "PRINTFRAME", "PRINTIMAGE", "OPENSCAN", "ACSPEC", "WRITESCAN", "WRITEFRAME", "WRITESOI", "WRITEQUANTIZATION", "WRITERESYNC", "WRITEHUFFMAN", "FREQUENCY", "ACSEND", "DCSEND", "QSEND", "STREAMNAME", "IMAGEHEIGHT", "IMAGEWIDTH", "RESYNC", "BUFFER", "OPENSTREAM", "CLOSESTREAM", "FRAMEHEIGHT", "FRAMEWIDTH", "CLOSESCAN", "WRITEEOI", "ECHO", "WRITESPECIAL", "WRITEDIRECT", "LUMINANCEDEFAULT", "CHROMINANCEDEFAULT", "ENABLE", "SCANDNL", "WRITEDNL", "AUTO", "EMPTY", ""}; #define R_COMPONENT 1 /* Token values mapped to token names */ #define R_SCAN 2 #define R_QUANTIZATION 3 #define R_DCSPEC 4 #define R_ACCUSTOM 5 #define R_DCCUSTOM 6 #define R_PRINTSCAN 7 #define R_PRINTFRAME 8 #define R_PRINTIMAGE 9 #define R_OPENSCAN 10 #define R_ACSPEC 11 #define R_WRITESCAN 12 #define R_WRITEFRAME 13 #define R_WRITESOI 14 #define R_WRITEQUANTIZATION 15 #define R_WRITERESYNC 16 #define R_WRITEHUFFMAN 17 #define R_FREQUENCY 18 #define R_ACSEND 19 #define R_DCSEND 20 #define R_QSEND 21 #define R_STREAMNAME 22 #define R_IMAGEHEIGHT 23 #define R_IMAGEWIDTH 24 #define R_RESYNC 25 #define R_BUFFER 26 #define R_OPENSTREAM 27 #define R_CLOSESTREAM 28 #define R_FRAMEHEIGHT 29 #define R_FRAMEWIDTH 30 #define R_CLOSESCAN 31 #define R_WRITEEOI 32 #define R_ECHO 33 #define R_WRITESPECIAL 34 #define R_WRITEDIRECT 35 #define R_LUMINANCEDEFAULT 36 #define R_CHROMINANCEDEFAULT 37 #define R_ENABLE 38 #define R_SCANDNL 39 #define R_WRITEDNL 40 #define R_AUTO 41 #define R_EMPTY 42 #define R_INTEGER 1000 /* Special TYPES for tokens */ #define R_LBRACKET 1001 #define R_RBRACKET 1002 #define R_ID 1003 #define R_STRING 1004 int CommentDepth = 0; /* depth of comment nesting */ int yyint=0; /* Return value for integers */ int LexDebug=0; /* Status of lex debugging */ #define PRIME 211 #define EOS '\0' #define MakeStructure(S) (S *) malloc(sizeof(S)) #define InsertLink(link,list){\ if(!list){list=link;}else{link->next=list;list=link;}} #define LINK struct link_def struct id { /* Default id structure */ char *name; /* Key */ int tokentype; /* Token type */ int count; /* Count of # references */ }; LINK { /* A link for the hash buckets */ struct id *lid; /* Current id */ LINK *next; /* Pointer to next id */ }; /*PUBLIC*/ extern void initparser(); extern void parser(); static int hashpjw(); static LINK * MakeLink(); static struct id * enter(); static int getint(); static char * getstr(); /*PRIVATE*/ /*NOPROTO*/ # define NORMAL 2 # define COMMENT 4 # define YYNEWLINE 10 yylex(){ int nstr; extern int yyprevious; while((nstr = yylook()) >= 0) yyfussy: switch(nstr){ case 0: if(yywrap()) return(0); break; case 1: {} break; case 2: {struct id *temp; temp = enter(0,yytext,yyleng); if (LexDebug) { printf("%s : %s (%d)\n", yytext, ((temp->tokentype) ? "RESERVED" : "IDENTIFIER"), temp->count); } if (temp->tokentype) { return(temp->tokentype); } else { return(R_ID); } } break; case 3: {if (LexDebug) { printf("%s : %s\n", yytext, "REAL"); } } break; case 4: {if (LexDebug) { printf("%s : %s\n", yytext, "INTEGER"); } yyint = atoi(yytext); return(R_INTEGER);} break; case 5: {if (LexDebug) { printf("%s : %s\n", yytext, "(HEX)INTEGER"); } yyint = strtol(yytext+2,NULL,16); return(R_INTEGER);} break; case 6: {if (LexDebug) { printf("%s : %s\n", yytext, "(HEX)INTEGER"); } yyint = strtol(yytext,NULL,16); return(R_INTEGER);} break; case 7: {if (LexDebug) { printf("%s : %s\n", yytext, "(OCT)INTEGER"); } yyint = strtol(yytext+2,NULL,8); return(R_INTEGER);} break; case 8: {if (LexDebug) { printf("%s : %s\n", yytext, "(OCT)INTEGER"); } yyint = strtol(yytext,NULL,8); return(R_INTEGER);} break; case 9: {if (LexDebug) { printf("%s : %s\n", yytext, "(CHAR)INTEGER"); } if (yyleng>4) { yyint = strtol(yytext+2,NULL,8); } else { if (*(yytext+1)=='\\') { switch(*(yytext+2)) { case '0': yyint=0; break; case 'b': yyint = 0x8; break; case 'i': yyint = 0x9; break; case 'n': yyint = 0xa; break; case 'v': yyint = 0xb; break; case 'f': yyint = 0xc; break; case 'r': yyint = 0xd; break; default: yyint=(*yytext+2); break; } } else { yyint = *(yytext+1); } } return(R_INTEGER);} break; case 10: {if (LexDebug) { printf("%s : %s\n", yytext, "LBRACKET"); } return(R_LBRACKET);} break; case 11: {if (LexDebug) { printf("%s : %s\n", yytext, "RBRACKET"); } return(R_RBRACKET);} break; case 12: {if (LexDebug) { printf("%s : %s\n", yytext, "OPERATOR"); } } break; case 13: {if (LexDebug) { printf("%s : %s\n", yytext, "STRING"); } return(R_STRING);} break; case 14: {CommentDepth++; BEGIN COMMENT;} break; case 15: {CommentDepth--;if(!CommentDepth) BEGIN NORMAL;} break; case 16: { /* None of the above rules applicable, so it's a bad symbol. */ printf("Bad input char '%c' on line %d\n", yytext[0], yylineno); } break; case 17: {} break; case -1: break; default: fprintf(yyout,"bad switch yylook %d",nstr); } return(0); } /* end of yylex */ /*PROTO*/ LINK *HashTable[PRIME]; /* My little hash table */ /*START*/ /*BFUNC initparser() is used to place the Reserved Words into the hash table. It must be called before the parser command is called. EFUNC*/ void initparser() { char i,**sptr; BEGIN NORMAL; for(i=1,sptr=ReservedWords;**sptr!='\0';i++,sptr++) { /* Add Reserved Words */ enter(i,*sptr,strlen(*sptr)); /* Put reserved words in */ } /* hash table */ } #undef BEGIN #undef MakeStructure #include "globals.h" #include "stream.h" #include "tables.h" extern FRAME *CFrame; extern IMAGE *CImage; extern SCAN *CScan; extern int ErrorValue; /*BFUNC hashpjw() returns a hash value for a string input. EFUNC*/ static int hashpjw(s) char *s; { BEGIN("hashpjw"); char *p; unsigned int h=0,g; for(p=s;*p!=EOS;p++) /* Taken from Aho Sethi Ullman Compilers book. */ { h = (h << 4) + *p; if (g = h&0xf0000000) { h = h ^(g >> 24); h = h ^ g; } } return(h % PRIME); } /*BFUNC MakeLink() is used to construct a link object. The link is used for the hash table construct. EFUNC*/ static LINK *MakeLink(tokentype,str,len) int tokentype; char *str; int len; { BEGIN("MakeLink"); LINK *temp; if (!(temp = MakeStructure(LINK))) /* Make link */ { WHEREAMI(); printf("Cannot make a LINK.\n"); exit(ERROR_MEMORY); } if (!(temp->lid = MakeStructure(struct id))) /* Make id */ { printf("Cannot make an id.\n"); exit(ERROR_MEMORY); } temp->next = NULL; /* Set fields */ if (!(temp->lid->name =(char *)calloc(len+1,sizeof(char)))) { printf("Cannot make a string space for the link.\n"); exit(ERROR_MEMORY); } strcpy(temp->lid->name,str); /* Copy key */ temp->lid->tokentype = tokentype; temp->lid->count = 1; return(temp); } /*BFUNC enter() is used to enter a Reserved Word or ID into the hash table. EFUNC*/ static struct id *enter(tokentype,str,len) int tokentype; char *str; int len; { BEGIN("enter"); int hashnum; LINK *temp,*current; char *ptr; for(ptr=str;*ptr!='\0';ptr++) /* All capitals is fine */ { if ((*ptr>='a') && (*ptr<='z')) { *ptr = *ptr - ('a'-'A'); } } hashnum = hashpjw(str); /* Check if in hash table */ for(temp=NULL,current=HashTable[hashnum]; current!= NULL; current=current->next) { if (strcmp(str,current->lid->name) == 0) { temp=current; break; } } if (temp) /* Yes, found ID then return */ { temp->lid->count++; return(temp->lid); } else /* Else make our own ID and return that*/ { temp = MakeLink(tokentype,str,len); InsertLink(temp,HashTable[hashnum]); return(temp->lid); } } /*BFUNC getint() takes an integer from the input. EFUNC*/ static int getint() { BEGIN("getint"); int type; if ((type=yylex())!=R_INTEGER) { printf("Bad input, not integer, '%s' on line %d\n", yytext, yylineno); return(0); } return(yyint); } /*BFUNC getstr() gets a string from the input. It copies the string to temporary storage before it returns the pointer. EFUNC*/ static char *getstr() { BEGIN("getstr"); char *tmp,*ptr,*bptr; int i,accum,flag; if (yylex() != R_STRING) /* Check if string */ { printf("String expected.\n"); if (!(tmp=(char *) malloc(sizeof(char)))) { WHEREAMI(); printf("Cannot allocate for null string.\n"); exit(ERROR_MEMORY); } *tmp='\0'; return(tmp); } if (!(tmp=(char *)calloc(strlen(yytext)+1,sizeof(char)))) /* Make space */ { WHEREAMI(); printf("Cannot allocate %d string space.\n",yyleng); exit(ERROR_MEMORY); } for(bptr=yytext+1,ptr=tmp;*bptr!='"';bptr++,ptr++) /* Copy to string */ { if (*bptr=='\\') { bptr++; for(flag=0,accum=0,i=0;i<3;i++) /* Octal character lookahead */ { if ((*bptr>='0')&&(*bptr<='7')) { accum = (accum<<3)+(*bptr-'0'); bptr++; flag=1; } else { break; } } if (flag) { bptr--; *ptr=accum; } else /* Do conversions, if necessary */ { switch(*(bptr)) { case '0': *ptr = 0; break; case 'b': *ptr = 0x8; break; case 'i': *ptr = 0x9; break; case 'n': *ptr = 0xa; break; case 'v': *ptr = 0xb; break; case 'f': *ptr = 0xc; break; case 'r': *ptr = 0xd; break; default: *ptr=(*bptr); } } } else { *ptr = (*bptr); } } *ptr='\0'; return(tmp); } /*BFUNC parser() handles all of the parsing required for the Command Interpreter. It is basically a while statement with a very large case statement for every input. The Command Interpreter is essentially driven by the keywords. All unmatched values such as integers, strings, and brackets, are ignored. EFUNC*/ #define ARRAYBEGIN if (ntoken==R_LBRACKET)\ {\ arrayflag=1;\ ntoken=yylex();\ }\ if (ntoken!=R_INTEGER)\ {\ WHEREAMI();\ printf("Expected integer.\n");\ break;\ }\ while(1)\ { #define ARRAYEND if (arrayflag)\ {\ if ((ntoken=yylex())==R_RBRACKET) break;\ else if (ntoken!=R_INTEGER)\ {\ WHEREAMI();\ printf("Expected integer or right bracket.\n");\ break;\ }\ }\ else break;\ } void parser() { BEGIN("parser"); int i,dest,value,token,ntoken,arrayflag; int accum; int Start,End; int *ptr,*ptr2; while(token=yylex()) /* The code handling is simple enough. */ { /* just read the code and documentation */ ErrorValue=0; /* book... */ arrayflag=0; switch(token) { case R_ECHO: printf("%s\n",getstr()); break; case R_PRINTIMAGE: PrintImage(); break; case R_PRINTFRAME: PrintFrame(); break; case R_PRINTSCAN: PrintScan(); break; case R_COMPONENT: ntoken=yylex(); ARRAYBEGIN; dest = yyint; InBounds(dest,0,MAXIMUM_COMPONENTS-1,"Bad component reference"); if (ErrorValue) break; if (yylex()!=R_LBRACKET) { WHEREAMI(); printf("Expected left bracket.\n"); break; } CFrame->ComponentFileName[dest] = getstr(); value=getint(); InBounds(value,0,MAXIMUM_HORIZONTAL_FREQUENCY, "Bad horizontal frequency"); if (ErrorValue) break; CFrame->hf[dest]=value; value=getint(); InBounds(value,0,MAXIMUM_VERTICAL_FREQUENCY, "Bad vertical frequency"); if (ErrorValue) break; CFrame->vf[dest]=value; value=getint(); InBounds(value,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; CFrame->tq[dest]=value; CFrame->cn[CFrame->GlobalNumberComponents++]=dest;/*Know to use it*/ if (yylex()!=R_RBRACKET) { WHEREAMI(); printf("Expected right bracket.\n"); break; } ARRAYEND; break; case R_SCAN: CScan->NumberComponents=0; ntoken=yylex(); ARRAYBEGIN; if (CScan->NumberComponents>=MAXIMUM_SOURCES) { WHEREAMI(); printf("Exceeded number of sources per scan.\n"); break; } InBounds(yyint,0,MAXIMUM_COMPONENTS-1,"Bad component reference"); if (ErrorValue) break; for(i=0;iGlobalNumberComponents;i++) /* Check there */ if (CFrame->cn[i]==yyint) break; if (i==CFrame->GlobalNumberComponents) { WHEREAMI(); printf("Scan index not defined in frame yet.\n"); break; } CScan->ci[CScan->NumberComponents] = yyint; if (yylex()!=R_LBRACKET) { WHEREAMI(); printf("Expected left bracket.\n"); break; } value=getint(); InBounds(value,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; CScan->td[CScan->NumberComponents]=value; value=getint(); InBounds(value,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; CScan->ta[CScan->NumberComponents]=value; CScan->NumberComponents++; if (yylex()!=R_RBRACKET) { WHEREAMI(); printf("Expected right bracket.\n"); break; } ARRAYEND; break; case R_QUANTIZATION: ntoken=yylex(); ARRAYBEGIN; dest = yyint; InBounds(dest,0,MAXIMUM_DEVICES-1, "Bad quantization reference."); if (ErrorValue) break; ntoken=yylex(); if (ntoken==R_LUMINANCEDEFAULT) { CImage->QuantizationMatrices[dest]=LuminanceQuantization; break; } else if (ntoken==R_CHROMINANCEDEFAULT) { CImage->QuantizationMatrices[dest]=ChrominanceQuantization; break; } else if (ntoken!=R_LBRACKET) { WHEREAMI(); printf("Expected left bracket.\n"); break; } CImage->NumberQuantizationMatrices = MAX(CImage->NumberQuantizationMatrices,(dest+1)); if (!(ptr=(int *)calloc(64,sizeof(int)))) { WHEREAMI(); printf("Cannot allocate quantization matrix.\n"); exit(ERROR_MEMORY); } CImage->NumberQuantizationMatrices = MAX(CImage->NumberQuantizationMatrices,(dest+1)); CImage->QuantizationMatrices[dest]=ptr; for(i=0;i<64;i++) { ptr[i]=16; } for(i=0;i<65;i++,ptr++) /* One additional to force r-bracket */ { if ((ntoken=yylex())!=R_INTEGER) break; InBounds(yyint,1,65535,"Integer out of bounds"); if (ErrorValue) yyint=16; *ptr = yyint; } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected integer or right bracket.\n"); break; } ARRAYEND; break; case R_ACSEND: ntoken=yylex(); if (ntoken==R_EMPTY) { CScan->NumberACTablesSend = 0; break; } ARRAYBEGIN; if (CScan->NumberACTablesSend>=MAXIMUM_DEVICES) { WHEREAMI(); printf("AC Huffman queue full.\n"); break; } InBounds(yyint,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; CScan->sa[CScan->NumberACTablesSend++] = yyint; ARRAYEND; break; case R_DCSEND: ntoken=yylex(); if (ntoken==R_EMPTY) { CScan->NumberDCTablesSend = 0; break; } ARRAYBEGIN; if (CScan->NumberDCTablesSend>=MAXIMUM_DEVICES) { WHEREAMI(); printf("DC Huffman queue full.\n"); break; } InBounds(yyint,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; CScan->sd[CScan->NumberDCTablesSend++] = yyint; ARRAYEND; break; case R_QSEND: ntoken=yylex(); if (ntoken==R_EMPTY) { CScan->NumberQTablesSend = 0; break; } ARRAYBEGIN; if (CScan->NumberQTablesSend>=MAXIMUM_DEVICES) { WHEREAMI(); printf("Quantization queue full.\n"); break; } InBounds(yyint,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; CScan->sq[CScan->NumberQTablesSend++] = yyint; ARRAYEND; break; case R_STREAMNAME: CImage->StreamFileName = getstr(); break; case R_IMAGEWIDTH: value=getint(); InBounds(value,0,MAXIMUM_IMAGE_WIDTH,"Bad image width"); CFrame->GlobalWidth = value; break; case R_IMAGEHEIGHT: value=getint(); InBounds(value,0,MAXIMUM_IMAGE_HEIGHT,"Bad image height"); CFrame->GlobalHeight = value; break; case R_SCANDNL: ntoken=yylex(); switch(ntoken) { case R_AUTO: CFrame->InsertDnl= -2; break; case R_ENABLE: CFrame->InsertDnl= -1; break; case R_INTEGER: CFrame->InsertDnl = yyint; break; default: WHEREAMI(); printf("Expected integer.\n"); break; } break; case R_FRAMEWIDTH: ntoken=yylex(); ARRAYBEGIN; dest = yyint; InBounds(dest,0,MAXIMUM_COMPONENTS-1,"Bad component destination"); if (ErrorValue) break; value=getint(); InBounds(value,0,MAXIMUM_IMAGE_WIDTH,"Bad frame width"); if (ErrorValue) break; CFrame->Width[dest] = value; ARRAYEND; break; case R_FRAMEHEIGHT: ntoken=yylex(); ARRAYBEGIN; dest = yyint; InBounds(dest,0,MAXIMUM_COMPONENTS-1,"Bad component destination"); if (ErrorValue) break; value=getint(); InBounds(value,0,MAXIMUM_IMAGE_HEIGHT,"Bad frame height"); if (ErrorValue) break; CFrame->Height[dest] = value; ARRAYEND; break; case R_RESYNC: value = getint(); InBounds(value,0,MAXIMUM_RESYNC_INTERVAL,"Bad resync interval"); if (ErrorValue) break; CFrame->ResyncInterval = value; break; case R_BUFFER: value = getint(); InBounds(value,MINIMUM_BUFFERSIZE, MAXIMUM_BUFFERSIZE,"Bad buffersize"); if (ErrorValue) break; CFrame->BufferSize = value; break; case R_OPENSCAN: CheckValidity(); CheckBaseline(); ConfirmFileSize(); MakeIob(IOB_BLOCK,O_RDONLY,1); break; case R_CLOSESCAN: for(i=0;iNumberComponents;i++) /* Close all components */ { InstallIob(i); CloseIob(); } break; case R_OPENSTREAM: if (CImage->StreamFileName) { swopen(CImage->StreamFileName,0); /* Index 0 open */ } else { printf("StreamFileName: Null. Failed\n"); } break; case R_CLOSESTREAM: swclose(); break; case R_FREQUENCY: JpegFrequencyScan(); break; case R_WRITESPECIAL: ntoken=yylex(); ARRAYBEGIN; value = yyint; swbytealign(); bputc(0xFF); /* Marker */ bputc(value&0xff); Start = swtell(); bputw(0); if (yylex()!=R_LBRACKET) { WHEREAMI(); printf("Expected left bracket.\n"); End = swtell(); swseek(Start); bputw((End-Start) >> 3); swseek(End); break; } while((ntoken=yylex())==R_INTEGER) { bputc(yyint&0xff); } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected integer or right bracket.\n"); End = swtell(); swseek(Start); bputw((End-Start) >> 3); swseek(End); break; } End = swtell(); swseek(Start); bputw((End-Start) >> 3); swseek(End); ARRAYEND; break; case R_WRITEDIRECT: swbytealign(); if (yylex()!=R_LBRACKET) { WHEREAMI(); printf("Expected left bracket.\n"); break; } while((ntoken=yylex())==R_INTEGER) { bputc(yyint&0xff); } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected integer or right bracket.\n"); break; } break; case R_WRITESCAN: JpegEncodeScan(); break; case R_WRITEFRAME: MakeConsistentFrameSize(); /* Do it here when everything defined */ WriteSof(); break; case R_WRITESOI: WriteSoi(); break; case R_WRITEEOI: WriteEoi(); break; case R_WRITEQUANTIZATION: WriteDqt(); break; case R_WRITERESYNC: WriteDri(); break; case R_WRITEDNL: WriteDnl(); break; case R_WRITEHUFFMAN: WriteDht(); break; case R_ACCUSTOM: ntoken=yylex(); ARRAYBEGIN; dest = yyint; InBounds(dest,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; if (yylex()!=R_LBRACKET) { WHEREAMI(); printf("Expected left bracket.\n"); break; } MakeXhuff(); MakeEhuff(); if (!(ptr=(int *)calloc(257,sizeof(int)))) { WHEREAMI(); printf("Out of custom frequency space.\n"); exit(ERROR_MEMORY); } for(i=0;i<257;i++) { ptr[i]=0; } while((ntoken=yylex())==R_INTEGER) { InBounds(yyint,0,MAXIMUM_SOURCES-1,"Bad frequency reference"); if(ErrorValue) yyint=0; AddFrequency(ptr,CScan->ACFrequency[yyint]); } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected right bracket.\n"); break; } MakeHuffman(ptr); SetACHuffman(dest); CImage->NumberACTables = MAX(CImage->NumberACTables,(dest+1)); ARRAYEND; break; case R_DCCUSTOM: ntoken=yylex(); ARRAYBEGIN; dest = yyint; InBounds(dest,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; if (yylex()!=R_LBRACKET) { WHEREAMI(); printf("Expected left bracket.\n"); break; } MakeXhuff(); MakeEhuff(); if (!(ptr=(int *)calloc(257,sizeof(int)))) { WHEREAMI(); printf("Out of custom frequency space.\n"); exit(ERROR_MEMORY); } for(i=0;i<257;i++) { ptr[i]=0; } while((ntoken=yylex())==R_INTEGER) { InBounds(yyint,0,MAXIMUM_SOURCES-1,"Bad frequency reference"); if(ErrorValue) yyint=0; AddFrequency(ptr,CScan->DCFrequency[yyint]); } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected right bracket.\n"); break; } MakeHuffman(ptr); SetDCHuffman(dest); CImage->NumberDCTables = MAX(CImage->NumberDCTables,(dest+1)); ARRAYEND; break; case R_ACSPEC: ntoken=yylex(); ARRAYBEGIN; dest = yyint; InBounds(dest,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; MakeXhuff(); MakeEhuff(); if ((ntoken=yylex())==R_LBRACKET) { if (!(ptr=(int *)calloc(38,sizeof(int)))) /* Get bits */ { WHEREAMI(); printf("Out of custom bits space.\n"); exit(ERROR_MEMORY); } for(i=0;i<32;i++) { ptr[i]=0; } for(accum=0,i=0;i<17;i++) /* First index is bitlength of 1. */ { /* One additional to force r-bracket. */ ntoken=yylex(); if (ntoken==R_INTEGER) { accum+=yyint; ptr[i]=yyint; } else break; } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected integer or right bracket.\n"); break; } if (yylex()!=R_LBRACKET) /* Get values */ { WHEREAMI(); printf("Expected left bracket.\n"); break; } if (!(ptr2=(int *)calloc(257,sizeof(int)))) { WHEREAMI(); printf("Out of custom Huffman value space.\n"); exit(ERROR_MEMORY); } for(i=0;i<257;i++) { ptr2[i]=0; } for(i=0;i<257;i++) /* One additinal to force r-bracket */ { ntoken=yylex(); if (ntoken==R_INTEGER) { ptr2[i]=yyint; } else break; } if (i!=accum) { WHEREAMI(); printf("Number of bitlengths != number of values."); } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected integer or right bracket.\n"); break; } SpecifiedHuffman(ptr,ptr2); } else if (ntoken==R_CHROMINANCEDEFAULT) { SpecifiedHuffman(ChrominanceACBits,ChrominanceACValues); } else if (ntoken==R_LUMINANCEDEFAULT) { SpecifiedHuffman(LuminanceACBits,LuminanceACValues); } else { WHEREAMI(); printf("Expected left bracket or ACDEFAULT.\n"); break; } SetACHuffman(dest); CImage->NumberACTables = MAX(CImage->NumberACTables,(dest+1)); ARRAYEND; break; case R_DCSPEC: ntoken=yylex(); ARRAYBEGIN; dest = yyint; InBounds(dest,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; MakeXhuff(); MakeEhuff(); if ((ntoken=yylex())==R_LBRACKET) { if (!(ptr=(int *)calloc(38,sizeof(int)))) /* Get bits */ { WHEREAMI(); printf("Out of custom bits space.\n"); exit(ERROR_MEMORY); } for(i=0;i<32;i++) { ptr[i]=0; } for(accum=0,i=0;i<17;i++) /* First index is bitlength of 1. */ { /* 0-16 to force right bracket. */ ntoken=yylex(); if (ntoken==R_INTEGER) { accum+=yyint; ptr[i]=yyint; } else break; } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected integer or right bracket.\n"); break; } if (yylex()!=R_LBRACKET) /* Get values */ { WHEREAMI(); printf("Expected left bracket.\n"); break; } if (!(ptr2=(int *)calloc(257,sizeof(int)))) { WHEREAMI(); printf("Out of custom Huffman value space.\n"); exit(ERROR_MEMORY); } for(i=0;i<257;i++) { ptr2[i]=0; } for(i=0;i<257;i++) /*One additional to force r-bracket.*/ { ntoken=yylex(); if (ntoken==R_INTEGER) { ptr2[i]=yyint; } else break; } if (i!=accum) { WHEREAMI(); printf("Number of bitlengths != number of values."); } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected integer or right bracket.\n"); break; } SpecifiedHuffman(ptr,ptr2); } else if (ntoken==R_CHROMINANCEDEFAULT) { SpecifiedHuffman(ChrominanceDCBits,ChrominanceDCValues); } else if (ntoken==R_LUMINANCEDEFAULT) { SpecifiedHuffman(LuminanceDCBits,LuminanceDCValues); } else { WHEREAMI(); printf("Expected left bracket or DCDEFAULT.\n"); break; } SetDCHuffman(dest); CImage->NumberDCTables = MAX(CImage->NumberDCTables,(dest+1)); ARRAYEND; break; } } } /*NOPROTO*/ /*END*/ int yyvstop[] ={ 0, 16, 0, 1, 16, 0, 1, 0, 16, 0, 12, 16, 0, 16, 0, 12, 16, 0, 12, 16, 0, 4, 16, 0, 4, 16, 0, 4, 16, 0, 12, 16, 0, 12, 16, 0, 12, 16, 0, 2, 16, 0, 2, 16, 0, 10, 12, 16, 0, 11, 12, 16, 0, 17, 0, 17, 0, 17, 0, 13, 0, 12, 0, 3, 0, 14, 0, 3, 0, 4, 0, 4, 0, 8, 0, 6, 0, 8, 0, 8, 0, 2, 0, 2, 0, 2, 6, 0, 15, 0, 13, 0, 9, 0, 3, 0, 3, 0, 7, 0, 5, 0, 3, 0, 3, 0, 3, 0, 3, 0, 0}; # define YYTYPE unsigned char struct yywork { YYTYPE verify, advance; } yycrank[] ={ 0,0, 0,0, 3,7, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 3,8, 3,9, 0,0, 0,0, 8,9, 8,9, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 3,10, 3,11, 8,9, 0,0, 3,11, 3,12, 3,11, 3,11, 3,11, 3,11, 3,11, 30,50, 3,13, 3,14, 3,15, 3,16, 3,16, 3,16, 3,16, 3,16, 3,16, 3,16, 3,17, 14,35, 3,18, 3,11, 3,19, 3,11, 3,20, 6,26, 26,49, 3,21, 3,21, 31,51, 6,27, 18,33, 0,0, 3,22, 3,22, 19,33, 19,33, 0,0, 54,63, 0,0, 0,0, 3,22, 43,58, 43,58, 43,58, 43,58, 43,58, 43,58, 43,58, 43,58, 3,22, 0,0, 0,0, 3,23, 3,7, 3,24, 3,11, 4,11, 0,0, 0,0, 4,11, 4,12, 4,11, 4,11, 4,11, 0,0, 4,11, 0,0, 4,13, 4,14, 0,0, 4,16, 4,16, 4,16, 4,16, 4,16, 4,16, 4,16, 0,0, 0,0, 4,18, 4,11, 4,19, 4,11, 4,20, 3,11, 3,11, 3,11, 3,11, 5,25, 52,51, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 5,25, 5,25, 52,60, 52,60, 52,60, 52,60, 52,60, 52,60, 52,60, 52,60, 0,0, 10,28, 0,0, 0,0, 0,0, 0,0, 4,23, 0,0, 4,24, 10,28, 10,28, 0,0, 12,31, 0,0, 0,0, 5,25, 0,0, 0,0, 0,0, 0,0, 12,31, 12,31, 0,0, 5,26, 5,25, 0,0, 0,0, 0,0, 5,27, 5,25, 0,0, 0,0, 0,0, 0,0, 10,29, 0,0, 0,0, 5,25, 4,11, 4,11, 4,11, 4,11, 0,0, 10,28, 0,0, 12,31, 5,25, 5,25, 10,28, 0,0, 0,0, 0,0, 5,25, 5,25, 12,31, 0,0, 10,28, 0,0, 0,0, 12,31, 5,25, 0,0, 0,0, 0,0, 0,0, 10,28, 10,28, 12,31, 0,0, 5,25, 0,0, 10,28, 10,28, 5,25, 0,0, 5,25, 12,31, 12,31, 0,0, 10,28, 0,0, 0,0, 12,31, 12,31, 0,0, 0,0, 0,0, 0,0, 10,28, 0,0, 12,31, 0,0, 10,30, 0,0, 10,28, 0,0, 0,0, 0,0, 0,0, 12,31, 0,0, 0,0, 0,0, 12,32, 13,33, 12,31, 13,34, 13,34, 13,34, 13,34, 13,34, 13,34, 13,34, 13,34, 13,34, 13,34, 15,36, 0,0, 15,37, 15,37, 15,37, 15,37, 15,37, 15,37, 15,37, 15,37, 15,38, 15,38, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 15,39, 15,40, 15,40, 15,39, 15,41, 15,39, 0,0, 15,42, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 15,43, 60,31, 60,31, 60,31, 60,31, 60,31, 60,31, 60,31, 60,31, 15,44, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 15,39, 15,40, 15,40, 15,39, 15,39, 15,39, 0,0, 15,42, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 15,43, 0,0, 0,0, 0,0, 32,31, 0,0, 0,0, 0,0, 16,36, 15,44, 16,37, 16,37, 16,37, 16,37, 16,37, 16,37, 16,37, 16,37, 16,38, 16,38, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 16,39, 16,40, 16,40, 16,39, 16,41, 16,39, 0,0, 16,42, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 16,45, 32,52, 32,52, 32,52, 32,52, 32,52, 32,52, 32,52, 32,52, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 16,39, 16,40, 16,40, 16,39, 16,39, 16,39, 0,0, 16,42, 0,0, 0,0, 0,0, 0,0, 0,0, 17,36, 16,45, 17,38, 17,38, 17,38, 17,38, 17,38, 17,38, 17,38, 17,38, 17,38, 17,38, 0,0, 0,0, 0,0, 0,0, 32,31, 0,0, 0,0, 17,39, 17,39, 17,39, 17,39, 17,41, 17,39, 0,0, 17,42, 34,34, 34,34, 34,34, 34,34, 34,34, 34,34, 34,34, 34,34, 34,34, 34,34, 56,66, 56,66, 56,66, 56,66, 56,66, 56,66, 56,66, 56,66, 56,66, 56,66, 0,0, 34,53, 0,0, 0,0, 17,39, 17,39, 17,39, 17,39, 17,39, 17,39, 0,0, 17,42, 21,46, 21,46, 21,46, 21,46, 21,46, 21,46, 21,46, 21,46, 21,46, 21,46, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 21,46, 21,46, 21,46, 21,46, 21,46, 21,46, 21,47, 21,48, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 21,46, 21,46, 21,46, 21,46, 21,46, 21,46, 21,47, 21,48, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 21,47, 22,47, 22,47, 22,47, 22,47, 22,47, 22,47, 22,47, 22,47, 22,47, 22,47, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 22,47, 22,47, 22,47, 22,47, 22,47, 22,47, 0,0, 22,47, 36,54, 36,54, 36,54, 36,54, 36,54, 36,54, 36,54, 36,54, 36,54, 36,54, 57,57, 57,57, 57,57, 57,57, 57,57, 57,57, 57,57, 57,57, 57,57, 57,57, 0,0, 36,55, 0,0, 0,0, 22,47, 22,47, 22,47, 22,47, 22,47, 22,47, 0,0, 22,47, 39,39, 39,39, 39,39, 39,39, 39,39, 39,39, 39,39, 39,39, 39,39, 39,39, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 39,39, 39,39, 39,39, 39,39, 39,39, 39,39, 41,56, 39,42, 41,56, 0,0, 0,0, 41,57, 41,57, 41,57, 41,57, 41,57, 41,57, 41,57, 41,57, 41,57, 41,57, 61,62, 61,62, 61,62, 61,62, 61,62, 61,62, 61,62, 61,62, 61,62, 61,62, 0,0, 39,39, 39,39, 39,39, 39,39, 39,39, 39,39, 0,0, 39,42, 44,59, 44,59, 44,59, 44,59, 44,59, 44,59, 44,59, 44,59, 44,59, 44,59, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 44,59, 44,59, 44,59, 44,59, 44,59, 44,59, 47,47, 47,47, 47,47, 47,47, 47,47, 47,47, 47,47, 47,47, 47,47, 47,47, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 47,47, 47,47, 47,47, 47,47, 47,47, 47,47, 0,0, 47,47, 0,0, 44,59, 44,59, 44,59, 44,59, 44,59, 44,59, 53,61, 0,0, 53,61, 0,0, 0,0, 53,62, 53,62, 53,62, 53,62, 53,62, 53,62, 53,62, 53,62, 53,62, 53,62, 0,0, 0,0, 47,47, 47,47, 47,47, 47,47, 47,47, 47,47, 0,0, 47,47, 48,47, 48,47, 48,47, 48,47, 48,47, 48,47, 48,47, 48,47, 48,47, 48,47, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 48,47, 48,47, 48,47, 48,47, 48,47, 48,47, 55,64, 48,47, 55,64, 0,0, 0,0, 55,65, 55,65, 55,65, 55,65, 55,65, 55,65, 55,65, 55,65, 55,65, 55,65, 64,65, 64,65, 64,65, 64,65, 64,65, 64,65, 64,65, 64,65, 64,65, 64,65, 0,0, 48,47, 48,47, 48,47, 48,47, 48,47, 48,47, 63,67, 48,47, 63,67, 0,0, 0,0, 63,68, 63,68, 63,68, 63,68, 63,68, 63,68, 63,68, 63,68, 63,68, 63,68, 67,68, 67,68, 67,68, 67,68, 67,68, 67,68, 67,68, 67,68, 67,68, 67,68, 0,0, 0,0}; struct yysvf yysvec[] ={ 0, 0, 0, yycrank+0, 0, 0, yycrank+0, 0, 0, yycrank+-1, 0, 0, yycrank+-61, yysvec+3, 0, yycrank+-127, 0, 0, yycrank+-22, yysvec+5, 0, yycrank+0, 0, yyvstop+1, yycrank+5, 0, yyvstop+3, yycrank+0, yysvec+8, yyvstop+6, yycrank+-146, 0, yyvstop+8, yycrank+0, 0, yyvstop+10, yycrank+-157, 0, yyvstop+13, yycrank+204, 0, yyvstop+15, yycrank+16, 0, yyvstop+18, yycrank+216, 0, yyvstop+21, yycrank+289, 0, yyvstop+24, yycrank+353, 0, yyvstop+27, yycrank+9, 0, yyvstop+30, yycrank+13, 0, yyvstop+33, yycrank+0, yysvec+18, yyvstop+36, yycrank+410, 0, yyvstop+39, yycrank+485, yysvec+21, yyvstop+42, yycrank+0, 0, yyvstop+45, yycrank+0, 0, yyvstop+49, yycrank+0, 0, yyvstop+53, yycrank+18, 0, yyvstop+55, yycrank+0, yysvec+14, yyvstop+57, yycrank+0, yysvec+10, 0, yycrank+0, 0, yyvstop+59, yycrank+-12, yysvec+10, 0, yycrank+29, 0, 0, yycrank+321, 0, 0, yycrank+0, 0, yyvstop+61, yycrank+378, 0, yyvstop+63, yycrank+0, 0, yyvstop+65, yycrank+510, 0, yyvstop+67, yycrank+0, yysvec+16, yyvstop+69, yycrank+0, yysvec+17, yyvstop+71, yycrank+542, 0, 0, yycrank+0, yysvec+39, yyvstop+73, yycrank+570, yysvec+39, 0, yycrank+0, 0, yyvstop+75, yycrank+33, 0, yyvstop+77, yycrank+599, 0, 0, yycrank+0, 0, yyvstop+79, yycrank+0, yysvec+21, yyvstop+81, yycrank+622, yysvec+21, yyvstop+83, yycrank+679, yysvec+21, yyvstop+85, yycrank+0, 0, yyvstop+88, yycrank+0, yysvec+10, yyvstop+90, yycrank+0, 0, yyvstop+92, yycrank+90, 0, 0, yycrank+659, 0, 0, yycrank+8, yysvec+36, yyvstop+94, yycrank+707, 0, 0, yycrank+388, 0, 0, yycrank+520, yysvec+39, yyvstop+96, yycrank+0, yysvec+43, yyvstop+98, yycrank+0, yysvec+44, yyvstop+100, yycrank+248, yysvec+52, 0, yycrank+580, 0, 0, yycrank+0, yysvec+61, yyvstop+102, yycrank+739, 0, 0, yycrank+717, 0, 0, yycrank+0, yysvec+64, yyvstop+104, yycrank+0, yysvec+56, yyvstop+106, yycrank+749, 0, 0, yycrank+0, yysvec+67, yyvstop+108, 0, 0, 0}; struct yywork *yytop = yycrank+806; struct yysvf *yybgin = yysvec+1; char yymatch[] ={ 00 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,011 ,012 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 011 ,01 ,'"' ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,'+' ,01 ,'+' ,01 ,01 , '0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' , '8' ,'8' ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,'A' ,'B' ,'B' ,'A' ,'A' ,'A' ,'G' , 'H' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'O' , 'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' , 'X' ,'G' ,'G' ,01 ,0134,01 ,'^' ,01 , 01 ,'A' ,'B' ,'B' ,'A' ,'A' ,'A' ,'G' , 'H' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'O' , 'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' , 'X' ,'G' ,'G' ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 0}; char yyextra[] ={ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0}; /* ncform 4.1 83/08/11 */ int yylineno =1; # define YYU(x) x # define NLSTATE yyprevious=YYNEWLINE char yytext[YYLMAX]; struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp; char yysbuf[YYLMAX]; char *yysptr = yysbuf; int *yyfnd; extern struct yysvf *yyestate; int yyprevious = YYNEWLINE; yylook(){ register struct yysvf *yystate, **lsp; register struct yywork *yyt; struct yysvf *yyz; int yych; struct yywork *yyr; # ifdef LEXDEBUG int debug; # endif char *yylastch; /* start off machines */ # ifdef LEXDEBUG debug = 0; # endif if (!yymorfg) yylastch = yytext; else { yymorfg=0; yylastch = yytext+yyleng; } for(;;){ lsp = yylstate; yyestate = yystate = yybgin; if (yyprevious==YYNEWLINE) yystate++; for (;;){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1); # endif yyt = yystate->yystoff; if(yyt == yycrank){ /* may not be any transitions */ yyz = yystate->yyother; if(yyz == 0)break; if(yyz->yystoff == yycrank)break; } *yylastch++ = yych = input(); tryagain: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"unsigned char "); allprint(yych); putchar('\n'); } # endif yyr = yyt; if ( (int)yyt > (int)yycrank){ yyt = yyr + yych; if (yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } # ifdef YYOPTIM else if((int)yyt < (int)yycrank) { /* r < yycrank */ yyt = yyr = yycrank+(yycrank-yyt); # ifdef LEXDEBUG if(debug)fprintf(yyout,"compressed state\n"); # endif yyt = yyt + yych; if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } yyt = yyr + YYU(yymatch[yych]); # ifdef LEXDEBUG if(debug){ fprintf(yyout,"try fall back character "); allprint(YYU(yymatch[yych])); putchar('\n'); } # endif if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transition */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1); # endif goto tryagain; } # endif else {unput(*--yylastch);break;} contin: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"state %d char ",yystate-yysvec-1); allprint(yych); putchar('\n'); } # endif ; } # ifdef LEXDEBUG if(debug){ fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1); allprint(yych); putchar('\n'); } # endif while (lsp-- > yylstate){ *yylastch-- = 0; if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){ yyolsp = lsp; if(yyextra[*yyfnd]){ /* must backup */ while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){ lsp--; unput(*yylastch--); } } yyprevious = YYU(*yylastch); yylsp = lsp; yyleng = yylastch-yytext+1; yytext[yyleng] = 0; # ifdef LEXDEBUG if(debug){ fprintf(yyout,"\nmatch "); sprint(yytext); fprintf(yyout," action %d\n",*yyfnd); } # endif return(*yyfnd++); } unput(*yylastch); } if (yytext[0] == 0 /* && feof(yyin) */) { yysptr=yysbuf; return(0); } yyprevious = yytext[0] = input(); if (yyprevious>0) output(yyprevious); yylastch=yytext; # ifdef LEXDEBUG if(debug)putchar('\n'); # endif } } yyback(p, m) int *p; { if (p==0) return(0); while (*p) { if (*p++ == m) return(1); } return(0); } /* the following are only used in the lex library */ yyinput(){ return(input()); } yyoutput(c) int c; { output(c); } yyunput(c) int c; { unput(c); } pvrg-jpeg-1.2.1/jpeg.10000644000175000017500000001453605725223012013774 0ustar naolivnaoliv.TH JPEG 1 "14 June 1993" .UC 4 .SH NAME jpeg \- JPEG compression and decompression .SH SYNOPSIS .B jpeg -iw ImageWidth -ih ImageHeight [-JFIF] [-q(l) Q-Factor] .B [-a] [-b] [-d] [-k predictortype] [-n] [-o] [-y] [-z] .B [-p PrecisionValue] [-t pointtransform] .B [-r ResyncInterval] [-s StreamName] .B [[-ci ComponentIndex1] [-fw FrameWidth1] [-fh FrameHeight1] .B [-hf HorizontalFrequency1] [-vf VerticalFrequency1] .B ComponentFile1] .B [[-ci ComponentIndex2] [-fw FrameWidth2] [-fh FrameHeight2] .B [-hf HorizontalFrequency2] [-vf VerticalFrequency2] .B ComponentFile2] .B .... .br .SH DESCRIPTION .I jpeg is a still-image compression/decompression program that performs JPEG encoding and decoding of multiple raster-scanned files. .PP .SH OPTIONS .TP .B ImageWidth specifies the width of the original image. This should correspond to the width of the widest component and, thus, the width of the ``original image''. All components have widths roughly corresponding to an integer decimation ratio from this specification. .br .TP .B ImageHeight specifies the height of the tallest component. This corresponds to the height of the ``original image''. .TP .B -JFIF specifies that a JFIF header is placed on the encoded stream. This is unnecessary for decoding. .TP .B Q-Factor option specifies a multiplicative factor for the quantization: each quantization coefficient of the default matrix is scaled by (Q-Factor/50). A Q-Factor of 0 is the same thing as a Q-Factor of 50 because it disables this function. .B -q specifies an 8 bit quantization matrix; .B -ql specifies a 16 bit quantization matrix, useful for 12 bit data. .TP .B -a enables the double-precision floating point Reference DCT. (Default is Chen DCT.) .TP .B -b enables the Lee DCT. (Default is Chen DCT.) .TP .B -d enables decoding. See below. .TP .B -k predictortype The lossless predictor type, specified as an integer between 1-7. If specified, then lossless mode is used. .TP .B -n This option specifies that the files should not be transmitted in interleaved format. .TP .B -o signals that the command interpreter will read from the standard input. .TP .B -p Specifies the precision. Normally should be between 2-16 for lossless; 8 or 12 for DCT. If it is specified as a number greater than 8 then the input is considered to be unsigned shorts (16 bits, msb first). Not aggressively checked. .TP .B -t pointtransform Specifies the shifting (right) upon loading input and shifting (left) upon writing input. Generally used by the lossless mode only. Can be used by the DCT mode to add or subtract bits. .TP .B -y for decoding only, signals that .I no resynchronization is enabled, thus ignore any markers found in the data stream. .TP .B -z enables use of default Huffman tables. This converts the coding from a two-pass system using the first pass to generate custom tables to a one-pass system using internal default tables. With this option, the compression speed is nearly doubled, but because the internal tables are not custom to the image, the compressed file size increases slightly. .TP .B ResyncInterval specifies a resync (restart) interval for the input file--if set to 0 (default), resynchronization is disabled; otherwise it signifies the number of MDU between a resync marker. .TP .B StreamName is the place to load(decoder)/store(encoder) the coded image--if unspecified it defaults to .B ComponentFile1.jpg. .br For every component in the image we have: .TP .B ComponentIndex describes the component index where the file data should be associated with. The possible values are between 0 and 255. As a rule Y is in 1; U is in 2; V is in 3. The file specfications, if left undisturbed, will result in component location of 1 for the first component file, 2 for the second component file, and so on. If .B -ci is specified for the previous component file, then the next component index defaults to the previous component index plus 1. .TP .B FrameWidth describes the actual width of the component. This should be determinable by the size of the original image (ImageHeight and ImageWidth) and the frequency sampling of that component. This program assumes that the sampling component will be round .I up to the nearest integer and other programs may not necessarily follow that convention, we allow precise specification of the FrameWidth. The program will notify the user if the framewidth and frameheight specifications do not correspond to a logical MDU pattern and thus will refuse to take the input (in fact, sometimes rounding down will not result in a logical MDU pattern). .TP .B FrameHeight describes the actual height of the component. Multiplied together with FrameWidth, this should equal the file size of the component. See the above discussion on the actual specification. .TP .B Hor-Frequency specifies the block sampling frequency of the component in the horizontal direction for every MDU transmitted. .TP .B Ver-Frequency specifies the block sampling frequency of the component in the vertical direction. When multiplied together with the Horizontal frequency, it corresponds to the number of blocks of that component in the MDU. .TP .B ComponentFile\fIn\fR represents the directory path location of the \fIn\fRth component file. .PP .SH EXAMPLES In order to encode a set of raster-scanned files: 128x128 in .B image.Y; 64x128 in .B image.U; and 64x128 in .B image.V into the file .B image.jpg, the command is .br .B jpeg -iw 128 -ih 128 -hf 2 image.Y image.U image.V -s image.jpg .br In order to decode a compressed file in .B image.jpg, type .br .B jpeg -d -s image.jpg .br The three output files will be in .B image.jpg.1 image.jpg.2 image.jpg.3. The images can be displayed by the .I cv program. The images can also be converted to ppm and back through the programs .I cyuv2ppm and .I ppm2cyuv Those utility programs available by anonymous ftp from .I havefun.stanford.edu:pub/cv/CVv1.2.1.tar.Z. .br There are many more options within an internal command interpreter. Please see the accompanying documentation in .I doc.ps for more details. .PP .SH FTP .I jpeg is available by anonymous ftp from .I havefun.stanford.edu:pub/jpeg/JPEGv1.2.tar.Z. .PP .SH BUGS Somewhat slower than many commercial implementations, some bugs are probably lurking around. Lossless coding and decoding are especially slow. Please inform the author at achung@cs.stanford.edu if any bugs are found. .PP .SH AUTHOR .PP Andy Hung pvrg-jpeg-1.2.1/README0000644000175000017500000001621705725223012013643 0ustar naolivnaoliv MPEG, CCITT H.261 (P*64), JPEG Image and Image sequence compression/decompression C software engines. The Portable Video Research Group at Stanford have developed image/image sequence compression and decompression engines (codecs) for MPEG, CCITT H.261, and JPEG. The primary goal of these codecs is to provide the functionality - these codecs are not optimized for speed, rather completeness, and some of the code is kludgey. Development of MPEG, P64, and JPEG engines has not been the primary goal of the Portable Video Research Group. Our research has been focused on software and hardware for portable wireless digital video communication. The charter of this group ended in the summer of 1994. COMMENTS/DISCLAIMERS: This code has been compiled on the Sun Sparc and DECstation UNIX machines; some code has been further checked on HP workstations. For comments, bugs, and other mail relating to the source code, we appreciate any comments. The code author can still be reached at Andy C. Hung at achung@cs.stanford.edu. The standard public domain disclaimer applies: Caveat Emptor - no guarantee on accuracy or software support. References related to these codecs should NOT use any author's name, or refer to Stanford University. Rather the Portable Video Research Group or the acronym (PVRG) should be used, such as PVRG-MPEG, PVRG-P64, PVRG-JPEG. ANONYMOUS FTP: The following files can be obtained through anonymous ftp from havefun.stanford.edu, IP address [36.2.0.35]. The procedure is to use ftp with the user name "anonymous" and an e-mail address for the password. CODEC DESCRIPTION: I) PVRG-MPEG CODEC: (pub/mpeg/MPEGv1.2.1.tar.Z) This public domain video encoder and decoder was generated according to the Santa Clara August 1991 format. It has been tested successfully with decoders using the Paris December 1991 format. The codec is capable of encoding all MPEG types of frames. The algorithms for rate control, buffer-constrained encoding, and quantization decisions are similar, but not identical, to that of the (simulation model 1-3) MPEG document. The rate control used is a simple proportional Q-stepsize/Buffer loop that works though not very well - better rate-control is the essence for good quality buffer-constrained MPEG encoding. Verification of the buffering is possible so as to provide streams for real-time decoders. The MPEG codec performs compression and decompression on raw raster scanned YCbCr (also known as digital YUV) files. The companion display program for the X window system is described in section IV) below. A manual of approximately 50 pages describes the program's use. There are also MPEG compressed files from the table tennis sequence in tennis.mpg and the flower garden sequence in flowg.mpg. This codec was recently tested with the MPEG decoder of the Berkeley Plateau Research group. If what you want is decoding and X display, then you might want to look into their faster public domain MPEG decoder/viewer. The Berkeley player is available via anonymous ftp from toe.cs.berkeley.edu (128.32.149.117) in /pub/multimedia/mpeg/mpeg-2.0.tar.Z. There is also an encoder at that site. An ISO mpeg2 encoder and decoder is available by anonymous ftp from ftp.netcom.com in the directory pub/c/cfogg/mpeg2 (alternate sites may include ftp.uu.net). II) PVRG-P64 CODEC: (pub/p64/P64v1.2.tar.Z) This public domain video encoder and decoder is based on the CCITT H.261 specification. Some encoding algorithms are based on the RM 8 encoder. We have tested it against a verified encoded sequence on the CCITT 1992 specifications, but we would still appreciate anyone having p64 video test sequences to let know. Like the MPEG codec, it supports all the encoding and decoding modes, and has provisions for buffer-constrained encoding, so it can produce streams for real-time decoders. The H.261 codec takes the similar YCbCr raster scanned files as the MPEG codec, and performs compression and decompresion on raster scanned YCbCr files. It can take standard CIF or NTSC-CIF files. The display of these programs is described in section IV) below. A manual of approximately 50 pages describes its use. There are also P64 compressed files from the table tennis sequence in table.p64 and the flower garden sequence in flowg.p64. The Inria codec also performs H.261 video compression and is integrated into a teleconferencing system; it can be obtained from avahi.inria.fr, in /pub/h261.tar.Z. III) PVRG-JPEG CODEC: (pub/jpeg/JPEGv1.2.tar.Z) This public domain image encoder and decoder is based on the JPEG Committee Draft. It supports all of the baseline for encoding and decoding. The JPEG encoder is flexible in the variety of output possible. It also supports lossless coding, though not as speedy as we would like. The manual is approximately 50 pages long which describes its use. The display program for JFIF-style (YCbCr) files is described in section IV) below. The JFIF style is not a requirement for this codec - it can compress and decompress CMYK, RGB, RGBalpha, and other formats - this codec may be helpful if you wish to extract information from non-JFIF encoded JPEG files. This codec has been tested on publicly available JPEG data. For general purpose X display, you might want to try the program "xv" (version 2.0 or greater). The JPEG engine of the program "xv" is based on the free, portable C code for JPEG compression available from the Independent JPEG Group. (anonymous login - ftp.uu.net (137.39.1.9 or 192.48.96.9) /graphics/jpeg/jpegsrc.v4.tar.Z). IV) X VIEWER: (pub/cv/CVv1.2.1.tar.Z) This viewer allows the user to look at image or image sequences generated through the codecs described above. These image or image sequences are in the YCbCr (also known as digital YUV) colorspace (either JFIF specified or CCIR 601 specified) and may be 4:1:1 (CIF, or MPEG 4:2:0 style) or 2:1:1 (CCIR-601 4:2:2 style) or 1:1:1 (non-decimated or CCIR-601 4:4:4 style). A short manual of approximately 2 pages describes its use. ACKNOWLEDGEMENTS: Funded by the Defense Advanced Research Projects Agency. I am especially grateful to Hewlett Packard and Storm Technology for their financial support during the earlier stages of codec development. Any errors in the code and documentation are my own. The following people are acknowledged for their advice and assistance. Thanks, one and all. The Portable Video Research Group at Stanford: Teresa Meng, Peter Black, Navin Chaddha, Ben Gordon, Sheila Hemami, Wee-Chiew Tan, Eli Tsern. Adriaan Ligtenberg of Storm Technology. Jeanne Wiseman, Andrew Fitzhugh, Gregory Yovanof and Chuck Rosenberg of Hewlett Packard. Eric Hamilton and Jean-Georges Fritsch of C-Cube Microsystems. Lawrence Rowe of the Berkeley Plateau Research Group. Tom Lane of the Independent JPEG Group. Katsumi Tahara, Sony. Ciaran Mc Goldrick. Karl Lillevold. Mats Lofkvist. Hiroshi Saitoh, Panasonic. Frank Gadegast. Chad Fogg, Cascade. Thierry Turletti, Inria. Anders Klemets. Graham Logan. Jelle van Zeijl. George Warner, AT&T. Chris Adams, Hewlett Packard. Kent Murray, Atlantic Centre For Remote Sensing Of The Oceans. I. C. Yang. Donald Lindsay. Harald A. Schiller, Tektronix. Ismail Dalgic. Tom Shield. Y. Fujii. pvrg-jpeg-1.2.1/marker.c0000644000175000017500000004313005725223004014403 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ /* ************************************************************ marker.c This file contains the Marker library which uses the direct buffer access routines bgetc... ************************************************************ */ /*LABEL marker.c */ /*Include files */ #include "globals.h" #include "stream.h" #include "marker.h" #ifdef SYSV #include #endif /*PUBLIC*/ extern void WriteSoi(); extern void WriteEoi(); extern void WriteJfif(); extern void WriteSof(); extern void WriteDri(); extern void WriteDqt(); extern void WriteSos(); extern void WriteDht(); extern void ReadSof(); extern void ReadDqt(); extern void ReadDht(); extern void ReadDri(); extern void ReadDnl(); extern int CheckMarker(); extern void CheckScan(); extern void ReadSos(); extern void MakeConsistentFrameSize(); /*PRIVATE*/ /* External marker definition */ extern FRAME *CFrame; extern IMAGE *CImage; extern SCAN *CScan; extern int NumberMDU; extern int Loud; extern int izigzag_index[]; #define Zigzag(i) izigzag_index[i] /*START*/ /*BFUNC WriteSoi() puts an SOI marker onto the stream. EFUNC*/ void WriteSoi() { BEGIN("WriteSoi"); swbytealign(); bputc(MARKER_MARKER); bputc(MARKER_SOI); } /*BFUNC WriteEoi() puts an EOI marker onto the stream. EFUNC*/ void WriteEoi() { BEGIN("WriteEoi"); swbytealign(); bputc(MARKER_MARKER); bputc(MARKER_EOI); } /*BFUNC WriteJfif() puts an JFIF APP0 marker onto the stream. This is a generic 1x1 aspect ratio, no thumbnail specification. EFUNC*/ void WriteJfif() { BEGIN("WriteJfif"); int Start,End; swbytealign(); bputc(MARKER_MARKER); bputc(MARKER_APP); Start = swtell(); /* Find out the start of position. */ bputw(0); /* Put a 0 down onto the stream. */ bputc(0x4a); bputc(0x46); bputc(0x49); bputc(0x46); bputc(0x00); bputc(0x01); bputc(0x02); /*Version 1.02*/ bputc(0x00); /* No absolute DPI */ bputw(1); /* Aspect ratio */ bputw(1); bputc(0x00); /* No thumbnails */ bputc(0x00); End = swtell(); /* Find out end of the marker. */ swseek(Start); /* Rewind */ bputw((End-Start) >> 3); /* Put marker there. */ if ((Start-End) & 0x7) /* if not byte flush, then problems. */ { WHEREAMI(); printf("Bad frame marker, not byte flush.\n"); } swseek(End); } /*BFUNC WriteSof() puts an SOF marker onto the stream. EFUNC*/ void WriteSof() { BEGIN("WriteSof"); int i,j,Start,End; swbytealign(); bputc(MARKER_MARKER); bputc(MARKER_SOF|(CFrame->Type&0xf)); Start = swtell(); /* Find out the start of position. */ bputw(0); /* Put a 0 down onto the stream. */ bputc(CFrame->DataPrecision); if (!CFrame->InsertDnl) {bputw(CFrame->GlobalHeight);} else {bputw(0);} bputw(CFrame->GlobalWidth); bputc(CFrame->GlobalNumberComponents); for(i=0;iGlobalNumberComponents;i++) { bputc(j=CFrame->cn[i]); /* Store off in index */ bputn(CFrame->hf[j],CFrame->vf[j]); bputc(CFrame->tq[j]); } End = swtell(); /* Find out end of the marker. */ swseek(Start); /* Rewind */ bputw((End-Start) >> 3); /* Put marker there. */ if ((Start-End) & 0x7) /* if not byte flush, then problems. */ { WHEREAMI(); printf("Bad frame marker, not byte flush.\n"); } swseek(End); } /*BFUNC WriteDri() writes out a resync (or restart) interval out to the stream. If unspecified, resync is not enabled. EFUNC*/ void WriteDri() { BEGIN("WriteDri"); swbytealign(); bputc(MARKER_MARKER); bputc(MARKER_DRI); bputw(4); /* Constant length of 4 */ bputw(CFrame->ResyncInterval); } /*BFUNC WriteDnl() writes out a number of line marker out to the stream. Note that we must have defined number of lines before as 0. EFUNC*/ WriteDnl() { BEGIN("WriteDnl"); swbytealign(); bputc(MARKER_MARKER); bputc(MARKER_DNL); bputw(4); /* Constant length of 4 */ bputw(CFrame->GlobalHeight); } /*BFUNC WriteDqt() writes out the quantization matrices in the CImage structure. EFUNC*/ void WriteDqt() { BEGIN("WriteDqt"); int i,j,bignum_p,Start,End,*qmatrix; if (!(CScan->NumberQTablesSend)) return; /* No tables to transmit, then ignore. */ swbytealign(); bputc(MARKER_MARKER); bputc(MARKER_DQT); Start = swtell(); bputw(0); for(i=0;iNumberQTablesSend;i++) { qmatrix = CImage->QuantizationMatrices[CScan->sq[i]]; for(bignum_p=0,j=63;j>=0;j--) { if(qmatrix[j]>255) { bignum_p=0x10; break; } } bputc((bignum_p|CScan->sq[i])); /* Precision defined for big numbers */ if (bignum_p) { for(j=0;j<64;j++) bputw(qmatrix[Zigzag(j)]); } else { for(j=0;j<64;j++) bputc(qmatrix[Zigzag(j)]); } } CScan->NumberQTablesSend=0; /* Clear out queue */ End = swtell(); /* Assume a marker code will follow.*/ swseek(Start); /* bputc(END_QUANTIZATION_TABLE);*/ bputw((End-Start) >> 3); if ((Start-End) & 0x7) { WHEREAMI(); printf("DQT marker not byte flush.\n"); } swseek(End); } /*BFUNC WriteSos() writes a start of scan marker. EFUNC*/ void WriteSos() { BEGIN("WriteSos"); int i,Start,End; swbytealign(); bputc(MARKER_MARKER); bputc(MARKER_SOS); Start = swtell(); bputw(0); bputc(CScan->NumberComponents); for(i=0;iNumberComponents;i++) { bputc(CScan->ci[i]); bputn(CScan->td[i],CScan->ta[i]); } bputc(CScan->SSS); bputc(CScan->SSE); bputn(CScan->SAH,CScan->SAL); End = swtell(); swseek(Start); bputw((End-Start) >> 3); if ((Start-End) & 0x7) { WHEREAMI(); printf("Bad scan marker not byte flush.\n"); } swseek(End); } /*BFUNC WriteDht() writes out the Huffman tables to send. EFUNC*/ void WriteDht() { BEGIN("WriteDht"); int i,Start,End; if (!(CScan->NumberDCTablesSend) && !(CScan->NumberACTablesSend)) return; /* No tables to transmit, then ignore. */ swbytealign(); bputc(MARKER_MARKER); bputc(MARKER_DHT); Start = swtell(); bputw(0); for(i=0;iNumberDCTablesSend;i++) { bputc(CScan->sd[i]); UseDCHuffman(CScan->sd[i]); WriteHuffman(); } for(i=0;iNumberACTablesSend;i++) { bputc(CScan->sa[i]|0x10); UseACHuffman(CScan->sa[i]); WriteHuffman(); } CScan->NumberDCTablesSend=0; /* Clear out send queue */ CScan->NumberACTablesSend=0; /* We end on a new marker... so an end of code table is unnecessary. bputc(END_CODE_TABLE); */ End = swtell(); swseek(Start); bputw((End-Start) >> 3); if ((Start-End) & 0x7) { WHEREAMI(); printf("Bad scan marker not byte flush.\n"); } swseek(End); } /*BFUNC ReadSof() reads a start of frame marker from the stream. We assume that the first two bytes (marker prefix) have already been stripped. EFUNC*/ void ReadSof(Type) int Type; { BEGIN("ReadSof"); int i,j,Length,Start,End,rb; Start = srtell(); Length = bgetw(); if (Loud > MUTE) printf("Frame Length %d\n",Length); CFrame->Type=Type; CFrame->DataPrecision = bgetc(); CFrame->GlobalHeight = bgetw(); CFrame->GlobalWidth = bgetw(); for(i=0;ihf[i]=CFrame->vf[i]=CFrame->tq[i]=0; CFrame->GlobalNumberComponents = bgetc(); for(i=0;iGlobalNumberComponents;i++) { j = bgetc(); rb = bgetc(); CFrame->cn[i] = j; CFrame->hf[j] = hinyb(rb); CFrame->vf[j] = lonyb(rb); CFrame->tq[j] = bgetc(); } MakeConsistentFrameSize(); End = srtell(); if ((End-Start) != (Length<<3)) { WHEREAMI(); printf("Bad read frame length.\n"); } if (Loud > MUTE) { PrintImage(); PrintFrame(); } } /*BFUNC ReadDqt() reads a quantization table marker from the stream. The first two bytes have been stripped off. EFUNC*/ void ReadDqt() { BEGIN("ReadDqt"); int i,Length,Qget,Index,Precision,Start,End; Start = srtell(); Length = bgetw(); if (Loud > MUTE) printf("Quantization Length %d\n",Length); while((Qget=bgetc()) != END_QUANTIZATION_TABLE) { Index = Qget & 0xf; Precision = (Qget >> 4)&0xf; if (Precision > 1) { printf("Bad Precision: %d in Quantization Download\n", Precision); printf("*** Dumping Image ***\n"); PrintImage(); printf("*** Dumping Frame ***\n"); PrintFrame(); exit(ERROR_MARKER); } /* Load in q-matrices */ CImage->QuantizationMatrices[Index] = (int *) calloc(65,sizeof(int)); if (Precision) /* If precision then word quantization*/ { for(i=0;i<64;i++) { if (!(CImage->QuantizationMatrices[Index][Zigzag(i)]=bgetw())) { printf("marker.c:ReadDqt: Quantization value of zero.\n"); if (i) { printf("marker.c:ReadDqt: Changing to i-1.\n"); CImage->QuantizationMatrices[Index][Zigzag(i)]= CImage->QuantizationMatrices[Index][Zigzag(i-1)]; } else { printf("marker.c:ReadDqt: Changing to 16.\n"); CImage->QuantizationMatrices[Index][Zigzag(i)]=16; } } } } else /* Otherwise byte quantization */ { for(i=0;i<64;i++) { if (!(CImage->QuantizationMatrices[Index][Zigzag(i)]=bgetc())) { printf("marker.c:ReadDqt: Quantization value of zero.\n"); if (i) { printf("marker.c:ReadDqt: Changing to i-1.\n"); CImage->QuantizationMatrices[Index][Zigzag(i)]= CImage->QuantizationMatrices[Index][Zigzag(i-1)]; } else { printf("marker.c:ReadDqt: Changing to 16.\n"); CImage->QuantizationMatrices[Index][Zigzag(i)]=16; } } } } } bpushc(END_QUANTIZATION_TABLE); End = srtell(); if ((End-Start) != (Length<<3)) { WHEREAMI(); printf("Bad DQT read length.\n"); } if (Loud > MUTE) { PrintImage(); PrintFrame(); } } /*BFUNC ReadDht() reads a Huffman marker from the stream. We assume that the first two bytes have been stripped off. EFUNC*/ void ReadDht() { BEGIN("ReadDht"); int Index,Where,Length,Start,End; Start = srtell(); Length = bgetw(); if (Loud > MUTE) printf("Define Huffman length %d\n",Length); while((Index = bgetc()) != END_CODE_TABLE) { Where = (Index >> 4) & 0x0f; /* Find location to place it in */ Index = Index & 0x0f; MakeXhuff(); /* Make Huffman table */ MakeDhuff(); ReadHuffman(); if (Where) { SetACHuffman(Index); /* Set current Huffman limit */ CImage->NumberACTables = MAX(CImage->NumberACTables,(Index+1)); } else { SetDCHuffman(Index); CImage->NumberDCTables = MAX(CImage->NumberDCTables,(Index+1)); } } bpushc(END_CODE_TABLE); End = srtell(); if ((End-Start) != (Length<<3)) { WHEREAMI(); printf("Bad DHT length.\n"); } if (Loud > MUTE) PrintImage(); } /*BFUNC ReadDri() reads a resync interval marker from the stream. We assume the first two bytes are stripped off. EFUNC*/ void ReadDri() { BEGIN("ReadDri"); int Length; if ((Length=bgetw())!=4) /* Constant length of 4 */ { WHEREAMI(); printf("Bad length %d, should be 4.\n",Length); } CFrame->ResyncInterval = bgetw(); } /*BFUNC ReadDnl() reads a number of lines marker from the stream. The first two bytes should be stripped off. EFUNC*/ void ReadDnl() { BEGIN("ReadDnl"); int Length; if ((Length=bgetw())!=4) /* Constant length of 4 */ printf("marker.c:ReadDnl: Bad length %d, should be 4.\n",Length); CFrame->GlobalHeight = bgetw(); if (CScan->NumberComponents) { MakeConsistentFrameSize(); CheckScan(); ResizeIob(); if (CFrame->GlobalHeight) { InstallIob(0); if (CFrame->Type==3) NumberMDU = CScan->MDUWide*CScan->MDUHigh; else NumberMDU = CScan->MDUWide*CScan->MDUHigh; } else NumberMDU = -1; } } /*BFUNC CheckMarker() checks to see if there is a marker in the stream ahead. This function presumes that ungetc is not allowed to push more than one byte back. EFUNC*/ int CheckMarker() { BEGIN("CheckMarker"); int Length; int v1; Length = brtell(); v1=bgetw(); if (v1>=0xffc0) { brseek(Length,0L); return(v1&0xff); } brseek(Length,0L); return(0); } /*BFUNC ReadSos() reads in a start of scan from the stream. The first two bytes should have been stripped off. EFUNC*/ void ReadSos() { BEGIN("ReadSos"); int i,Length,Start,End,rb; Start = srtell(); Length = bgetw(); if (Loud > MUTE) { WHEREAMI(); printf("Scan length %d\n",Length); } CScan->NumberComponents = bgetc(); for(i=0;iNumberComponents;i++) { CScan->ci[i] = bgetc(); rb = bgetc(); CScan->td[i] = hinyb(rb); CScan->ta[i] = lonyb(rb); } CScan->SSS = bgetc(); CScan->SSE = bgetc(); rb = bgetc(); CScan->SAH = hinyb(rb); CScan->SAL = lonyb(rb); End = srtell(); if ((End-Start) != (Length<<3)) { WHEREAMI(); printf("Bad scan length.\n"); } if (Loud > MUTE) PrintScan(); MakeConsistentFileNames(); /* A Scan marker always makes new files */ CheckValidity(); CheckBaseline(); CheckScan(); /* Create the io buffer structure */ if (CFrame->Type==3) { MakeIob(IOB_LINE,O_RDWR | O_CREAT, ((CFrame->DataPrecision>8)?2:1)); if (CFrame->GlobalHeight) { InstallIob(0); NumberMDU = CScan->MDUWide*CScan->MDUHigh; } else NumberMDU = -1; } else { MakeIob(IOB_BLOCK,O_WRONLY | O_CREAT | O_TRUNC, ((CFrame->DataPrecision>8)?2:1)); if (CFrame->GlobalHeight) { InstallIob(0); NumberMDU = CScan->MDUWide*CScan->MDUHigh; } else NumberMDU = -1; } /* Sometimes rewinding is necessary */ /* for(i=0;iNumberComponents;i++) { InstallIob(i); RewindIob(); } */ ResetCodec(); /* Reset codec for information */ } /*BFUNC CheckScan() sets the MDU dimensions for the CScan structure. EFUNC*/ void CheckScan() { int i; if (CScan->NumberComponents==1) { i = (((CFrame->GlobalWidth*CFrame->hf[CScan->ci[0]])-1)/CFrame->Maxh)+1; if (CFrame->Type!=3) i = ((i-1)/8)+1; CScan->MDUWide = i; i = (((CFrame->GlobalHeight*CFrame->vf[CScan->ci[0]])-1)/CFrame->Maxv)+1; if (CFrame->Type!=3) i = ((i-1)/8)+1; CScan->MDUHigh = i; } else { CScan->MDUWide=CFrame->MDUWide; CScan->MDUHigh=CFrame->MDUHigh; } } /*BFUNC MakeConsistentFrameSize() makes a consistent frame size for all of the horizontal and vertical frequencies read. EFUNC*/ void MakeConsistentFrameSize() { BEGIN("MakeConsistentFrameSize"); int i,Maxh,Maxv; int TestWide, TestHigh; Maxv = Maxh = 1; for(i=0;ivf[i] > Maxv) Maxv = CFrame->vf[i]; if (CFrame->hf[i] > Maxh) Maxh = CFrame->hf[i]; } for(i=0;ihf[i]) { if (!CFrame->Width[i]) CFrame->Width[i] = (((CFrame->GlobalWidth*CFrame->hf[i])-1)/Maxh)+1; if (!CFrame->Height[i]) CFrame->Height[i] = (((CFrame->GlobalHeight*CFrame->vf[i])-1)/Maxv)+1; } } CFrame->Maxv = Maxv; CFrame->Maxh = Maxh; CFrame->MDUWide = (CFrame->GlobalWidth-1)/Maxh +1; if (CFrame->GlobalHeight) CFrame->MDUHigh = (CFrame->GlobalHeight-1)/Maxv +1; else CFrame->MDUHigh = 0; if (CFrame->Type!=3) { CFrame->MDUWide= (CFrame->MDUWide-1)/8 +1; if (CFrame->MDUHigh) CFrame->MDUHigh= (CFrame->MDUHigh-1)/8 +1; } for(i=0;ihf[i]) { TestWide = ((CFrame->Width[i]-1)/(CFrame->hf[i]))+1; if (CFrame->Type!=3) TestWide= (TestWide-1)/8 +1; if (CFrame->MDUWide!=TestWide) { WHEREAMI(); printf("Inconsistent frame width.\n"); printf("Component[%dx%d]\n", CFrame->Width[i],CFrame->Height[i]); printf("MDU Wide: Image, Component %d!= %d.\n", CFrame->MDUWide,TestWide); } if (CFrame->MDUHigh) { TestHigh = ((CFrame->Height[i]-1)/(CFrame->vf[i]))+1; if (CFrame->Type!=3) TestHigh= (TestHigh-1)/8 +1; if (CFrame->MDUHigh!=TestHigh) { WHEREAMI(); printf("Inconsistent frame height.\n"); printf("Component[%dx%d]\n", CFrame->Width[i],CFrame->Height[i]); printf("MDU High: Image, Component %d!= %d.\n", CFrame->MDUHigh,TestHigh); } } } } } /*END*/ pvrg-jpeg-1.2.1/codec.c0000644000175000017500000003500605725223001014177 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ /* ************************************************************ codec.c This file contains much of the transform coding routines to manipulate the Huffman stream. ************************************************************ */ /*LABEL codec.c */ /* Include files. */ #include "globals.h" #include "csize.h" /* Definitions for renaming functions. */ #define fputv meputv #define fgetv megetv /* Exportable functions. */ /*PUBLIC*/ extern void FrequencyAC(); extern void EncodeAC(); extern void DecodeAC(); extern int DecodeDC(); extern void FrequencyDC(); extern void EncodeDC(); extern void ResetCodec(); extern void ClearFrameFrequency(); extern void AddFrequency(); extern void InstallFrequency(); extern void InstallPrediction(); extern void PrintACEhuff(); extern void PrintDCEhuff(); extern int SizeACEhuff(); extern int SizeDCEhuff(); extern int LosslessDecodeDC(); extern void LosslessFrequencyDC(); extern void LosslessEncodeDC(); /*PRIVATE*/ /* Imported Variables. */ extern int bit_set_mask[]; /* Used for testing sign extension. */ extern int Loud; /* General debug level. */ extern FRAME *CFrame; /* Frame parameter. */ extern IMAGE *CImage; /* Image parameter. */ extern SCAN *CScan; /* Scan parameter. */ /* Local Variables */ static int *LastDC=NULL; /* Last DC value for DPCM. */ static int *ACFrequency=NULL; /* AC Frequency table to accum. statistics.*/ static int *DCFrequency=NULL; /* DC Frequency table to accum. statistics.*/ static int extend_mask[]={ /* Used for sign extensions. */ 0xFFFFFFFE, 0xFFFFFFFC, 0xFFFFFFF8, 0xFFFFFFF0, 0xFFFFFFE0, 0xFFFFFFC0, 0xFFFFFF80, 0xFFFFFF00, 0xFFFFFE00, 0xFFFFFC00, 0xFFFFF800, 0xFFFFF000, 0xFFFFE000, 0xFFFFC000, 0xFFFF8000, 0xFFFF0000, 0xFFFE0000, 0xFFFC0000, 0xFFF80000, 0xFFF00000 }; /*START*/ /*BFUNC FrequencyAC() is used to accumulate the Huffman codes for the input matrix. The Huffman codes are not actually stored but rather the count of each code is stored so that construction of a Custom Table is possible. EFUNC*/ void FrequencyAC(matrix) int *matrix; { BEGIN("FrequencyAC"); int i,k,r,ssss,cofac; for(k=r=0;++k < BLOCKSIZE;) /* Like EncodeAC below except don't write out */ { cofac = abs(matrix[k]); /* Find absolute size */ if (cofac < 256) { ssss = csize[cofac]; } else { cofac = cofac >> 8; ssss = csize[cofac] + 8; } if (matrix[k] == 0) /* Check for zeroes */ { if (k == BLOCKSIZE-1) /* If end of block, then process */ { #ifdef CODEC_DEBUG printf("AC FEncoding EOB %d\n",0); #endif ACFrequency[0]++; /* Increment EOB frequency */ break; } r++; } else { while(r > 15) /* Convert, r, ssss, into RLE */ { #ifdef CODEC_DEBUG printf("AC FEncoding OVFL %d\n",240); #endif ACFrequency[240]++; /* Increment ZRL extender freq */ r -= 16; } i = 16*r + ssss; /* Make code */ r = 0; #ifdef CODEC_DEBUG printf("AC FEncoding nnnnssss %d\n",i); #endif ACFrequency[i]++; /* Increment frequency of such code. */ } } } /*BFUNC EncodeAC() takes the matrix and encodes it by passing the values of the codes found to the Huffman package. EFUNC*/ void EncodeAC(matrix) int *matrix; { BEGIN("EncodeAC"); int i,k,r,ssss,cofac; for(k=r=0;++k> 8; ssss = csize[cofac] + 8; } if (matrix[k] == 0) /* Check for zeroes */ { if (k == BLOCKSIZE-1) { #ifdef CODEC_DEBUG printf("AC Encoding EOB %d\n",0); #endif EncodeHuffman(0); break; } r++; /* Increment run-length of zeroes */ } else { while(r > 15) /* If run-length > 15, time for */ { /* Run-length extension */ #ifdef CODEC_DEBUG printf("AC Encoding OVFL %d\n",240); #endif EncodeHuffman(240); r -= 16; } i = 16*r + ssss; /* Now we can find code byte */ #ifdef CODEC_DEBUG printf("AC Encoding nnnnssss %d\n",i); #endif r = 0; EncodeHuffman(i); /* Encode RLE code */ if (matrix[k]< 0) /* Follow by significant bits */ { fputv(ssss,matrix[k]-1); } else { fputv(ssss,matrix[k]); } } } } /*BFUNC DecodeAC() is used to decode the AC coefficients from the stream in the stream package. The information generated is stored in the matrix passed to it. EFUNC*/ void DecodeAC(matrix) int *matrix; { BEGIN("DecodeAC"); int k,r,s,n; register int *mptr; for(mptr=matrix+1;mptr> 4) & 0xf; /* n = run-length */ if (s) { if ((k += n)>=BLOCKSIZE) break; /* JPEG Mistake */ matrix[k] = fgetv(s); /* Get s bits */ s--; /* Align s */ if ((matrix[k] & bit_set_mask[s]) == 0) /* Also (1 << s) */ { matrix[k] |= extend_mask[s]; /* Also (-1 << s) + 1 */ matrix[k]++; /* Increment 2's c */ } k++; /* Goto next element */ } else if (n == 15) /* Zero run length code extnd */ k += 16; else { break; } } } /*BFUNC DecodeDC() is used to decode a DC value from the input stream. It returns the actual number found. EFUNC*/ int DecodeDC() { BEGIN("DecodeDC"); int s,diff; s = DecodeHuffman(); #ifdef CODEC_DEBUG printf("DC Decode sig. %d\n",s); #endif if (s) { diff = fgetv(s); s--; /* 2's Bit Align */ #ifdef CODEC_DEBUG printf("Raw DC Decode %d\n",diff); #endif if ((diff & bit_set_mask[s]) == 0) { diff |= extend_mask[s]; diff++; } diff += *LastDC; /* Change the last DC */ *LastDC = diff; } return(*LastDC); } /*BFUNC FrequencyDC() is used to accumulate statistics on what DC codes occur most frequently. EFUNC*/ void FrequencyDC(coef) int coef; { BEGIN("FrequencyDC"); int s,diff,cofac; diff = coef - *LastDC; /* Do DPCM */ *LastDC = coef; cofac = abs(diff); if (cofac < 256) /* Find "code" */ { s = csize[cofac]; } else { cofac = cofac >> 8; s = csize[cofac] + 8; } #ifdef CODEC_DEBUG printf("DC FEncoding Difference %d Size %d\n",diff,s); #endif DCFrequency[s]++; /* Increment frequency of such code */ } /*BFUNC EncodeDC() encodes the input coefficient to the stream using the currently installed DC Huffman table. EFUNC*/ void EncodeDC(coef) int coef; { BEGIN("EncodeDC"); int s,diff,cofac; diff = coef - *LastDC; *LastDC = coef; /* Do DPCM */ cofac = abs(diff); if (cofac < 256) { s = csize[cofac]; /* Find true size */ } else { cofac = cofac >> 8; s = csize[cofac] + 8; } #ifdef CODEC_DEBUG printf("DC Encoding Difference %d Size %d\n",diff,s); #endif EncodeHuffman(s); /* Encode size */ if (diff < 0) /* Encode difference */ { diff--; } fputv(s,diff); } /*BFUNC ResetCodec() is used to reset all the DC prediction values. This function is primarily used for initialization and resynchronization. EFUNC*/ void ResetCodec() { BEGIN("ResetCodec"); int i; for(i=0;iNumberComponents;i++) { *CScan->LastDC[i] = 0; /* Sets all DC predictions to 0 */ } } /*BFUNC ClearFrameFrequency() clears all current statistics. EFUNC*/ void ClearFrameFrequency() { int i; int *iptr; for(i=0;iNumberComponents;i++) { *CScan->LastDC[i] = 0; for(iptr=CScan->ACFrequency[i]; iptrACFrequency[i]+257;iptr++) { *iptr = 0; } for(iptr=CScan->DCFrequency[i]; iptrDCFrequency[i]+257;iptr++) { *iptr = 0; } } } /*BFUNC AddFrequency() is used to combine the first set of frequencies denoted by the first pointer to the second set of frequencies denoted by the second pointer. EFUNC*/ void AddFrequency(ptr1,ptr2) int *ptr1; int *ptr2; { BEGIN("AddFrequency"); int i; for(i=0;i<256;i++) { *(ptr1) = *(ptr1) + *(ptr2); ptr1++; ptr2++; } *(ptr1) = MAX(*(ptr1),*(ptr2)); } /*BFUNC InstallFrequency() is used to install a particular frequency set of arrays (denoted by the [index] scan component from the Scan parameters). EFUNC*/ void InstallFrequency(index) int index; { BEGIN("InstallFrequency"); ACFrequency = CScan->ACFrequency[index]; /* Set the right pointers */ DCFrequency = CScan->DCFrequency[index]; LastDC = CScan->LastDC[index]; } /*BFUNC InstallPrediction() is used to install a particular DC prediction for use in frequency counting, encoding and decoding. EFUNC*/ void InstallPrediction(index) int index; { BEGIN("InstallPrediction"); LastDC = CScan->LastDC[index]; /* Set the right pointer */ } /*BFUNC PrintACEhuff() prints out the [index] AC Huffman encoding structure in the Image structure. EFUNC*/ void PrintACEhuff(index) int index; { BEGIN("PrintACEhuff"); int place; EHUFF *eh; int *freq; int i,j; freq = CScan->ACFrequency[index]; eh = CImage->ACEhuff[index]; printf("Code:[Frequency:Size]:TotalBits\n"); for(place=0,i=0;i<8;i++) { for(j=0;j<8;j++) { printf("%2x:[%d:%d]:%d ", place,freq[place],eh->ehufsi[place], freq[place]*eh->ehufsi[place]); place++; } printf("\n"); } } /*BFUNC SizeACEhuff() returns the size in bits necessary to code the particular frequency spectrum by the indexed ehuff. EFUNC*/ int SizeACEhuff(index) int index; { BEGIN("SizeACEhuff"); int place,sumbits; EHUFF *eh; int *freq; freq = CScan->ACFrequency[index]; eh = CImage->ACEhuff[index]; for(sumbits=0,place=0;place<256;place++) /* For all codes, */ { /* return freq * codelength */ sumbits += freq[place]*(eh->ehufsi[place] + (place & 0x0f)); } return(sumbits); } /*BFUNC PrintDCEhuff() prints out the DC encoding Huffman structure in the CImage structure according to the position specified by [index]. EFUNC*/ void PrintDCEhuff(index) int index; { BEGIN("PrintDCEhuff"); int place; EHUFF *eh; int *freq; int i,j; freq = CScan->DCFrequency[index]; eh = CImage->DCEhuff[index]; printf("Code:[Frequency:Size]:TotalBits\n"); for(place=0,i=0;i<8;i++) { for(j=0;j<8;j++) { printf("%2x:[%d:%d]:%d ", place,freq[place],eh->ehufsi[place], freq[place]*eh->ehufsi[place]); place++; } printf("\n"); } } /*BFUNC SizeDCEhuff() returns the bit size of the frequency and codes held by the indexed dc codebook and frequency. EFUNC*/ int SizeDCEhuff(index) int index; { BEGIN("SizeDCEhuff"); int place,sumbits; EHUFF *eh; int *freq; freq = CScan->DCFrequency[index]; eh = CImage->DCEhuff[index]; for(sumbits=0,place=0;place<256;place++) /* For all codes */ { /* Return freq * codelength */ sumbits += freq[place]*(eh->ehufsi[place] + place); } return(sumbits); } /*BFUNC LosslessFrequencyDC() is used to accumulate statistics on what DC codes occur most frequently. EFUNC*/ void LosslessFrequencyDC(coef) int coef; { BEGIN("FrequencyDC"); int s,cofac; cofac = coef&0xffff; /* Take modulo */ if (cofac & 0x8000) /* if signed, then get absoulte val*/ cofac = 0x10000-cofac; for(s=0;cofac>=256;s+=8,cofac>>=8); /* Find "code" */ s += csize[cofac]; #ifdef CODEC_DEBUG printf("DC FEncoding Difference %d Size %d\n",diff,s); #endif DCFrequency[s]++; /* Increment frequency of such code */ } /*BFUNC LosslessEncodeDC() encodes the input coefficient to the stream using the currently installed DC Huffman table. The only exception is the SSSS value of 16. EFUNC*/ void LosslessEncodeDC(coef) int coef; { BEGIN("EncodeDC"); int s,cofac; cofac = coef&0xffff; /* Take modulo */ if (cofac & 0x8000) /* if signed, then get absoulte val*/ cofac = 0x10000-cofac; for(s=0;cofac>=256;s+=8,cofac>>=8); /* Find "code" */ s += csize[cofac]; #ifdef CODEC_DEBUG printf("DC Encoding Difference %d Size %d\n",coeff,s); #endif EncodeHuffman(s); /* Encode size */ if (coef &0x8000) /* Encode difference */ coef--; if (s!=16) fputv(s,coef); } /*BFUNC LosslessDecodeDC() is used to decode a DC value from the input stream. It returns the actual number found. EFUNC*/ int LosslessDecodeDC() { BEGIN("DecodeDC"); int s,coef; s = DecodeHuffman(); #ifdef CODEC_DEBUG printf("DC Decode sig. %d\n",s); #endif if (s==16) return(32768); else if (s) { coef = fgetv(s); s--; /* 2's Bit Align */ #ifdef CODEC_DEBUG printf("Raw DC Decode %d\n",coef); #endif if ((coef & bit_set_mask[s]) == 0) { coef |= extend_mask[s]; coef++; } return(coef); } else return(0); } /*END*/ pvrg-jpeg-1.2.1/lexer.l0000644000175000017500000007001405725222773014267 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ %{ /*LABEL lexer.c */ /* Redefine the yywrap so that we don't have to worry about lex library */ # define yywrap() (1) static char *ReservedWords[] = { /* Token names */ "COMPONENT", "SCAN", "QUANTIZATION", "DCSPEC", "ACCUSTOM", "DCCUSTOM", "PRINTSCAN", "PRINTFRAME", "PRINTIMAGE", "OPENSCAN", "ACSPEC", "WRITESCAN", "WRITEFRAME", "WRITESOI", "WRITEQUANTIZATION", "WRITERESYNC", "WRITEHUFFMAN", "FREQUENCY", "ACSEND", "DCSEND", "QSEND", "STREAMNAME", "IMAGEHEIGHT", "IMAGEWIDTH", "RESYNC", "BUFFER", "OPENSTREAM", "CLOSESTREAM", "FRAMEHEIGHT", "FRAMEWIDTH", "CLOSESCAN", "WRITEEOI", "ECHO", "WRITESPECIAL", "WRITEDIRECT", "LUMINANCEDEFAULT", "CHROMINANCEDEFAULT", "ENABLE", "SCANDNL", "WRITEDNL", "AUTO", "EMPTY", ""}; #define R_COMPONENT 1 /* Token values mapped to token names */ #define R_SCAN 2 #define R_QUANTIZATION 3 #define R_DCSPEC 4 #define R_ACCUSTOM 5 #define R_DCCUSTOM 6 #define R_PRINTSCAN 7 #define R_PRINTFRAME 8 #define R_PRINTIMAGE 9 #define R_OPENSCAN 10 #define R_ACSPEC 11 #define R_WRITESCAN 12 #define R_WRITEFRAME 13 #define R_WRITESOI 14 #define R_WRITEQUANTIZATION 15 #define R_WRITERESYNC 16 #define R_WRITEHUFFMAN 17 #define R_FREQUENCY 18 #define R_ACSEND 19 #define R_DCSEND 20 #define R_QSEND 21 #define R_STREAMNAME 22 #define R_IMAGEHEIGHT 23 #define R_IMAGEWIDTH 24 #define R_RESYNC 25 #define R_BUFFER 26 #define R_OPENSTREAM 27 #define R_CLOSESTREAM 28 #define R_FRAMEHEIGHT 29 #define R_FRAMEWIDTH 30 #define R_CLOSESCAN 31 #define R_WRITEEOI 32 #define R_ECHO 33 #define R_WRITESPECIAL 34 #define R_WRITEDIRECT 35 #define R_LUMINANCEDEFAULT 36 #define R_CHROMINANCEDEFAULT 37 #define R_ENABLE 38 #define R_SCANDNL 39 #define R_WRITEDNL 40 #define R_AUTO 41 #define R_EMPTY 42 #define R_INTEGER 1000 /* Special TYPES for tokens */ #define R_LBRACKET 1001 #define R_RBRACKET 1002 #define R_ID 1003 #define R_STRING 1004 int CommentDepth = 0; /* depth of comment nesting */ int yyint=0; /* Return value for integers */ int LexDebug=0; /* Status of lex debugging */ #define PRIME 211 #define EOS '\0' #define MakeStructure(S) (S *) malloc(sizeof(S)) #define InsertLink(link,list){\ if(!list){list=link;}else{link->next=list;list=link;}} #define LINK struct link_def struct id { /* Default id structure */ char *name; /* Key */ int tokentype; /* Token type */ int count; /* Count of # references */ }; LINK { /* A link for the hash buckets */ struct id *lid; /* Current id */ LINK *next; /* Pointer to next id */ }; /*PUBLIC*/ extern void initparser(); extern void parser(); static int hashpjw(); static LINK * MakeLink(); static struct id * enter(); static int getint(); static char * getstr(); /*PRIVATE*/ /*NOPROTO*/ %} Delim [ \t\n] WhiteSpace {Delim}+ Letter [a-zA-Z] Digit [0-9] HexDigit ({Digit}|[a-fA-F]) OctalDigit [0-7] Id {Letter}({Letter}|{Digit})* DecInteger {Digit}+ HexInteger 0[xX]{HexDigit}+ OctInteger 0[oO]{OctalDigit}+ HexInteger2 {HexDigit}+[Hh] OctInteger2 {OctalDigit}+[BCObco] CharInteger '([^\\]|\\([\n^\n]|{OctalDigit}{1,3}))' ScaleFactor E[-+]?{Digit}+ Real1 ({Digit}+"."{Digit}*({ScaleFactor})?) Real2 ({Digit}*"."{Digit}+({ScaleFactor})?) Real3 ({Digit}+{ScaleFactor}) Real {Real1}|{Real2}|{Real3} Operator (\+|=|\-|#|\*|\<|\>|\/|:=|\<\>|\&|\<=|\.|\>=|\,|\.\.|;|:|\(|\)|\[|\]|\{|\}|\^|\||~) String \"([^\"]|\\\")*\" %S NORMAL COMMENT %% {WhiteSpace} {} {Id} {struct id *temp; temp = enter(0,yytext,yyleng); if (LexDebug) { printf("%s : %s (%d)\n", yytext, ((temp->tokentype) ? "RESERVED" : "IDENTIFIER"), temp->count); } if (temp->tokentype) { return(temp->tokentype); } else { return(R_ID); } } {Real} {if (LexDebug) { printf("%s : %s\n", yytext, "REAL"); } } {DecInteger} {if (LexDebug) { printf("%s : %s\n", yytext, "INTEGER"); } yyint = atoi(yytext); return(R_INTEGER);} {HexInteger} {if (LexDebug) { printf("%s : %s\n", yytext, "(HEX)INTEGER"); } yyint = strtol(yytext+2,NULL,16); return(R_INTEGER);} {HexInteger2} {if (LexDebug) { printf("%s : %s\n", yytext, "(HEX)INTEGER"); } yyint = strtol(yytext,NULL,16); return(R_INTEGER);} {OctInteger} {if (LexDebug) { printf("%s : %s\n", yytext, "(OCT)INTEGER"); } yyint = strtol(yytext+2,NULL,8); return(R_INTEGER);} {OctInteger2} {if (LexDebug) { printf("%s : %s\n", yytext, "(OCT)INTEGER"); } yyint = strtol(yytext,NULL,8); return(R_INTEGER);} {CharInteger} {if (LexDebug) { printf("%s : %s\n", yytext, "(CHAR)INTEGER"); } if (yyleng>4) { yyint = strtol(yytext+2,NULL,8); } else { if (*(yytext+1)=='\\') { switch(*(yytext+2)) { case '0': yyint=0; break; case 'b': yyint = 0x8; break; case 'i': yyint = 0x9; break; case 'n': yyint = 0xa; break; case 'v': yyint = 0xb; break; case 'f': yyint = 0xc; break; case 'r': yyint = 0xd; break; default: yyint=(*yytext+2); break; } } else { yyint = *(yytext+1); } } return(R_INTEGER);} \[ {if (LexDebug) { printf("%s : %s\n", yytext, "LBRACKET"); } return(R_LBRACKET);} \] {if (LexDebug) { printf("%s : %s\n", yytext, "RBRACKET"); } return(R_RBRACKET);} {Operator} {if (LexDebug) { printf("%s : %s\n", yytext, "OPERATOR"); } } {String} {if (LexDebug) { printf("%s : %s\n", yytext, "STRING"); } return(R_STRING);} "/*" {CommentDepth++; BEGIN COMMENT;} "*/" {CommentDepth--;if(!CommentDepth) BEGIN NORMAL;} . { /* None of the above rules applicable, so it's a bad symbol. */ printf("Bad input char '%c' on line %d\n", yytext[0], yylineno); } .|\n {} /*Everything's AOK */ %% /*PROTO*/ LINK *HashTable[PRIME]; /* My little hash table */ /*START*/ /*BFUNC initparser() is used to place the Reserved Words into the hash table. It must be called before the parser command is called. EFUNC*/ void initparser() { char i,**sptr; BEGIN NORMAL; for(i=1,sptr=ReservedWords;**sptr!='\0';i++,sptr++) { /* Add Reserved Words */ enter(i,*sptr,strlen(*sptr)); /* Put reserved words in */ } /* hash table */ } #undef BEGIN #undef MakeStructure #include "globals.h" #include "stream.h" #include "tables.h" extern FRAME *CFrame; extern IMAGE *CImage; extern SCAN *CScan; extern int ErrorValue; /*BFUNC hashpjw() returns a hash value for a string input. EFUNC*/ static int hashpjw(s) char *s; { BEGIN("hashpjw"); char *p; unsigned int h=0,g; for(p=s;*p!=EOS;p++) /* Taken from Aho Sethi Ullman Compilers book. */ { h = (h << 4) + *p; if (g = h&0xf0000000) { h = h ^(g >> 24); h = h ^ g; } } return(h % PRIME); } /*BFUNC MakeLink() is used to construct a link object. The link is used for the hash table construct. EFUNC*/ static LINK *MakeLink(tokentype,str,len) int tokentype; char *str; int len; { BEGIN("MakeLink"); LINK *temp; if (!(temp = MakeStructure(LINK))) /* Make link */ { WHEREAMI(); printf("Cannot make a LINK.\n"); exit(ERROR_MEMORY); } if (!(temp->lid = MakeStructure(struct id))) /* Make id */ { printf("Cannot make an id.\n"); exit(ERROR_MEMORY); } temp->next = NULL; /* Set fields */ if (!(temp->lid->name =(char *)calloc(len+1,sizeof(char)))) { printf("Cannot make a string space for the link.\n"); exit(ERROR_MEMORY); } strcpy(temp->lid->name,str); /* Copy key */ temp->lid->tokentype = tokentype; temp->lid->count = 1; return(temp); } /*BFUNC enter() is used to enter a Reserved Word or ID into the hash table. EFUNC*/ static struct id *enter(tokentype,str,len) int tokentype; char *str; int len; { BEGIN("enter"); int hashnum; LINK *temp,*current; char *ptr; for(ptr=str;*ptr!='\0';ptr++) /* All capitals is fine */ { if ((*ptr>='a') && (*ptr<='z')) { *ptr = *ptr - ('a'-'A'); } } hashnum = hashpjw(str); /* Check if in hash table */ for(temp=NULL,current=HashTable[hashnum]; current!= NULL; current=current->next) { if (strcmp(str,current->lid->name) == 0) { temp=current; break; } } if (temp) /* Yes, found ID then return */ { temp->lid->count++; return(temp->lid); } else /* Else make our own ID and return that*/ { temp = MakeLink(tokentype,str,len); InsertLink(temp,HashTable[hashnum]); return(temp->lid); } } /*BFUNC getint() takes an integer from the input. EFUNC*/ static int getint() { BEGIN("getint"); int type; if ((type=yylex())!=R_INTEGER) { printf("Bad input, not integer, '%s' on line %d\n", yytext, yylineno); return(0); } return(yyint); } /*BFUNC getstr() gets a string from the input. It copies the string to temporary storage before it returns the pointer. EFUNC*/ static char *getstr() { BEGIN("getstr"); char *tmp,*ptr,*bptr; int i,accum,flag; if (yylex() != R_STRING) /* Check if string */ { printf("String expected.\n"); if (!(tmp=(char *) malloc(sizeof(char)))) { WHEREAMI(); printf("Cannot allocate for null string.\n"); exit(ERROR_MEMORY); } *tmp='\0'; return(tmp); } if (!(tmp=(char *)calloc(strlen(yytext)+1,sizeof(char)))) /* Make space */ { WHEREAMI(); printf("Cannot allocate %d string space.\n",yyleng); exit(ERROR_MEMORY); } for(bptr=yytext+1,ptr=tmp;*bptr!='"';bptr++,ptr++) /* Copy to string */ { if (*bptr=='\\') { bptr++; for(flag=0,accum=0,i=0;i<3;i++) /* Octal character lookahead */ { if ((*bptr>='0')&&(*bptr<='7')) { accum = (accum<<3)+(*bptr-'0'); bptr++; flag=1; } else { break; } } if (flag) { bptr--; *ptr=accum; } else /* Do conversions, if necessary */ { switch(*(bptr)) { case '0': *ptr = 0; break; case 'b': *ptr = 0x8; break; case 'i': *ptr = 0x9; break; case 'n': *ptr = 0xa; break; case 'v': *ptr = 0xb; break; case 'f': *ptr = 0xc; break; case 'r': *ptr = 0xd; break; default: *ptr=(*bptr); } } } else { *ptr = (*bptr); } } *ptr='\0'; return(tmp); } /*BFUNC parser() handles all of the parsing required for the Command Interpreter. It is basically a while statement with a very large case statement for every input. The Command Interpreter is essentially driven by the keywords. All unmatched values such as integers, strings, and brackets, are ignored. EFUNC*/ #define ARRAYBEGIN if (ntoken==R_LBRACKET)\ {\ arrayflag=1;\ ntoken=yylex();\ }\ if (ntoken!=R_INTEGER)\ {\ WHEREAMI();\ printf("Expected integer.\n");\ break;\ }\ while(1)\ { #define ARRAYEND if (arrayflag)\ {\ if ((ntoken=yylex())==R_RBRACKET) break;\ else if (ntoken!=R_INTEGER)\ {\ WHEREAMI();\ printf("Expected integer or right bracket.\n");\ break;\ }\ }\ else break;\ } void parser() { BEGIN("parser"); int i,dest,value,token,ntoken,arrayflag; int accum; int Start,End; int *ptr,*ptr2; while(token=yylex()) /* The code handling is simple enough. */ { /* just read the code and documentation */ ErrorValue=0; /* book... */ arrayflag=0; switch(token) { case R_ECHO: printf("%s\n",getstr()); break; case R_PRINTIMAGE: PrintImage(); break; case R_PRINTFRAME: PrintFrame(); break; case R_PRINTSCAN: PrintScan(); break; case R_COMPONENT: ntoken=yylex(); ARRAYBEGIN; dest = yyint; InBounds(dest,0,MAXIMUM_COMPONENTS-1,"Bad component reference"); if (ErrorValue) break; if (yylex()!=R_LBRACKET) { WHEREAMI(); printf("Expected left bracket.\n"); break; } CFrame->ComponentFileName[dest] = getstr(); value=getint(); InBounds(value,0,MAXIMUM_HORIZONTAL_FREQUENCY, "Bad horizontal frequency"); if (ErrorValue) break; CFrame->hf[dest]=value; value=getint(); InBounds(value,0,MAXIMUM_VERTICAL_FREQUENCY, "Bad vertical frequency"); if (ErrorValue) break; CFrame->vf[dest]=value; value=getint(); InBounds(value,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; CFrame->tq[dest]=value; CFrame->cn[CFrame->GlobalNumberComponents++]=dest;/*Know to use it*/ if (yylex()!=R_RBRACKET) { WHEREAMI(); printf("Expected right bracket.\n"); break; } ARRAYEND; break; case R_SCAN: CScan->NumberComponents=0; ntoken=yylex(); ARRAYBEGIN; if (CScan->NumberComponents>=MAXIMUM_SOURCES) { WHEREAMI(); printf("Exceeded number of sources per scan.\n"); break; } InBounds(yyint,0,MAXIMUM_COMPONENTS-1,"Bad component reference"); if (ErrorValue) break; for(i=0;iGlobalNumberComponents;i++) /* Check there */ if (CFrame->cn[i]==yyint) break; if (i==CFrame->GlobalNumberComponents) { WHEREAMI(); printf("Scan index not defined in frame yet.\n"); break; } CScan->ci[CScan->NumberComponents] = yyint; if (yylex()!=R_LBRACKET) { WHEREAMI(); printf("Expected left bracket.\n"); break; } value=getint(); InBounds(value,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; CScan->td[CScan->NumberComponents]=value; value=getint(); InBounds(value,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; CScan->ta[CScan->NumberComponents]=value; CScan->NumberComponents++; if (yylex()!=R_RBRACKET) { WHEREAMI(); printf("Expected right bracket.\n"); break; } ARRAYEND; break; case R_QUANTIZATION: ntoken=yylex(); ARRAYBEGIN; dest = yyint; InBounds(dest,0,MAXIMUM_DEVICES-1, "Bad quantization reference."); if (ErrorValue) break; ntoken=yylex(); if (ntoken==R_LUMINANCEDEFAULT) { CImage->QuantizationMatrices[dest]=LuminanceQuantization; break; } else if (ntoken==R_CHROMINANCEDEFAULT) { CImage->QuantizationMatrices[dest]=ChrominanceQuantization; break; } else if (ntoken!=R_LBRACKET) { WHEREAMI(); printf("Expected left bracket.\n"); break; } CImage->NumberQuantizationMatrices = MAX(CImage->NumberQuantizationMatrices,(dest+1)); if (!(ptr=(int *)calloc(64,sizeof(int)))) { WHEREAMI(); printf("Cannot allocate quantization matrix.\n"); exit(ERROR_MEMORY); } CImage->NumberQuantizationMatrices = MAX(CImage->NumberQuantizationMatrices,(dest+1)); CImage->QuantizationMatrices[dest]=ptr; for(i=0;i<64;i++) { ptr[i]=16; } for(i=0;i<65;i++,ptr++) /* One additional to force r-bracket */ { if ((ntoken=yylex())!=R_INTEGER) break; InBounds(yyint,1,65535,"Integer out of bounds"); if (ErrorValue) yyint=16; *ptr = yyint; } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected integer or right bracket.\n"); break; } ARRAYEND; break; case R_ACSEND: ntoken=yylex(); if (ntoken==R_EMPTY) { CScan->NumberACTablesSend = 0; break; } ARRAYBEGIN; if (CScan->NumberACTablesSend>=MAXIMUM_DEVICES) { WHEREAMI(); printf("AC Huffman queue full.\n"); break; } InBounds(yyint,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; CScan->sa[CScan->NumberACTablesSend++] = yyint; ARRAYEND; break; case R_DCSEND: ntoken=yylex(); if (ntoken==R_EMPTY) { CScan->NumberDCTablesSend = 0; break; } ARRAYBEGIN; if (CScan->NumberDCTablesSend>=MAXIMUM_DEVICES) { WHEREAMI(); printf("DC Huffman queue full.\n"); break; } InBounds(yyint,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; CScan->sd[CScan->NumberDCTablesSend++] = yyint; ARRAYEND; break; case R_QSEND: ntoken=yylex(); if (ntoken==R_EMPTY) { CScan->NumberQTablesSend = 0; break; } ARRAYBEGIN; if (CScan->NumberQTablesSend>=MAXIMUM_DEVICES) { WHEREAMI(); printf("Quantization queue full.\n"); break; } InBounds(yyint,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; CScan->sq[CScan->NumberQTablesSend++] = yyint; ARRAYEND; break; case R_STREAMNAME: CImage->StreamFileName = getstr(); break; case R_IMAGEWIDTH: value=getint(); InBounds(value,0,MAXIMUM_IMAGE_WIDTH,"Bad image width"); CFrame->GlobalWidth = value; break; case R_IMAGEHEIGHT: value=getint(); InBounds(value,0,MAXIMUM_IMAGE_HEIGHT,"Bad image height"); CFrame->GlobalHeight = value; break; case R_SCANDNL: ntoken=yylex(); switch(ntoken) { case R_AUTO: CFrame->InsertDnl= -2; break; case R_ENABLE: CFrame->InsertDnl= -1; break; case R_INTEGER: CFrame->InsertDnl = yyint; break; default: WHEREAMI(); printf("Expected integer.\n"); break; } break; case R_FRAMEWIDTH: ntoken=yylex(); ARRAYBEGIN; dest = yyint; InBounds(dest,0,MAXIMUM_COMPONENTS-1,"Bad component destination"); if (ErrorValue) break; value=getint(); InBounds(value,0,MAXIMUM_IMAGE_WIDTH,"Bad frame width"); if (ErrorValue) break; CFrame->Width[dest] = value; ARRAYEND; break; case R_FRAMEHEIGHT: ntoken=yylex(); ARRAYBEGIN; dest = yyint; InBounds(dest,0,MAXIMUM_COMPONENTS-1,"Bad component destination"); if (ErrorValue) break; value=getint(); InBounds(value,0,MAXIMUM_IMAGE_HEIGHT,"Bad frame height"); if (ErrorValue) break; CFrame->Height[dest] = value; ARRAYEND; break; case R_RESYNC: value = getint(); InBounds(value,0,MAXIMUM_RESYNC_INTERVAL,"Bad resync interval"); if (ErrorValue) break; CFrame->ResyncInterval = value; break; case R_BUFFER: value = getint(); InBounds(value,MINIMUM_BUFFERSIZE, MAXIMUM_BUFFERSIZE,"Bad buffersize"); if (ErrorValue) break; CFrame->BufferSize = value; break; case R_OPENSCAN: CheckValidity(); CheckBaseline(); ConfirmFileSize(); MakeIob(IOB_BLOCK,O_RDONLY,1); break; case R_CLOSESCAN: for(i=0;iNumberComponents;i++) /* Close all components */ { InstallIob(i); CloseIob(); } break; case R_OPENSTREAM: if (CImage->StreamFileName) { swopen(CImage->StreamFileName,0); /* Index 0 open */ } else { printf("StreamFileName: Null. Failed\n"); } break; case R_CLOSESTREAM: swclose(); break; case R_FREQUENCY: JpegFrequencyScan(); break; case R_WRITESPECIAL: ntoken=yylex(); ARRAYBEGIN; value = yyint; swbytealign(); bputc(0xFF); /* Marker */ bputc(value&0xff); Start = swtell(); bputw(0); if (yylex()!=R_LBRACKET) { WHEREAMI(); printf("Expected left bracket.\n"); End = swtell(); swseek(Start); bputw((End-Start) >> 3); swseek(End); break; } while((ntoken=yylex())==R_INTEGER) { bputc(yyint&0xff); } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected integer or right bracket.\n"); End = swtell(); swseek(Start); bputw((End-Start) >> 3); swseek(End); break; } End = swtell(); swseek(Start); bputw((End-Start) >> 3); swseek(End); ARRAYEND; break; case R_WRITEDIRECT: swbytealign(); if (yylex()!=R_LBRACKET) { WHEREAMI(); printf("Expected left bracket.\n"); break; } while((ntoken=yylex())==R_INTEGER) { bputc(yyint&0xff); } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected integer or right bracket.\n"); break; } break; case R_WRITESCAN: JpegEncodeScan(); break; case R_WRITEFRAME: MakeConsistentFrameSize(); /* Do it here when everything defined */ WriteSof(); break; case R_WRITESOI: WriteSoi(); break; case R_WRITEEOI: WriteEoi(); break; case R_WRITEQUANTIZATION: WriteDqt(); break; case R_WRITERESYNC: WriteDri(); break; case R_WRITEDNL: WriteDnl(); break; case R_WRITEHUFFMAN: WriteDht(); break; case R_ACCUSTOM: ntoken=yylex(); ARRAYBEGIN; dest = yyint; InBounds(dest,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; if (yylex()!=R_LBRACKET) { WHEREAMI(); printf("Expected left bracket.\n"); break; } MakeXhuff(); MakeEhuff(); if (!(ptr=(int *)calloc(257,sizeof(int)))) { WHEREAMI(); printf("Out of custom frequency space.\n"); exit(ERROR_MEMORY); } for(i=0;i<257;i++) { ptr[i]=0; } while((ntoken=yylex())==R_INTEGER) { InBounds(yyint,0,MAXIMUM_SOURCES-1,"Bad frequency reference"); if(ErrorValue) yyint=0; AddFrequency(ptr,CScan->ACFrequency[yyint]); } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected right bracket.\n"); break; } MakeHuffman(ptr); SetACHuffman(dest); CImage->NumberACTables = MAX(CImage->NumberACTables,(dest+1)); ARRAYEND; break; case R_DCCUSTOM: ntoken=yylex(); ARRAYBEGIN; dest = yyint; InBounds(dest,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; if (yylex()!=R_LBRACKET) { WHEREAMI(); printf("Expected left bracket.\n"); break; } MakeXhuff(); MakeEhuff(); if (!(ptr=(int *)calloc(257,sizeof(int)))) { WHEREAMI(); printf("Out of custom frequency space.\n"); exit(ERROR_MEMORY); } for(i=0;i<257;i++) { ptr[i]=0; } while((ntoken=yylex())==R_INTEGER) { InBounds(yyint,0,MAXIMUM_SOURCES-1,"Bad frequency reference"); if(ErrorValue) yyint=0; AddFrequency(ptr,CScan->DCFrequency[yyint]); } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected right bracket.\n"); break; } MakeHuffman(ptr); SetDCHuffman(dest); CImage->NumberDCTables = MAX(CImage->NumberDCTables,(dest+1)); ARRAYEND; break; case R_ACSPEC: ntoken=yylex(); ARRAYBEGIN; dest = yyint; InBounds(dest,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; MakeXhuff(); MakeEhuff(); if ((ntoken=yylex())==R_LBRACKET) { if (!(ptr=(int *)calloc(38,sizeof(int)))) /* Get bits */ { WHEREAMI(); printf("Out of custom bits space.\n"); exit(ERROR_MEMORY); } for(i=0;i<32;i++) { ptr[i]=0; } for(accum=0,i=0;i<17;i++) /* First index is bitlength of 1. */ { /* One additional to force r-bracket. */ ntoken=yylex(); if (ntoken==R_INTEGER) { accum+=yyint; ptr[i]=yyint; } else break; } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected integer or right bracket.\n"); break; } if (yylex()!=R_LBRACKET) /* Get values */ { WHEREAMI(); printf("Expected left bracket.\n"); break; } if (!(ptr2=(int *)calloc(257,sizeof(int)))) { WHEREAMI(); printf("Out of custom Huffman value space.\n"); exit(ERROR_MEMORY); } for(i=0;i<257;i++) { ptr2[i]=0; } for(i=0;i<257;i++) /* One additinal to force r-bracket */ { ntoken=yylex(); if (ntoken==R_INTEGER) { ptr2[i]=yyint; } else break; } if (i!=accum) { WHEREAMI(); printf("Number of bitlengths != number of values."); } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected integer or right bracket.\n"); break; } SpecifiedHuffman(ptr,ptr2); } else if (ntoken==R_CHROMINANCEDEFAULT) { SpecifiedHuffman(ChrominanceACBits,ChrominanceACValues); } else if (ntoken==R_LUMINANCEDEFAULT) { SpecifiedHuffman(LuminanceACBits,LuminanceACValues); } else { WHEREAMI(); printf("Expected left bracket or ACDEFAULT.\n"); break; } SetACHuffman(dest); CImage->NumberACTables = MAX(CImage->NumberACTables,(dest+1)); ARRAYEND; break; case R_DCSPEC: ntoken=yylex(); ARRAYBEGIN; dest = yyint; InBounds(dest,0,MAXIMUM_DEVICES-1,"Bad device reference"); if (ErrorValue) break; MakeXhuff(); MakeEhuff(); if ((ntoken=yylex())==R_LBRACKET) { if (!(ptr=(int *)calloc(38,sizeof(int)))) /* Get bits */ { WHEREAMI(); printf("Out of custom bits space.\n"); exit(ERROR_MEMORY); } for(i=0;i<32;i++) { ptr[i]=0; } for(accum=0,i=0;i<17;i++) /* First index is bitlength of 1. */ { /* 0-16 to force right bracket. */ ntoken=yylex(); if (ntoken==R_INTEGER) { accum+=yyint; ptr[i]=yyint; } else break; } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected integer or right bracket.\n"); break; } if (yylex()!=R_LBRACKET) /* Get values */ { WHEREAMI(); printf("Expected left bracket.\n"); break; } if (!(ptr2=(int *)calloc(257,sizeof(int)))) { WHEREAMI(); printf("Out of custom Huffman value space.\n"); exit(ERROR_MEMORY); } for(i=0;i<257;i++) { ptr2[i]=0; } for(i=0;i<257;i++) /*One additional to force r-bracket.*/ { ntoken=yylex(); if (ntoken==R_INTEGER) { ptr2[i]=yyint; } else break; } if (i!=accum) { WHEREAMI(); printf("Number of bitlengths != number of values."); } if (ntoken!=R_RBRACKET) { WHEREAMI(); printf("Expected integer or right bracket.\n"); break; } SpecifiedHuffman(ptr,ptr2); } else if (ntoken==R_CHROMINANCEDEFAULT) { SpecifiedHuffman(ChrominanceDCBits,ChrominanceDCValues); } else if (ntoken==R_LUMINANCEDEFAULT) { SpecifiedHuffman(LuminanceDCBits,LuminanceDCValues); } else { WHEREAMI(); printf("Expected left bracket or DCDEFAULT.\n"); break; } SetDCHuffman(dest); CImage->NumberDCTables = MAX(CImage->NumberDCTables,(dest+1)); ARRAYEND; break; } } } /*NOPROTO*/ /*END*/ pvrg-jpeg-1.2.1/nonint.jpg0000644000175000017500000000555205725223007014776 0ustar naolivnaoliv   (1#%(:3=<9387@H\N@DWE78PmQW_bghg>Mqypdx\egc//cB8BBccccccccccccccccccccccccccccccccccccccccccccccccc! }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz?gp=jܺwvpLP];vqD@l3DHmw5ϼL(`v *;ȠҺ4 N*jUFS=^FTK ul-YX9Q/;,:Ulg8cTL{EM/RiYwv, ʵ,2D S@ZşRj b\ Jkeu?>&nCAqH| x_zv6?4jfԐ2sGֲgG *(TU!on<55kb[Օr#5˸a g\5,A6[a48,@zkV JK: 񩕙>US7^#+n79Pk=`%7v8Zt1;:zUyYf\*kӳYcK]3 ֐2p8aXAU5T z/El`"?Qϩ1 r{:j=Rb<- .zh!5+A e;!8LlFHD5J$eN+ jըTN;Xe;gdonªZJ>)\j`Ry n0Ê,)*Úθ QyoqD@ԓUt_5' zd#yeݻ hF F;SWFr-*d9#< QH7>x5iXSZ8^RRP:4=k9@Y'V J2 |ݳ֪gbvc+!ZJN`vPё޹LO,H3ZidgZbO7^jUWjc2>;pˎª#9^/ cԊEx.F?YnKnsjkXc QcPb&LGeVXce TaS>S_cY"oXMҒxUI*j}=B8Eܾu@VGÖ֭7*άp"BVE#RUYPD/9YَbZ{痌`gҢPT0*'#+uNx>,@yss8Ƨ1g8QWHp f]ZCUVdmn*.WW5]jAF{IF1HzFB1ʯOp*0ǐ:|U{7jYbRGB conversion. Some printers (non-laserwriters) have been unable to cope with the doc.ps files, specifically problems occurred in the postscript include files. For some reason, Apple laserwriters and ghostscript do not seem to be afflicted by the above problem. We have found a change in the dvi2ps postscript header that seems to fix this problem for Sun newsprint (and probably other) printers as well. If this still is a problem, the raw tex and .ps files are available in the file JPEGDOCv1.1.tar.Z. Caution: the special scaling command has different relative scales for different dvi2ps, dvips programs - can be a factor of 100 off depending on the version of the header file. 6/14/93 Changed a few things in the documentation to reflect the YCbCr terminology. Other than that, essentially the same. Added some declaration for SYSTEM V libraries and libraries without ftruncate(). Version(1.2) 7/28/93 Changed the lossless predictor encoding functions so that 16 bit accuracy is attained. Some problems occurred with improper modulo arithmetic when full 16 bits were used with certain predictors. The changes were in codec.c Lossless*() and a couple of lines in jpeg.c which used &0xffff to properly trim the values. pvrg-jpeg-1.2.1/marker.h0000644000175000017500000000336705725222775014436 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ /* ************************************************************ marker.h Some basic definitions of commonly occurring markers. ************************************************************ */ #ifndef MARKER_DONE #define MARKER_DONE #define END_QUANTIZATION_TABLE 0xFF #define END_CODE_TABLE 0xFF #define MARKER_MARKER 0xff #define MARKER_FIL 0xff #define MARKER_SOI 0xd8 #define MARKER_EOI 0xd9 #define MARKER_SOS 0xda #define MARKER_DQT 0xdb #define MARKER_DNL 0xdc #define MARKER_DRI 0xdd #define MARKER_DHP 0xde #define MARKER_EXP 0xdf #define MARKER_DHT 0xc4 #define MARKER_SOF 0xc0 #define MARKER_RSC 0xd0 #define MARKER_APP 0xe0 #define MARKER_JPG 0xf0 #define MARKER_RSC_MASK 0xf8 #endif pvrg-jpeg-1.2.1/csize.h0000644000175000017500000000414305725222774014262 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ /* ************************************************************ csize.h This file contains one array which has in by value index, the "size" of the value in bits. ************************************************************ */ #ifndef CSIZE_DONE #define CSIZE_DONE static int csize[] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; #endif pvrg-jpeg-1.2.1/PORTABILITY0000644000175000017500000000055505725223012014506 0ustar naolivnaoliv For PC's the portability problem may be in the shift-division in the DCT's and the UNIX calls open, read, ftruncate, etc. For modification of the lexer.l file: Lex does not accept comments in the heading, unfortunately, the automatic header program puts that at the top. Put the first comment (pvrg disclaimer, etc.) into the %{ %} body and all should be fine. pvrg-jpeg-1.2.1/dct.h0000644000175000017500000001037405725222774013722 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ /* ************************************************************ dct.h This file contains the basic DCT matrix values for the reference DCT transform. It doesn't matter if it is slow because it is rarely used. A butterfly would be much faster. ************************************************************ */ #ifndef DCT_DONE #define DCT_DONE #define DC_QUARTER 1.41421356237309504880 #define DC_THREE_EIGHTHS 0.76536686473017954348 #define DC_ONE_EIGHTH 1.84775906502257351226 /* Bitshifted Twelve */ #define IC_QUARTER 2896 #define IC_THREE_EIGHTHS 1567 #define IC_ONE_EIGHTH 3784 double DctMatrix[] = { 0.3535533905932737, 0.3535533905932737, 0.3535533905932737, 0.3535533905932737, 0.3535533905932737, 0.3535533905932737, 0.3535533905932737, 0.3535533905932737, 0.4903926402016152, 0.4157348061512727, 0.2777851165098011, 0.0975451610080642, -0.0975451610080641, -0.2777851165098010, -0.4157348061512727, -0.4903926402016152, 0.4619397662556434, 0.1913417161825449, -0.1913417161825449, -0.4619397662556434, -0.4619397662556434, -0.1913417161825452, 0.1913417161825450, 0.4619397662556432, 0.4157348061512727, -0.0975451610080641, -0.4903926402016152, -0.2777851165098011, 0.2777851165098009, 0.4903926402016153, 0.0975451610080640, -0.4157348061512721, 0.3535533905932738, -0.3535533905932737, -0.3535533905932738, 0.3535533905932737, 0.3535533905932738, -0.3535533905932733, -0.3535533905932736, 0.3535533905932733, 0.2777851165098011, -0.4903926402016152, 0.0975451610080641, 0.4157348061512728, -0.4157348061512726, -0.0975451610080649, 0.4903926402016152, -0.2777851165098008, 0.1913417161825449, -0.4619397662556434, 0.4619397662556432, -0.1913417161825449, -0.1913417161825453, 0.4619397662556437, -0.4619397662556435, 0.1913417161825431, 0.0975451610080642, -0.2777851165098011, 0.4157348061512728, -0.4903926402016153, 0.4903926402016152, -0.4157348061512720, 0.2777851165098022, -0.0975451610080625}; static double IDctMatrix[] = { 0.3535533905932737, 0.4903926402016152, 0.4619397662556434, 0.4157348061512727, 0.3535533905932738, 0.2777851165098011, 0.1913417161825449, 0.0975451610080642, 0.3535533905932737, 0.4157348061512727, 0.1913417161825449, -0.0975451610080641, -0.3535533905932737, -0.4903926402016152, -0.4619397662556434, -0.2777851165098011, 0.3535533905932737, 0.2777851165098011, -0.1913417161825449, -0.4903926402016152, -0.3535533905932738, 0.0975451610080641, 0.4619397662556432, 0.4157348061512728, 0.3535533905932737, 0.0975451610080642, -0.4619397662556434, -0.2777851165098011, 0.3535533905932737, 0.4157348061512728, -0.1913417161825449, -0.4903926402016153, 0.3535533905932737, -0.0975451610080641, -0.4619397662556434, 0.2777851165098009, 0.3535533905932738, -0.4157348061512726, -0.1913417161825453, 0.4903926402016152, 0.3535533905932737, -0.2777851165098010, -0.1913417161825452, 0.4903926402016153, -0.3535533905932733, -0.0975451610080649, 0.4619397662556437, -0.4157348061512720, 0.3535533905932737, -0.4157348061512727, 0.1913417161825450, 0.0975451610080640, -0.3535533905932736, 0.4903926402016152, -0.4619397662556435, 0.2777851165098022, 0.3535533905932737, -0.4903926402016152, 0.4619397662556432, -0.4157348061512721, 0.3535533905932733, -0.2777851165098008, 0.1913417161825431, -0.0975451610080625}; #endif pvrg-jpeg-1.2.1/huffman.c0000644000175000017500000004064205725223002014551 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ /* ************************************************************ huffman.c This file represents the core Huffman routines, most of them implemented with the JPEG reference. These routines are not very fast and can be improved, but comprise very little of software run-time. ************************************************************ */ /*LABEL huffman.c */ /* Include files */ #include "globals.h" #include "stream.h" /*PUBLIC*/ static void CodeSize(); static void CountBits(); static void AdjustBits(); static void SortInput(); static void SizeTable(); static void CodeTable(); static void OrderCodes(); static void DecoderTables(); extern void MakeHuffman(); extern void SpecifiedHuffman(); extern void MakeDecoderHuffman(); extern void ReadHuffman(); extern void WriteHuffman(); extern int DecodeHuffman(); extern void EncodeHuffman(); extern void MakeXhuff(); extern void MakeEhuff(); extern void MakeDhuff(); extern void UseACHuffman(); extern void UseDCHuffman(); extern void SetACHuffman(); extern void SetDCHuffman(); extern void PrintHuffman(); extern void PrintTable(); /*PRIVATE*/ extern int Loud; extern int ErrorValue; extern IMAGE *CImage; extern FRAME *CFrame; extern SCAN *CScan; static int frequency[257]; static int codesize[257]; static int huffsize[257]; static int huffcode[257]; static int lastp; static int others[257]; static XHUFF *Xhuff=NULL; static DHUFF *Dhuff=NULL; static EHUFF *Ehuff=NULL; #define fgetb megetb #define fputv meputv #define ClearFrequency() \ {int *cfip; for(cfip=frequency;cfipbits;cbipbits+36;*(cbip++)=0);} #define ClearEcodes() \ {int *cip,*dip;dip=Ehuff->ehufsi;cip=Ehuff->ehufco;\ while(cip=codesize;csptr--) { if (*csptr) { Xhuff->bits[*csptr]++; } } } /*BFUNC AdjustBits() is used to trim the Huffman code tree into 16 bit code words only. EFUNC*/ static void AdjustBits() { BEGIN("AdjustBits"); int i,j; i=32; while(1) { if (Xhuff->bits[i]>0) { j = i-1; while(!Xhuff->bits[--j]); /* Change from JPEG Manual */ Xhuff->bits[i] -= 2; /* Remove 2 of the longest hufco */ Xhuff->bits[i-1]++; /* Add one hufco to its prefix */ Xhuff->bits[j]--; /* Remove hufco from next length */ Xhuff->bits[j+1] += 2; /* to be prefix to one hufco */ } /* from j term and the one */ /* hufco from the i (longest) term.*/ else if (--i==16) { break; } } while(!Xhuff->bits[i]) /* If fortunate enough not to use */ { /* any 16 bit codes, then find out */ i--; /* where last codes are. */ } Xhuff->bits[i]--; /* Get rid of the extra code that generated 0xffff */ } /*BFUNC SortInput() assembles the codes in increasing order with code length. Since we know the bit-lengths in increasing order, they will correspond to the codes with decreasing frequency. This sort is O(mn),), not the greatest. EFUNC*/ static void SortInput() { BEGIN("SortInput"); int i,j,p; for(p=0,i=1;i<33;i++) /* Designate a length in i. */ { for(j=0;j<256;j++) /* Find all codes with a given length. */ { if (codesize[j]==i) { Xhuff->huffval[p++] = j; /* Add that value to be associated */ } /* with the next largest code. */ } } } /*BFUNC SizeTable() is used to associate a size with the code in increasing length. For example, it would be 44556677... in huffsize[]. Lastp is the number of codes used. EFUNC*/ static void SizeTable() { BEGIN("SizeTable"); int i,j,p; for(p=0,i=1;i<17;i++) { for(j=1;j<=Xhuff->bits[i];j++) { huffsize[p++] = i; } } huffsize[p] = 0; lastp = p; } /*BFUNC CodeTable() is used to generate the codes once the hufsizes are known. EFUNC*/ static void CodeTable() { BEGIN("CodeTable"); int p,code,size; p=0; code=0; size = huffsize[0]; while(1) { do { huffcode[p++] = code++; } while((huffsize[p]==size)&&(p<257)); /* Overflow Detection */ if (!huffsize[p]) /* All finished. */ { break; } do /* Shift next code to expand prefix. */ { code <<= 1; size++; } while(huffsize[p] != size); } } /*BFUNC OrderCodes() reorders from the monotonically increasing Huffman-code words into an array which is indexed on the actual value represented by the codes. This converts the Xhuff structure into an Ehuff structure. EFUNC*/ static void OrderCodes() { BEGIN("OrderCodes"); int index,p; for(p=0;phuffval[p]; Ehuff->ehufco[index] = huffcode[p]; Ehuff->ehufsi[index] = huffsize[p]; } } /*BFUNC DecoderTables() takes the Xhuff and converts it to a form suitable for the JPEG suggested decoder. This is not the fastest method but it is the reference method. EFUNC*/ static void DecoderTables() { BEGIN("DecoderTables"); int l,p; for(Dhuff->ml=1,p=0,l=1;l<=16;l++) { if (Xhuff->bits[l]==0) { Dhuff->maxcode[l] = -1; /* Watch out JPEG is wrong here */ } /* We use -1 to indicate skipping. */ else { Dhuff->valptr[l]=p; Dhuff->mincode[l]=huffcode[p]; p+=Xhuff->bits[l]-1; Dhuff->maxcode[l]=huffcode[p]; Dhuff->ml = l; p++; } } Dhuff->maxcode[Dhuff->ml]++; } /*BFUNC MakeHuffman() is used to create the Huffman table from the frequency passed into it. EFUNC*/ void MakeHuffman(freq) int *freq; { BEGIN("MakeHuffman"); int *ptr; for(ptr=frequency;ptrbits[i+1] = bts[i]; /* Shift offset for internal specs.*/ } for(i=0;ihuffval[i] = hvls[i]; } SizeTable(); /*From Xhuff to Ehuff */ CodeTable(); OrderCodes(); } /*BFUNC MakeDecoderHuffman() creates the decoder tables from the Xhuff structure. EFUNC*/ void MakeDecoderHuffman() { BEGIN("MakeDecoderHuffman"); SizeTable(); CodeTable(); DecoderTables(); } /*BFUNC ReadHuffman() reads in a Huffman structure from the currently open stream. EFUNC*/ void ReadHuffman() { BEGIN("ReadHuffman"); int i,accum; for(accum=0,i=1;i<=16;i++) { Xhuff->bits[i]=bgetc(); accum += Xhuff->bits[i]; } if (Loud > NOISY) { printf("Huffman Read In:\n"); printf("NUMBER OF CODES %d\n",accum); } for(i=0;ihuffval[i] = bgetc(); } SizeTable(); CodeTable(); DecoderTables(); if (Loud > NOISY) { printf("Huffman Read In:\n"); for(i=1;i<=16;i++) { printf("DHUFF->MAXCODE DHUFF->MINCODE DHUFF->VALPTR %d %d %d\n", Dhuff->maxcode[i],Dhuff->mincode[i],Dhuff->valptr[i]); } } } /*BFUNC WriteHuffman() writes the Huffman out to the stream. This Huffman structure is written from the Xhuff structure. EFUNC*/ void WriteHuffman() { BEGIN("WriteHuffman"); int i,accum; if (Xhuff) { for(accum=0,i=1;i<=16;i++) { bputc(Xhuff->bits[i]); accum += Xhuff->bits[i]; } for(i=0;ihuffval[i]); } } else { WHEREAMI(); printf("Null Huffman table found.\n"); } } /*BFUNC DecodeHuffman() returns the value decoded from the Huffman stream. The Dhuff must be loaded before this function be called. EFUNC*/ int DecodeHuffman() { BEGIN("DecodeHuffman"); int code,l,p; if (!Dhuff) { WHEREAMI(); printf("Unreferenced decoder Huffman table!\n"); exit(ERROR_HUFFMAN_READ); } code = fgetb(); for(l=1;code>Dhuff->maxcode[l];l++) { if (Loud > WHISPER) { WHEREAMI(); printf("CurrentCode=%d Length=%d Dhuff->Maxcode=%d\n", code,l,Dhuff->maxcode[l]); } code= (code<<1)+fgetb(); } if(codemaxcode[Dhuff->ml]) { p = Dhuff->valptr[l] + code - Dhuff->mincode[l]; if (Loud > WHISPER) { WHEREAMI(); printf("HuffmanDecoded code: %d value: %d\n",p,Xhuff->huffval[p]); } return(Xhuff->huffval[p]); } else { WHEREAMI(); printf("Huffman read error: l=%d code=%d\n"); Resync(); ErrorValue = ERROR_HUFFMAN_READ; return(0); } } /*BFUNC EncodeHuffman() places the Huffman code for the value onto the stream. EFUNC*/ void EncodeHuffman(value) int value; { BEGIN("EncodeHuffman"); if (Loud > WHISPER) { WHEREAMI(); printf("HUFFMAN_OUTPUT value=%d Ehuff->ehufsi=%d Ehuff->ehufco=%d\n", value,Ehuff->ehufsi[value],Ehuff->ehufco[value]); } if (!Ehuff) { WHEREAMI(); printf("Encoding with Null Huffman table.\n"); exit(ERROR_HUFFMAN_ENCODE); } if (Ehuff->ehufsi[value]) { fputv(Ehuff->ehufsi[value],Ehuff->ehufco[value]); } else { WHEREAMI(); printf("Null Code for [%d] Encountered:\n",value); printf("*** Dumping Huffman Table ***\n"); PrintHuffman(); printf("***\n"); ErrorValue = ERROR_HUFFMAN_ENCODE; exit(ErrorValue); } } /*BFUNC MakeXhuff() creates a Huffman structure and puts it into the current slot. EFUNC*/ void MakeXhuff() { BEGIN("MakeXhuff"); if (!(Xhuff = MakeStructure(XHUFF))) { WHEREAMI(); printf("Cannot allocate memory for Xhuff structure.\n"); exit(ERROR_MEMORY); } } /*BFUNC MakeEhuff() creates a Huffman structure and puts it into the current slot. EFUNC*/ void MakeEhuff() { BEGIN("MakeEhuff"); if (!(Ehuff = MakeStructure(EHUFF))) { WHEREAMI(); printf("Cannot allocate memory for Ehuff structure.\n"); exit(ERROR_MEMORY); } } /*BFUNC MakeDhuff() creates a Huffman structure and puts it into the current slot. EFUNC*/ void MakeDhuff() { BEGIN("MakeDhuff"); if (!(Dhuff = MakeStructure(DHUFF))) { WHEREAMI(); printf("Cannot allocate memory for Dhuff structure.\n"); exit(ERROR_MEMORY); } } /*BFUNC UseACHuffman() installs the appropriate Huffman structure from the CImage structure. EFUNC*/ void UseACHuffman(index) int index; { BEGIN("UseACHuffman"); Xhuff = CImage->ACXhuff[index]; Dhuff = CImage->ACDhuff[index]; Ehuff = CImage->ACEhuff[index]; if (!Dhuff && !Ehuff) { WHEREAMI(); printf("Reference to nonexistent table %d.\n",index); } } /*BFUNC UseDCHuffman() installs the DC Huffman structure from the CImage structure. EFUNC*/ void UseDCHuffman(index) int index; { BEGIN("UseDCHuffman"); Xhuff = CImage->DCXhuff[index]; Dhuff = CImage->DCDhuff[index]; Ehuff = CImage->DCEhuff[index]; if (!Dhuff && !Ehuff) { WHEREAMI(); printf("Reference to nonexistent table %d.\n",index); } } /*BFUNC SetACHuffman() sets the CImage structure contents to be the current Huffman structure. EFUNC*/ void SetACHuffman(index) int index; { BEGIN("SetACHuffman"); CImage->ACXhuff[index] = Xhuff; CImage->ACDhuff[index] = Dhuff; CImage->ACEhuff[index] = Ehuff; } /*BFUNC SetDCHuffman() sets the CImage structure contents to be the current Huffman structure. EFUNC*/ void SetDCHuffman(index) int index; { BEGIN("SetDCHuffman"); CImage->DCXhuff[index] = Xhuff; CImage->DCDhuff[index] = Dhuff; CImage->DCEhuff[index] = Ehuff; } /*BFUNC PrintHuffman() prints out the current Huffman structure. EFUNC*/ void PrintHuffman() { BEGIN("PrintHuffman"); int i; if (Xhuff) { printf("Xhuff ID: %x\n",Xhuff); printf("Bits: [length:number]\n"); for(i=1;i<9;i++) { printf("[%d:%d]",i,Xhuff->bits[i]); } printf("\n"); for(i=9;i<17;i++) { printf("[%d:%d]",i,Xhuff->bits[i]); } printf("\n"); printf("Huffval:\n"); PrintTable(Xhuff->huffval); } if (Ehuff) { printf("Ehuff ID: %x\n",Ehuff); printf("Ehufco:\n"); PrintTable(Ehuff->ehufco); printf("Ehufsi:\n"); PrintTable(Ehuff->ehufsi); } if (Dhuff) { printf("Dhuff ID: %x\n",Dhuff); printf("MaxLength: %d\n",Dhuff->ml); printf("[index:MaxCode:MinCode:ValPtr]\n"); for(i=1;i<5;i++) { printf("[%d:%2x:%2x:%2x]", i, Dhuff->maxcode[i], Dhuff->mincode[i], Dhuff->valptr[i]); } printf("\n"); for(i=5;i<9;i++) { printf("[%d:%2x:%2x:%2x]", i, Dhuff->maxcode[i], Dhuff->mincode[i], Dhuff->valptr[i]); } printf("\n"); for(i=9;i<13;i++) { printf("[%d:%2x:%2x:%2x]", i, Dhuff->maxcode[i], Dhuff->mincode[i], Dhuff->valptr[i]); } printf("\n"); for(i=13;i<17;i++) { printf("[%d:%2x:%2x:%2x]", i, Dhuff->maxcode[i], Dhuff->mincode[i], Dhuff->valptr[i]); } printf("\n"); } } /*BFUNC PrintTable() prints out a table to the screen. The table is assumed to be a 16x16 matrix represented by a single integer pointer. EFUNC*/ void PrintTable(table) int *table; { BEGIN("PrintTable"); int i,j; for(i=0;i<16;i++) { for(j=0;j<16;j++) { printf("%2x ",*(table++)); } printf("\n"); } } /*END*/ pvrg-jpeg-1.2.1/prototypes.h0000644000175000017500000001176405725222776015406 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ /* ************************************************************ prototypes.h This file contains the functional prototypes for typechecking. ************************************************************ */ #ifndef PROTOTYPES_DONE #define PROTOTYPES_DONE /* jpeg.c */ extern void PrintImage(); extern void PrintFrame(); extern void PrintScan(); extern void MakeImage(); extern void MakeFrame(); extern void MakeScanFrequency(); extern void MakeScan(); extern void MakeConsistentFileNames(); extern void CheckValidity(); extern int CheckBaseline(); extern void ConfirmFileSize(); extern void JpegQuantizationFrame(); extern void JpegDefaultHuffmanScan(); extern void JpegFrequencyScan(); extern void JpegCustomScan(); extern void JpegEncodeScan(); extern void JpegLosslessFrequencyScan(); extern void JpegLosslessEncodeScan(); /* codec.c */ extern void FrequencyAC(); extern void EncodeAC(); extern void DecodeAC(); extern int DecodeDC(); extern void FrequencyDC(); extern void EncodeDC(); extern void ResetCodec(); extern void ClearFrameFrequency(); extern void AddFrequency(); extern void InstallFrequency(); extern void InstallPrediction(); extern void PrintACEhuff(); extern void PrintDCEhuff(); extern int SizeACEhuff(); extern int SizeDCEhuff(); extern int LosslessDecodeDC(); extern void LosslessFrequencyDC(); extern void LosslessEncodeDC(); /* huffman.c */ extern void MakeHuffman(); extern void SpecifiedHuffman(); extern void MakeDecoderHuffman(); extern void ReadHuffman(); extern void WriteHuffman(); extern int DecodeHuffman(); extern void EncodeHuffman(); extern void MakeXhuff(); extern void MakeEhuff(); extern void MakeDhuff(); extern void UseACHuffman(); extern void UseDCHuffman(); extern void SetACHuffman(); extern void SetDCHuffman(); extern void PrintHuffman(); extern void PrintTable(); /* io.c */ extern void ReadBlock(); extern void WriteBlock(); extern void ResizeIob(); extern void RewindIob(); extern void FlushIob(); extern void SeekEndIob(); extern void CloseIob(); extern void MakeIob(); extern void PrintIob(); extern int NumberBlocksIob(); extern int NumberBlockMDUIob(); extern void InstallIob(); extern void TerminateFile(); extern int NumberLineMDUIob(); extern void ReadLine(); extern void ReadPreambleLine(); extern void WriteLine(); extern int LineNumberMDUWideIob(); extern int LineNumberMDUHighIob(); extern void LineResetBuffers(); /* chendct.c */ extern void ChenDct(); extern void ChenIDct(); /* leedct.c */ extern void LeeIDct(); extern void LeeDct(); /* lexer.c */ extern void initparser(); extern void parser(); /* marker.c */ extern void WriteSoi(); extern void WriteEoi(); extern void WriteJfif(); extern void WriteSof(); extern void WriteDri(); extern void WriteDqt(); extern void WriteSos(); extern void WriteDht(); extern void ReadSof(); extern void ReadDqt(); extern void ReadDht(); extern void ReadDri(); extern void ReadDnl(); extern void ReadSos(); extern void CheckScan(); extern void MakeConsistentFrameSize(); /* stream.c */ extern void initstream(); extern void pushstream(); extern void popstream(); extern void bpushc(); extern int bgetc(); extern void bputc(); extern void mropen(); extern void mrclose(); extern void mwopen(); extern void swbytealign(); extern void mwclose(); extern long mwtell(); extern long mrtell(); extern void mwseek(); extern void mrseek(); extern int megetb(); extern void meputv(); extern int megetv(); extern int DoMarker(); extern int ScreenMarker(); extern void Resync(); extern void WriteResync(); extern int ReadResync(); extern int ScreenAllMarker(); extern int DoAllMarker(); /* transform.c */ extern void ReferenceDct(); extern void ReferenceIDct(); extern void TransposeMatrix(); extern void Quantize(); extern void IQuantize(); extern void PreshiftDctMatrix(); extern void PostshiftIDctMatrix(); extern void BoundDctMatrix(); extern void BoundIDctMatrix(); extern void ZigzagMatrix(); extern void IZigzagMatrix(); extern int *ScaleMatrix(); extern void PrintMatrix(); extern void ClearMatrix(); #endif pvrg-jpeg-1.2.1/stream.h0000644000175000017500000000301405725222777014437 0ustar naolivnaoliv/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ /* ************************************************************ stream.h This file contains simple macros for better access to the direct stream. ************************************************************ */ #ifndef STREAM_DONE #define STREAM_DONE #define bputw(word) {bputc((word>>8)&0xff); bputc(word&0xff);} #define bputn(nybbleh,nybblel) {bputc(((nybbleh&0x0f)<<4)|(nybblel&0x0f));} #define hinyb(val) ((val>>4)&0x0f) #define lonyb(val) (val & 0x0f) #endif pvrg-jpeg-1.2.1/test.q0000644000175000017500000000112105725223007014114 0ustar naolivnaoliv/* This program sends a 128x128 file blkint.jpg.1 to the compressed file output.jpg using a predefined quantization. */ STREAMNAME "output.jpg" COMPONENT [0 ["blkint.jpg.1" 1 1 0]] SCAN [0 [0 0]] IMAGEWIDTH 128 IMAGEHEIGHT 128 QUANTIZATION 0 [ 9 9 9 7 7 7 7 7 9 7 7 7 7 7 7 9 7 7 7 7 7 7 9 9 7 7 7 7 7 9 9 15 5 7 7 7 7 9 15 17 7 7 7 7 11 13 17 23 7 7 7 11 13 19 23 27 7 7 13 13 21 21 27 23 ] QSEND 0 OPENSTREAM WRITESOI WRITEFRAME OPENSCAN FREQUENCY ACSPEC 0 LUMINANCEDEFAULT DCSPEC 0 LUMINANCEDEFAULT ACSEND 0 DCSEND 0 WRITEHUFFMAN WRITEQUANTIZATION WRITESCAN CLOSESCAN WRITEEOI CLOSESTREAM pvrg-jpeg-1.2.1/test.huff0000644000175000017500000000731505725223007014617 0ustar naolivnaoliv/* This program sends over a set huffman table with 10 MDU resynchronization for a 128x128 file blkint.jpg.1 to the compressed file output.jpg. */ STREAMNAME "output.jpg" COMPONENT [0 ["blkint.jpg.1" 1 1 0]] SCAN [0 [0 0]] IMAGEWIDTH 128 IMAGEHEIGHT 128 RESYNC 10 QSEND 0 SCANDNL AUTO OPENSTREAM WRITESOI WRITERESYNC WRITEFRAME OPENSCAN FREQUENCY DCSPEC [0 [0 1 5 1 1 1 1 1 1] [0 1 2 3 4 5 6 7 8 9 0xa 0xb] 1 [0 3 1 1 1 1 1 1 1 1 1] [0 1 2 3 4 5 6 7 8 9 0xa 0xb]] ACSPEC 0 [0x00 0x02 0x01 0x03 0x03 0x02 0x04 0x03 0x05 0x05 0x04 0x04 0x00 0x00 0x01 0x7d] [0x01 0x02 0x03 0x00 0x04 0x11 0x05 0x12 0x21 0x31 0x41 0x06 0x13 0x51 0x61 0x07 0x22 0x71 0x14 0x32 0x81 0x91 0xa1 0x08 0x23 0x42 0xb1 0xc1 0x15 0x52 0xd1 0xf0 0x24 0x33 0x62 0x72 0x82 0x09 0x0a 0x16 0x17 0x18 0x19 0x1a 0x25 0x26 0x27 0x28 0x29 0x2a 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x63 0x64 0x65 0x66 0x67 0x68 0x69 0x6a 0x73 0x74 0x75 0x76 0x77 0x78 0x79 0x7a 0x83 0x84 0x85 0x86 0x87 0x88 0x89 0x8a 0x92 0x93 0x94 0x95 0x96 0x97 0x98 0x99 0x9a 0xa2 0xa3 0xa4 0xa5 0xa6 0xa7 0xa8 0xa9 0xaa 0xb2 0xb3 0xb4 0xb5 0xb6 0xb7 0xb8 0xb9 0xba 0xc2 0xc3 0xc4 0xc5 0xc6 0xc7 0xc8 0xc9 0xca 0xd2 0xd3 0xd4 0xd5 0xd6 0xd7 0xd8 0xd9 0xda 0xe1 0xe2 0xe3 0xe4 0xe5 0xe6 0xe7 0xe8 0xe9 0xea 0xf1 0xf2 0xf3 0xf4 0xf5 0xf6 0xf7 0xf8 0xf9 0xfa] ACSPEC 1 [0x00 0x02 0x01 0x02 0x04 0x04 0x03 0x04 0x07 0x05 0x04 0x04 0x00 0x01 0x02 0x77] [0x00 0x01 0x02 0x03 0x11 0x04 0x05 0x21 0x31 0x06 0x12 0x41 0x51 0x07 0x61 0x71 0x13 0x22 0x32 0x81 0x08 0x14 0x42 0x91 0xa1 0xb1 0xc1 0x09 0x23 0x33 0x52 0xf0 0x15 0x62 0x72 0xd1 0x0a 0x16 0x24 0x34 0xe1 0x25 0xf1 0x17 0x18 0x19 0x1a 0x26 0x27 0x28 0x29 0x2a 0x35 0x36 0x37 0x38 0x39 0x3a 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x63 0x64 0x65 0x66 0x67 0x68 0x69 0x6a 0x73 0x74 0x75 0x76 0x77 0x78 0x79 0x7a 0x82 0x83 0x84 0x85 0x86 0x87 0x88 0x89 0x8a 0x92 0x93 0x94 0x95 0x96 0x97 0x98 0x99 0x9a 0xa2 0xa3 0xa4 0xa5 0xa6 0xa7 0xa8 0xa9 0xaa 0xb2 0xb3 0xb4 0xb5 0xb6 0xb7 0xb8 0xb9 0xba 0xc2 0xc3 0xc4 0xc5 0xc6 0xc7 0xc8 0xc9 0xca 0xd2 0xd3 0xd4 0xd5 0xd6 0xd7 0xd8 0xd9 0xda 0xe2 0xe3 0xe4 0xe5 0xe6 0xe7 0xe8 0xe9 0xea 0xf2 0xf3 0xf4 0xf5 0xf6 0xf7 0xf8 0xf9 0xfa] ACSEND 0 DCSEND 0 WRITEHUFFMAN WRITEQUANTIZATION WRITESCAN CLOSESCAN WRITEEOI CLOSESTREAM