123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include <draw.h>
- #include "imagefile.h"
- enum {
- /* Constants, all preceded by byte 0xFF */
- SOF =0xC0, /* Start of Frame */
- SOF2=0xC2, /* Start of Frame; progressive Huffman */
- JPG =0xC8, /* Reserved for JPEG extensions */
- DHT =0xC4, /* Define Huffman Tables */
- DAC =0xCC, /* Arithmetic coding conditioning */
- RST =0xD0, /* Restart interval termination */
- RST7 =0xD7, /* Restart interval termination (highest value) */
- SOI =0xD8, /* Start of Image */
- EOI =0xD9, /* End of Image */
- SOS =0xDA, /* Start of Scan */
- DQT =0xDB, /* Define quantization tables */
- DNL =0xDC, /* Define number of lines */
- DRI =0xDD, /* Define restart interval */
- DHP =0xDE, /* Define hierarchical progression */
- EXP =0xDF, /* Expand reference components */
- APPn =0xE0, /* Reserved for application segments */
- JPGn =0xF0, /* Reserved for JPEG extensions */
- COM =0xFE, /* Comment */
- CLAMPOFF = 300,
- NCLAMP = CLAMPOFF+700
- };
- typedef struct Framecomp Framecomp;
- typedef struct Header Header;
- typedef struct Huffman Huffman;
- struct Framecomp /* Frame component specifier from SOF marker */
- {
- int C;
- int H;
- int V;
- int Tq;
- };
- struct Huffman
- {
- int *size; /* malloc'ed */
- int *code; /* malloc'ed */
- int *val; /* malloc'ed */
- int mincode[17];
- int maxcode[17];
- int valptr[17];
- /* fast lookup */
- int value[256];
- int shift[256];
- };
- struct Header
- {
- Biobuf *fd;
- char err[256];
- jmp_buf errlab;
- /* variables in i/o routines */
- int sr; /* shift register, right aligned */
- int cnt; /* # bits in right part of sr */
- uchar *buf;
- int nbuf;
- int peek;
- int Nf;
- Framecomp comp[3];
- uchar mode;
- int X;
- int Y;
- int qt[4][64]; /* quantization tables */
- Huffman dcht[4];
- Huffman acht[4];
- int **data[3];
- int ndata[3];
-
- uchar *sf; /* start of frame; do better later */
- uchar *ss; /* start of scan; do better later */
- int ri; /* restart interval */
- /* progressive scan */
- Rawimage *image;
- Rawimage **array;
- int *dccoeff[3];
- int **accoeff[3]; /* only need 8 bits plus quantization */
- int naccoeff[3];
- int nblock[3];
- int nacross;
- int ndown;
- int Hmax;
- int Vmax;
- };
- static uchar clamp[NCLAMP];
- static Rawimage *readslave(Header*, int);
- static int readsegment(Header*, int*);
- static void quanttables(Header*, uchar*, int);
- static void huffmantables(Header*, uchar*, int);
- static void soiheader(Header*);
- static int nextbyte(Header*, int);
- static int int2(uchar*, int);
- static void nibbles(int, int*, int*);
- static int receive(Header*, int);
- static int receiveEOB(Header*, int);
- static int receivebit(Header*);
- static void restart(Header*, int);
- static int decode(Header*, Huffman*);
- static Rawimage* baselinescan(Header*, int);
- static void progressivescan(Header*, int);
- static Rawimage* progressiveIDCT(Header*, int);
- static void idct(int*);
- static void colormap1(Header*, int, Rawimage*, int*, int, int);
- static void colormapall1(Header*, int, Rawimage*, int*, int*, int*, int, int);
- static void colormap(Header*, int, Rawimage*, int**, int**, int**, int, int, int, int, int*, int*);
- static void jpgerror(Header*, char*, ...);
- static char readerr[] = "ReadJPG: read error: %r";
- static char memerr[] = "ReadJPG: malloc failed: %r";
- static int zig[64] = {
- 0, 1, 8, 16, 9, 2, 3, 10, 17, /* 0-7 */
- 24, 32, 25, 18, 11, 4, 5, /* 8-15 */
- 12, 19, 26, 33, 40, 48, 41, 34, /* 16-23 */
- 27, 20, 13, 6, 7, 14, 21, 28, /* 24-31 */
- 35, 42, 49, 56, 57, 50, 43, 36, /* 32-39 */
- 29, 22, 15, 23, 30, 37, 44, 51, /* 40-47 */
- 58, 59, 52, 45, 38, 31, 39, 46, /* 48-55 */
- 53, 60, 61, 54, 47, 55, 62, 63 /* 56-63 */
- };
- static
- void
- jpginit(void)
- {
- int k;
- static int inited;
- if(inited)
- return;
- inited = 1;
- for(k=0; k<CLAMPOFF; k++)
- clamp[k] = 0;
- for(; k<CLAMPOFF+256; k++)
- clamp[k] = k-CLAMPOFF;
- for(; k<NCLAMP; k++)
- clamp[k] = 255;
- }
- static
- void*
- jpgmalloc(Header *h, int n, int clear)
- {
- void *p;
- p = malloc(n);
- if(p == nil)
- jpgerror(h, memerr);
- if(clear)
- memset(p, 0, n);
- return p;
- }
- static
- void
- clear(void **p)
- {
- if(*p){
- free(*p);
- *p = nil;
- }
- }
- static
- void
- jpgfreeall(Header *h, int freeimage)
- {
- int i, j;
- clear(&h->buf);
- if(h->dccoeff[0])
- for(i=0; i<3; i++)
- clear(&h->dccoeff[i]);
- if(h->accoeff[0])
- for(i=0; i<3; i++){
- if(h->accoeff[i])
- for(j=0; j<h->naccoeff[i]; j++)
- clear(&h->accoeff[i][j]);
- clear(&h->accoeff[i]);
- }
- for(i=0; i<4; i++){
- clear(&h->dcht[i].size);
- clear(&h->acht[i].size);
- clear(&h->dcht[i].code);
- clear(&h->acht[i].code);
- clear(&h->dcht[i].val);
- clear(&h->acht[i].val);
- }
- if(h->data[0])
- for(i=0; i<3; i++){
- if(h->data[i])
- for(j=0; j<h->ndata[i]; j++)
- clear(&h->data[i][j]);
- clear(&h->data[i]);
- }
- if(freeimage && h->image!=nil){
- clear(&h->array);
- clear(&h->image->cmap);
- for(i=0; i<3; i++)
- clear(&h->image->chans[i]);
- clear(&h->image);
- }
- }
- static
- void
- jpgerror(Header *h, char *fmt, ...)
- {
- va_list arg;
- va_start(arg, fmt);
- vseprint(h->err, h->err+sizeof h->err, fmt, arg);
- va_end(arg);
- werrstr(h->err);
- jpgfreeall(h, 1);
- longjmp(h->errlab, 1);
- }
- Rawimage**
- Breadjpg(Biobuf *b, int colorspace)
- {
- Rawimage *r, **array;
- Header *h;
- char buf[ERRMAX];
- buf[0] = '\0';
- if(colorspace!=CYCbCr && colorspace!=CRGB){
- errstr(buf, sizeof buf); /* throw it away */
- werrstr("ReadJPG: unknown color space");
- return nil;
- }
- jpginit();
- h = malloc(sizeof(Header));
- array = malloc(sizeof(Header));
- if(h==nil || array==nil){
- free(h);
- free(array);
- return nil;
- }
- h->array = array;
- memset(h, 0, sizeof(Header));
- h->fd = b;
- errstr(buf, sizeof buf); /* throw it away */
- if(setjmp(h->errlab))
- r = nil;
- else
- r = readslave(h, colorspace);
- jpgfreeall(h, 0);
- free(h);
- array[0] = r;
- array[1] = nil;
- return array;
- }
- Rawimage**
- readjpg(int fd, int colorspace)
- {
- Rawimage** a;
- Biobuf b;
- if(Binit(&b, fd, OREAD) < 0)
- return nil;
- a = Breadjpg(&b, colorspace);
- Bterm(&b);
- return a;
- }
- static
- Rawimage*
- readslave(Header *header, int colorspace)
- {
- Rawimage *image;
- int nseg, i, H, V, m, n;
- uchar *b;
- soiheader(header);
- nseg = 0;
- image = nil;
- header->buf = jpgmalloc(header, 4096, 0);
- header->nbuf = 4096;
- while(header->err[0] == '\0'){
- nseg++;
- n = readsegment(header, &m);
- b = header->buf;
- switch(m){
- case -1:
- return image;
- case APPn+0:
- if(nseg==1 && strncmp((char*)b, "JFIF", 4)==0) /* JFIF header; check version */
- if(b[5]>1 || b[6]>2)
- sprint(header->err, "ReadJPG: can't handle JFIF version %d.%2d", b[5], b[6]);
- break;
- case APPn+1: case APPn+2: case APPn+3: case APPn+4: case APPn+5:
- case APPn+6: case APPn+7: case APPn+8: case APPn+9: case APPn+10:
- case APPn+11: case APPn+12: case APPn+13: case APPn+14: case APPn+15:
- break;
- case DQT:
- quanttables(header, b, n);
- break;
- case SOF:
- case SOF2:
- header->Y = int2(b, 1);
- header->X = int2(b, 3);
- header->Nf =b[5];
- for(i=0; i<header->Nf; i++){
- header->comp[i].C = b[6+3*i+0];
- nibbles(b[6+3*i+1], &H, &V);
- if(H<=0 || V<=0)
- jpgerror(header, "non-positive sampling factor (Hsamp or Vsamp)");
- header->comp[i].H = H;
- header->comp[i].V = V;
- header->comp[i].Tq = b[6+3*i+2];
- }
- header->mode = m;
- header->sf = b;
- break;
- case SOS:
- header->ss = b;
- switch(header->mode){
- case SOF:
- image = baselinescan(header, colorspace);
- break;
- case SOF2:
- progressivescan(header, colorspace);
- break;
- default:
- sprint(header->err, "unrecognized or unspecified encoding %d", header->mode);
- break;
- }
- break;
- case DHT:
- huffmantables(header, b, n);
- break;
- case DRI:
- header->ri = int2(b, 0);
- break;
- case COM:
- break;
- case EOI:
- if(header->mode == SOF2)
- image = progressiveIDCT(header, colorspace);
- return image;
- default:
- sprint(header->err, "ReadJPG: unknown marker %.2x", m);
- break;
- }
- }
- return image;
- }
- /* readsegment is called after reading scan, which can have */
- /* read ahead a byte. so we must check peek here */
- static
- int
- readbyte(Header *h)
- {
- uchar x;
- if(h->peek >= 0){
- x = h->peek;
- h->peek = -1;
- }else if(Bread(h->fd, &x, 1) != 1)
- jpgerror(h, readerr);
- return x;
- }
- static
- int
- marker(Header *h)
- {
- int c;
- while((c=readbyte(h)) == 0)
- fprint(2, "ReadJPG: skipping zero byte at offset %lld\n", Boffset(h->fd));
- if(c != 0xFF)
- jpgerror(h, "ReadJPG: expecting marker; found 0x%x at offset %lld\n", c, Boffset(h->fd));
- while(c == 0xFF)
- c = readbyte(h);
- return c;
- }
- static
- int
- int2(uchar *buf, int n)
- {
- return (buf[n]<<8) + buf[n+1];
- }
- static
- void
- nibbles(int b, int *p0, int *p1)
- {
- *p0 = (b>>4) & 0xF;
- *p1 = b & 0xF;
- }
- static
- void
- soiheader(Header *h)
- {
- h->peek = -1;
- if(marker(h) != SOI)
- jpgerror(h, "ReadJPG: unrecognized marker in header");
- h->err[0] = '\0';
- h->mode = 0;
- h->ri = 0;
- }
- static
- int
- readsegment(Header *h, int *markerp)
- {
- int m, n;
- uchar tmp[2];
- m = marker(h);
- switch(m){
- case EOI:
- *markerp = m;
- return 0;
- case 0:
- jpgerror(h, "ReadJPG: expecting marker; saw %.2x at offset %lld", m, Boffset(h->fd));
- }
- if(Bread(h->fd, tmp, 2) != 2)
- Readerr:
- jpgerror(h, readerr);
- n = int2(tmp, 0);
- if(n < 2)
- goto Readerr;
- n -= 2;
- if(n > h->nbuf){
- free(h->buf);
- h->buf = jpgmalloc(h, n+1, 0); /* +1 for sentinel */
- h->nbuf = n;
- }
- if(Bread(h->fd, h->buf, n) != n)
- goto Readerr;
- *markerp = m;
- return n;
- }
- static
- int
- huffmantable(Header *h, uchar *b)
- {
- Huffman *t;
- int Tc, th, n, nsize, i, j, k, v, cnt, code, si, sr, m;
- int *maxcode;
- nibbles(b[0], &Tc, &th);
- if(Tc > 1)
- jpgerror(h, "ReadJPG: unknown Huffman table class %d", Tc);
- if(th>3 || (h->mode==SOF && th>1))
- jpgerror(h, "ReadJPG: unknown Huffman table index %d", th);
- if(Tc == 0)
- t = &h->dcht[th];
- else
- t = &h->acht[th];
- /* flow chart C-2 */
- nsize = 0;
- for(i=0; i<16; i++)
- nsize += b[1+i];
- t->size = jpgmalloc(h, (nsize+1)*sizeof(int), 1);
- k = 0;
- for(i=1; i<=16; i++){
- n = b[i];
- for(j=0; j<n; j++)
- t->size[k++] = i;
- }
- t->size[k] = 0;
- /* initialize HUFFVAL */
- t->val = jpgmalloc(h, nsize*sizeof(int), 1);
- for(i=0; i<nsize; i++)
- t->val[i] = b[17+i];
- /* flow chart C-3 */
- t->code = jpgmalloc(h, (nsize+1)*sizeof(int), 1);
- k = 0;
- code = 0;
- si = t->size[0];
- for(;;){
- do
- t->code[k++] = code++;
- while(t->size[k] == si);
- if(t->size[k] == 0)
- break;
- do{
- code <<= 1;
- si++;
- }while(t->size[k] != si);
- }
- /* flow chart F-25 */
- i = 0;
- j = 0;
- for(;;){
- for(;;){
- i++;
- if(i > 16)
- goto outF25;
- if(b[i] != 0)
- break;
- t->maxcode[i] = -1;
- }
- t->valptr[i] = j;
- t->mincode[i] = t->code[j];
- j += b[i]-1;
- t->maxcode[i] = t->code[j];
- j++;
- }
- outF25:
- /* create byte-indexed fast path tables */
- maxcode = t->maxcode;
- /* stupid startup algorithm: just run machine for each byte value */
- for(v=0; v<256; ){
- cnt = 7;
- m = 1<<7;
- code = 0;
- sr = v;
- i = 1;
- for(;;i++){
- if(sr & m)
- code |= 1;
- if(code <= maxcode[i])
- break;
- code <<= 1;
- m >>= 1;
- if(m == 0){
- t->shift[v] = 0;
- t->value[v] = -1;
- goto continueBytes;
- }
- cnt--;
- }
- t->shift[v] = 8-cnt;
- t->value[v] = t->val[t->valptr[i]+(code-t->mincode[i])];
- continueBytes:
- v++;
- }
- return nsize;
- }
- static
- void
- huffmantables(Header *h, uchar *b, int n)
- {
- int l, mt;
- for(l=0; l<n; l+=17+mt)
- mt = huffmantable(h, &b[l]);
- }
- static
- int
- quanttable(Header *h, uchar *b)
- {
- int i, pq, tq, *q;
- nibbles(b[0], &pq, &tq);
- if(pq > 1)
- jpgerror(h, "ReadJPG: unknown quantization table class %d", pq);
- if(tq > 3)
- jpgerror(h, "ReadJPG: unknown quantization table index %d", tq);
- q = h->qt[tq];
- for(i=0; i<64; i++){
- if(pq == 0)
- q[i] = b[1+i];
- else
- q[i] = int2(b, 1+2*i);
- }
- return 64*(1+pq);
- }
- static
- void
- quanttables(Header *h, uchar *b, int n)
- {
- int l, m;
- for(l=0; l<n; l+=1+m)
- m = quanttable(h, &b[l]);
- }
- static
- Rawimage*
- baselinescan(Header *h, int colorspace)
- {
- int Ns, z, k, m, Hmax, Vmax, comp;
- int allHV1, nblock, ri, mcu, nacross, nmcu;
- Huffman *dcht, *acht;
- int block, t, diff, *qt;
- uchar *ss;
- Rawimage *image;
- int Td[3], Ta[3], H[3], V[3], DC[3];
- int ***data, *zz;
- ss = h->ss;
- Ns = ss[0];
- if((Ns!=3 && Ns!=1) || Ns!=h->Nf)
- jpgerror(h, "ReadJPG: can't handle scan not 3 components");
- image = jpgmalloc(h, sizeof(Rawimage), 1);
- h->image = image;
- image->r = Rect(0, 0, h->X, h->Y);
- image->cmap = nil;
- image->cmaplen = 0;
- image->chanlen = h->X*h->Y;
- image->fields = 0;
- image->gifflags = 0;
- image->gifdelay = 0;
- image->giftrindex = 0;
- if(Ns == 3)
- image->chandesc = colorspace;
- else
- image->chandesc = CY;
- image->nchans = h->Nf;
- for(k=0; k<h->Nf; k++)
- image->chans[k] = jpgmalloc(h, h->X*h->Y, 0);
- /* compute maximum H and V */
- Hmax = 0;
- Vmax = 0;
- for(comp=0; comp<Ns; comp++){
- if(h->comp[comp].H > Hmax)
- Hmax = h->comp[comp].H;
- if(h->comp[comp].V > Vmax)
- Vmax = h->comp[comp].V;
- }
- /* initialize data structures */
- allHV1 = 1;
- data = h->data;
- for(comp=0; comp<Ns; comp++){
- /* JPEG requires scan components to be in same order as in frame, */
- /* so if both have 3 we know scan is Y Cb Cr and there's no need to */
- /* reorder */
- nibbles(ss[2+2*comp], &Td[comp], &Ta[comp]);
- H[comp] = h->comp[comp].H;
- V[comp] = h->comp[comp].V;
- nblock = H[comp]*V[comp];
- if(nblock != 1)
- allHV1 = 0;
- data[comp] = jpgmalloc(h, nblock*sizeof(int*), 0);
- h->ndata[comp] = nblock;
- DC[comp] = 0;
- for(m=0; m<nblock; m++)
- data[comp][m] = jpgmalloc(h, 8*8*sizeof(int), 0);
- }
- ri = h->ri;
- h->cnt = 0;
- h->sr = 0;
- h->peek = -1;
- nacross = ((h->X+(8*Hmax-1))/(8*Hmax));
- nmcu = ((h->Y+(8*Vmax-1))/(8*Vmax))*nacross;
- for(mcu=0; mcu<nmcu; ){
- for(comp=0; comp<Ns; comp++){
- dcht = &h->dcht[Td[comp]];
- acht = &h->acht[Ta[comp]];
- qt = h->qt[h->comp[comp].Tq];
- for(block=0; block<H[comp]*V[comp]; block++){
- /* F-22 */
- t = decode(h, dcht);
- diff = receive(h, t);
- DC[comp] += diff;
- /* F-23 */
- zz = data[comp][block];
- memset(zz, 0, 8*8*sizeof(int));
- zz[0] = qt[0]*DC[comp];
- k = 1;
- for(;;){
- t = decode(h, acht);
- if((t&0x0F) == 0){
- if((t&0xF0) != 0xF0)
- break;
- k += 16;
- }else{
- k += t>>4;
- z = receive(h, t&0xF);
- zz[zig[k]] = z*qt[k];
- if(k == 63)
- break;
- k++;
- }
- }
- idct(zz);
- }
- }
- /* rotate colors to RGB and assign to bytes */
- if(Ns == 1) /* very easy */
- colormap1(h, colorspace, image, data[0][0], mcu, nacross);
- else if(allHV1) /* fairly easy */
- colormapall1(h, colorspace, image, data[0][0], data[1][0], data[2][0], mcu, nacross);
- else /* miserable general case */
- colormap(h, colorspace, image, data[0], data[1], data[2], mcu, nacross, Hmax, Vmax, H, V);
- /* process restart marker, if present */
- mcu++;
- if(ri>0 && mcu<nmcu && mcu%ri==0){
- restart(h, mcu);
- for(comp=0; comp<Ns; comp++)
- DC[comp] = 0;
- }
- }
- return image;
- }
- static
- void
- restart(Header *h, int mcu)
- {
- int rest, rst, nskip;
- rest = mcu/h->ri-1;
- nskip = 0;
- do{
- do{
- rst = nextbyte(h, 1);
- nskip++;
- }while(rst>=0 && rst!=0xFF);
- if(rst == 0xFF){
- rst = nextbyte(h, 1);
- nskip++;
- }
- }while(rst>=0 && (rst&~7)!=RST);
- if(nskip != 2)
- sprint(h->err, "ReadJPG: skipped %d bytes at restart %d\n", nskip-2, rest);
- if(rst < 0)
- jpgerror(h, readerr);
- if((rst&7) != (rest&7))
- jpgerror(h, "ReadJPG: expected RST%d got %d", rest&7, rst&7);
- h->cnt = 0;
- h->sr = 0;
- }
- static
- Rawimage*
- progressiveIDCT(Header *h, int colorspace)
- {
- int k, m, comp, block, Nf, bn;
- int allHV1, nblock, mcu, nmcu;
- int H[3], V[3], blockno[3];
- int *dccoeff, **accoeff;
- int ***data, *zz;
- Nf = h->Nf;
- allHV1 = 1;
- data = h->data;
- for(comp=0; comp<Nf; comp++){
- H[comp] = h->comp[comp].H;
- V[comp] = h->comp[comp].V;
- nblock = h->nblock[comp];
- if(nblock != 1)
- allHV1 = 0;
- h->ndata[comp] = nblock;
- data[comp] = jpgmalloc(h, nblock*sizeof(int*), 0);
- for(m=0; m<nblock; m++)
- data[comp][m] = jpgmalloc(h, 8*8*sizeof(int), 0);
- }
- memset(blockno, 0, sizeof blockno);
- nmcu = h->nacross*h->ndown;
- for(mcu=0; mcu<nmcu; mcu++){
- for(comp=0; comp<Nf; comp++){
- dccoeff = h->dccoeff[comp];
- accoeff = h->accoeff[comp];
- bn = blockno[comp];
- for(block=0; block<h->nblock[comp]; block++){
- zz = data[comp][block];
- memset(zz, 0, 8*8*sizeof(int));
- zz[0] = dccoeff[bn];
- for(k=1; k<64; k++)
- zz[zig[k]] = accoeff[bn][k];
- idct(zz);
- bn++;
- }
- blockno[comp] = bn;
- }
- /* rotate colors to RGB and assign to bytes */
- if(Nf == 1) /* very easy */
- colormap1(h, colorspace, h->image, data[0][0], mcu, h->nacross);
- else if(allHV1) /* fairly easy */
- colormapall1(h, colorspace, h->image, data[0][0], data[1][0], data[2][0], mcu, h->nacross);
- else /* miserable general case */
- colormap(h, colorspace, h->image, data[0], data[1], data[2], mcu, h->nacross, h->Hmax, h->Vmax, H, V);
- }
- return h->image;
- }
- static
- void
- progressiveinit(Header *h, int colorspace)
- {
- int Nf, Ns, j, k, nmcu, comp;
- uchar *ss;
- Rawimage *image;
- ss = h->ss;
- Ns = ss[0];
- Nf = h->Nf;
- if((Ns!=3 && Ns!=1) || Ns!=Nf)
- jpgerror(h, "ReadJPG: image must have 1 or 3 components");
- image = jpgmalloc(h, sizeof(Rawimage), 1);
- h->image = image;
- image->r = Rect(0, 0, h->X, h->Y);
- image->cmap = nil;
- image->cmaplen = 0;
- image->chanlen = h->X*h->Y;
- image->fields = 0;
- image->gifflags = 0;
- image->gifdelay = 0;
- image->giftrindex = 0;
- if(Nf == 3)
- image->chandesc = colorspace;
- else
- image->chandesc = CY;
- image->nchans = h->Nf;
- for(k=0; k<Nf; k++){
- image->chans[k] = jpgmalloc(h, h->X*h->Y, 0);
- h->nblock[k] = h->comp[k].H*h->comp[k].V;
- }
- /* compute maximum H and V */
- h->Hmax = 0;
- h->Vmax = 0;
- for(comp=0; comp<Nf; comp++){
- if(h->comp[comp].H > h->Hmax)
- h->Hmax = h->comp[comp].H;
- if(h->comp[comp].V > h->Vmax)
- h->Vmax = h->comp[comp].V;
- }
- h->nacross = ((h->X+(8*h->Hmax-1))/(8*h->Hmax));
- h->ndown = ((h->Y+(8*h->Vmax-1))/(8*h->Vmax));
- nmcu = h->nacross*h->ndown;
- for(k=0; k<Nf; k++){
- h->dccoeff[k] = jpgmalloc(h, h->nblock[k]*nmcu * sizeof(int), 1);
- h->accoeff[k] = jpgmalloc(h, h->nblock[k]*nmcu * sizeof(int*), 1);
- h->naccoeff[k] = h->nblock[k]*nmcu;
- for(j=0; j<h->nblock[k]*nmcu; j++)
- h->accoeff[k][j] = jpgmalloc(h, 64*sizeof(int), 1);
- }
- }
- static
- void
- progressivedc(Header *h, int comp, int Ah, int Al)
- {
- int Ns, z, ri, mcu, nmcu;
- int block, t, diff, qt, *dc, bn;
- Huffman *dcht;
- uchar *ss;
- int Td[3], DC[3], blockno[3];
- ss= h->ss;
- Ns = ss[0];
- if(Ns!=h->Nf)
- jpgerror(h, "ReadJPG: can't handle progressive with Nf!=Ns in DC scan");
- /* initialize data structures */
- h->cnt = 0;
- h->sr = 0;
- h->peek = -1;
- for(comp=0; comp<Ns; comp++){
- /*
- * JPEG requires scan components to be in same order as in frame,
- * so if both have 3 we know scan is Y Cb Cr and there's no need to
- * reorder
- */
- nibbles(ss[2+2*comp], &Td[comp], &z); /* z is ignored */
- DC[comp] = 0;
- }
- ri = h->ri;
- nmcu = h->nacross*h->ndown;
- memset(blockno, 0, sizeof blockno);
- for(mcu=0; mcu<nmcu; ){
- for(comp=0; comp<Ns; comp++){
- dcht = &h->dcht[Td[comp]];
- qt = h->qt[h->comp[comp].Tq][0];
- dc = h->dccoeff[comp];
- bn = blockno[comp];
- for(block=0; block<h->nblock[comp]; block++){
- if(Ah == 0){
- t = decode(h, dcht);
- diff = receive(h, t);
- DC[comp] += diff;
- dc[bn] = qt*DC[comp]<<Al;
- }else
- dc[bn] |= qt*receivebit(h)<<Al;
- bn++;
- }
- blockno[comp] = bn;
- }
- /* process restart marker, if present */
- mcu++;
- if(ri>0 && mcu<nmcu && mcu%ri==0){
- restart(h, mcu);
- for(comp=0; comp<Ns; comp++)
- DC[comp] = 0;
- }
- }
- }
- static
- void
- progressiveac(Header *h, int comp, int Al)
- {
- int Ns, Ss, Se, z, k, eobrun, x, y, nver, tmcu, blockno, *acc, rs;
- int ri, mcu, nacross, ndown, nmcu, nhor;
- Huffman *acht;
- int *qt, rrrr, ssss, q;
- uchar *ss;
- int Ta, H, V;
- ss = h->ss;
- Ns = ss[0];
- if(Ns != 1)
- jpgerror(h, "ReadJPG: illegal Ns>1 in progressive AC scan");
- Ss = ss[1+2];
- Se = ss[2+2];
- H = h->comp[comp].H;
- V = h->comp[comp].V;
- nacross = h->nacross*H;
- ndown = h->ndown*V;
- q = 8*h->Hmax/H;
- nhor = (h->X+q-1)/q;
- q = 8*h->Vmax/V;
- nver = (h->Y+q-1)/q;
- /* initialize data structures */
- h->cnt = 0;
- h->sr = 0;
- h->peek = -1;
- nibbles(ss[1+1], &z, &Ta); /* z is thrown away */
- ri = h->ri;
- eobrun = 0;
- acht = &h->acht[Ta];
- qt = h->qt[h->comp[comp].Tq];
- nmcu = nacross*ndown;
- mcu = 0;
- for(y=0; y<nver; y++){
- for(x=0; x<nhor; x++){
- /* Figure G-3 */
- if(eobrun > 0){
- --eobrun;
- continue;
- }
- /* arrange blockno to be in same sequence as original scan calculation. */
- tmcu = x/H + (nacross/H)*(y/V);
- blockno = tmcu*H*V + H*(y%V) + x%H;
- acc = h->accoeff[comp][blockno];
- k = Ss;
- for(;;){
- rs = decode(h, acht);
- /* XXX remove rrrr ssss as in baselinescan */
- nibbles(rs, &rrrr, &ssss);
- if(ssss == 0){
- if(rrrr < 15){
- eobrun = 0;
- if(rrrr > 0)
- eobrun = receiveEOB(h, rrrr)-1;
- break;
- }
- k += 16;
- }else{
- k += rrrr;
- z = receive(h, ssss);
- acc[k] = z*qt[k]<<Al;
- if(k == Se)
- break;
- k++;
- }
- }
- }
- /* process restart marker, if present */
- mcu++;
- if(ri>0 && mcu<nmcu && mcu%ri==0){
- restart(h, mcu);
- eobrun = 0;
- }
- }
- }
- static
- void
- increment(Header *h, int acc[], int k, int Pt)
- {
- if(acc[k] == 0)
- return;
- if(receivebit(h) != 0)
- if(acc[k] < 0)
- acc[k] -= Pt;
- else
- acc[k] += Pt;
- }
- static
- void
- progressiveacinc(Header *h, int comp, int Al)
- {
- int Ns, i, z, k, Ss, Se, Ta, **ac, H, V;
- int ri, mcu, nacross, ndown, nhor, nver, eobrun, nzeros, pending, x, y, tmcu, blockno, q, nmcu;
- Huffman *acht;
- int *qt, rrrr, ssss, *acc, rs;
- uchar *ss;
- ss = h->ss;
- Ns = ss[0];
- if(Ns != 1)
- jpgerror(h, "ReadJPG: illegal Ns>1 in progressive AC scan");
- Ss = ss[1+2];
- Se = ss[2+2];
- H = h->comp[comp].H;
- V = h->comp[comp].V;
- nacross = h->nacross*H;
- ndown = h->ndown*V;
- q = 8*h->Hmax/H;
- nhor = (h->X+q-1)/q;
- q = 8*h->Vmax/V;
- nver = (h->Y+q-1)/q;
- /* initialize data structures */
- h->cnt = 0;
- h->sr = 0;
- h->peek = -1;
- nibbles(ss[1+1], &z, &Ta); /* z is thrown away */
- ri = h->ri;
- eobrun = 0;
- ac = h->accoeff[comp];
- acht = &h->acht[Ta];
- qt = h->qt[h->comp[comp].Tq];
- nmcu = nacross*ndown;
- mcu = 0;
- pending = 0;
- nzeros = -1;
- for(y=0; y<nver; y++){
- for(x=0; x<nhor; x++){
- /* Figure G-7 */
- /* arrange blockno to be in same sequence as original scan calculation. */
- tmcu = x/H + (nacross/H)*(y/V);
- blockno = tmcu*H*V + H*(y%V) + x%H;
- acc = ac[blockno];
- if(eobrun > 0){
- if(nzeros > 0)
- jpgerror(h, "ReadJPG: zeros pending at block start");
- for(k=Ss; k<=Se; k++)
- increment(h, acc, k, qt[k]<<Al);
- --eobrun;
- continue;
- }
- for(k=Ss; k<=Se; ){
- if(nzeros >= 0){
- if(acc[k] != 0)
- increment(h, acc, k, qt[k]<<Al);
- else if(nzeros-- == 0)
- acc[k] = pending;
- k++;
- continue;
- }
- rs = decode(h, acht);
- nibbles(rs, &rrrr, &ssss);
- if(ssss == 0){
- if(rrrr < 15){
- eobrun = 0;
- if(rrrr > 0)
- eobrun = receiveEOB(h, rrrr)-1;
- while(k <= Se){
- increment(h, acc, k, qt[k]<<Al);
- k++;
- }
- break;
- }
- for(i=0; i<16; k++){
- increment(h, acc, k, qt[k]<<Al);
- if(acc[k] == 0)
- i++;
- }
- continue;
- }else if(ssss != 1)
- jpgerror(h, "ReadJPG: ssss!=1 in progressive increment");
- nzeros = rrrr;
- pending = receivebit(h);
- if(pending == 0)
- pending = -1;
- pending *= qt[k]<<Al;
- }
- }
- /* process restart marker, if present */
- mcu++;
- if(ri>0 && mcu<nmcu && mcu%ri==0){
- restart(h, mcu);
- eobrun = 0;
- nzeros = -1;
- }
- }
- }
- static
- void
- progressivescan(Header *h, int colorspace)
- {
- uchar *ss;
- int Ns, Ss, Ah, Al, c, comp, i;
- if(h->dccoeff[0] == nil)
- progressiveinit(h, colorspace);
- ss = h->ss;
- Ns = ss[0];
- Ss = ss[1+2*Ns];
- nibbles(ss[3+2*Ns], &Ah, &Al);
- c = ss[1];
- comp = -1;
- for(i=0; i<h->Nf; i++)
- if(h->comp[i].C == c)
- comp = i;
- if(comp == -1)
- jpgerror(h, "ReadJPG: bad component index in scan header");
- if(Ss == 0){
- progressivedc(h, comp, Ah, Al);
- return;
- }
- if(Ah == 0){
- progressiveac(h, comp, Al);
- return;
- }
- progressiveacinc(h, comp, Al);
- }
- enum {
- c1 = 2871, /* 1.402 * 2048 */
- c2 = 705, /* 0.34414 * 2048 */
- c3 = 1463, /* 0.71414 * 2048 */
- c4 = 3629, /* 1.772 * 2048 */
- };
- static
- void
- colormap1(Header *h, int colorspace, Rawimage *image, int data[8*8], int mcu, int nacross)
- {
- uchar *pic;
- int x, y, dx, dy, minx, miny;
- int r, k, pici;
- USED(colorspace);
- pic = image->chans[0];
- minx = 8*(mcu%nacross);
- dx = 8;
- if(minx+dx > h->X)
- dx = h->X-minx;
- miny = 8*(mcu/nacross);
- dy = 8;
- if(miny+dy > h->Y)
- dy = h->Y-miny;
- pici = miny*h->X+minx;
- k = 0;
- for(y=0; y<dy; y++){
- for(x=0; x<dx; x++){
- r = clamp[(data[k+x]+128)+CLAMPOFF];
- pic[pici+x] = r;
- }
- pici += h->X;
- k += 8;
- }
- }
- static
- void
- colormapall1(Header *h, int colorspace, Rawimage *image, int data0[8*8], int data1[8*8], int data2[8*8], int mcu, int nacross)
- {
- uchar *rpic, *gpic, *bpic, *rp, *gp, *bp;
- int *p0, *p1, *p2;
- int x, y, dx, dy, minx, miny;
- int r, g, b, k, pici;
- int Y, Cr, Cb;
- rpic = image->chans[0];
- gpic = image->chans[1];
- bpic = image->chans[2];
- minx = 8*(mcu%nacross);
- dx = 8;
- if(minx+dx > h->X)
- dx = h->X-minx;
- miny = 8*(mcu/nacross);
- dy = 8;
- if(miny+dy > h->Y)
- dy = h->Y-miny;
- pici = miny*h->X+minx;
- k = 0;
- for(y=0; y<dy; y++){
- p0 = data0+k;
- p1 = data1+k;
- p2 = data2+k;
- rp = rpic+pici;
- gp = gpic+pici;
- bp = bpic+pici;
- if(colorspace == CYCbCr)
- for(x=0; x<dx; x++){
- *rp++ = clamp[*p0++ + 128 + CLAMPOFF];
- *gp++ = clamp[*p1++ + 128 + CLAMPOFF];
- *bp++ = clamp[*p2++ + 128 + CLAMPOFF];
- }
- else
- for(x=0; x<dx; x++){
- Y = (*p0++ + 128) << 11;
- Cb = *p1++;
- Cr = *p2++;
- r = Y+c1*Cr;
- g = Y-c2*Cb-c3*Cr;
- b = Y+c4*Cb;
- *rp++ = clamp[(r>>11)+CLAMPOFF];
- *gp++ = clamp[(g>>11)+CLAMPOFF];
- *bp++ = clamp[(b>>11)+CLAMPOFF];
- }
- pici += h->X;
- k += 8;
- }
- }
- static
- void
- colormap(Header *h, int colorspace, Rawimage *image, int *data0[8*8], int *data1[8*8], int *data2[8*8], int mcu, int nacross, int Hmax, int Vmax, int *H, int *V)
- {
- uchar *rpic, *gpic, *bpic;
- int x, y, dx, dy, minx, miny;
- int r, g, b, pici, H0, H1, H2;
- int t, b0, b1, b2, y0, y1, y2, x0, x1, x2;
- int Y, Cr, Cb;
- rpic = image->chans[0];
- gpic = image->chans[1];
- bpic = image->chans[2];
- minx = 8*Hmax*(mcu%nacross);
- dx = 8*Hmax;
- if(minx+dx > h->X)
- dx = h->X-minx;
- miny = 8*Vmax*(mcu/nacross);
- dy = 8*Vmax;
- if(miny+dy > h->Y)
- dy = h->Y-miny;
- pici = miny*h->X+minx;
- H0 = H[0];
- H1 = H[1];
- H2 = H[2];
- for(y=0; y<dy; y++){
- t = y*V[0];
- b0 = H0*(t/(8*Vmax));
- y0 = 8*((t/Vmax)&7);
- t = y*V[1];
- b1 = H1*(t/(8*Vmax));
- y1 = 8*((t/Vmax)&7);
- t = y*V[2];
- b2 = H2*(t/(8*Vmax));
- y2 = 8*((t/Vmax)&7);
- x0 = 0;
- x1 = 0;
- x2 = 0;
- for(x=0; x<dx; x++){
- if(colorspace == CYCbCr){
- rpic[pici+x] = clamp[data0[b0][y0+x0++*H0/Hmax] + 128 + CLAMPOFF];
- gpic[pici+x] = clamp[data1[b1][y1+x1++*H1/Hmax] + 128 + CLAMPOFF];
- bpic[pici+x] = clamp[data2[b2][y2+x2++*H2/Hmax] + 128 + CLAMPOFF];
- }else{
- Y = (data0[b0][y0+x0++*H0/Hmax]+128)<<11;
- Cb = data1[b1][y1+x1++*H1/Hmax];
- Cr = data2[b2][y2+x2++*H2/Hmax];
- r = Y+c1*Cr;
- g = Y-c2*Cb-c3*Cr;
- b = Y+c4*Cb;
- rpic[pici+x] = clamp[(r>>11)+CLAMPOFF];
- gpic[pici+x] = clamp[(g>>11)+CLAMPOFF];
- bpic[pici+x] = clamp[(b>>11)+CLAMPOFF];
- }
- if(x0*H0/Hmax >= 8){
- x0 = 0;
- b0++;
- }
- if(x1*H1/Hmax >= 8){
- x1 = 0;
- b1++;
- }
- if(x2*H2/Hmax >= 8){
- x2 = 0;
- b2++;
- }
- }
- pici += h->X;
- }
- }
- /*
- * decode next 8-bit value from entropy-coded input. chart F-26
- */
- static
- int
- decode(Header *h, Huffman *t)
- {
- int code, v, cnt, m, sr, i;
- int *maxcode;
- static int badcode;
- maxcode = t->maxcode;
- if(h->cnt < 8)
- nextbyte(h, 0);
- /* fast lookup */
- code = (h->sr>>(h->cnt-8))&0xFF;
- v = t->value[code];
- if(v >= 0){
- h->cnt -= t->shift[code];
- return v;
- }
- h->cnt -= 8;
- if(h->cnt == 0)
- nextbyte(h, 0);
- h->cnt--;
- cnt = h->cnt;
- m = 1<<cnt;
- sr = h->sr;
- code <<= 1;
- i = 9;
- for(;;i++){
- if(sr & m)
- code |= 1;
- if(code <= maxcode[i])
- break;
- code <<= 1;
- m >>= 1;
- if(m == 0){
- sr = nextbyte(h, 0);
- m = 0x80;
- cnt = 8;
- }
- cnt--;
- }
- if(i >= 17){
- if(badcode == 0)
- fprint(2, "badly encoded %dx%d JPEG file; ignoring bad value\n", h->X, h->Y);
- badcode = 1;
- i = 0;
- }
- h->cnt = cnt;
- return t->val[t->valptr[i]+(code-t->mincode[i])];
- }
- /*
- * load next byte of input
- */
- static
- int
- nextbyte(Header *h, int marker)
- {
- int b, b2;
- if(h->peek >= 0){
- b = h->peek;
- h->peek = -1;
- }else{
- b = Bgetc(h->fd);
- if(b == Beof)
- jpgerror(h, "truncated file");
- b &= 0xFF;
- }
- if(b == 0xFF){
- if(marker)
- return b;
- b2 = Bgetc(h->fd);
- if(b2 != 0){
- if(b2 == Beof)
- jpgerror(h, "truncated file");
- b2 &= 0xFF;
- if(b2 == DNL)
- jpgerror(h, "ReadJPG: DNL marker unimplemented");
- /* decoder is reading into marker; satisfy it and restore state */
- Bungetc(h->fd);
- h->peek = b;
- }
- }
- h->cnt += 8;
- h->sr = (h->sr<<8) | b;
- return b;
- }
- /*
- * return next s bits of input, MSB first, and level shift it
- */
- static
- int
- receive(Header *h, int s)
- {
- int v, m;
- while(h->cnt < s)
- nextbyte(h, 0);
- h->cnt -= s;
- v = h->sr >> h->cnt;
- m = (1<<s);
- v &= m-1;
- /* level shift */
- if(v < (m>>1))
- v += ~(m-1)+1;
- return v;
- }
- /*
- * return next s bits of input, decode as EOB
- */
- static
- int
- receiveEOB(Header *h, int s)
- {
- int v, m;
- while(h->cnt < s)
- nextbyte(h, 0);
- h->cnt -= s;
- v = h->sr >> h->cnt;
- m = (1<<s);
- v &= m-1;
- /* level shift */
- v += m;
- return v;
- }
- /*
- * return next bit of input
- */
- static
- int
- receivebit(Header *h)
- {
- if(h->cnt < 1)
- nextbyte(h, 0);
- h->cnt--;
- return (h->sr >> h->cnt) & 1;
- }
- /*
- * Scaled integer implementation.
- * inverse two dimensional DCT, Chen-Wang algorithm
- * (IEEE ASSP-32, pp. 803-816, Aug. 1984)
- * 32-bit integer arithmetic (8 bit coefficients)
- * 11 mults, 29 adds per DCT
- *
- * coefficients extended to 12 bit for IEEE1180-1990 compliance
- */
- enum {
- W1 = 2841, /* 2048*sqrt(2)*cos(1*pi/16)*/
- W2 = 2676, /* 2048*sqrt(2)*cos(2*pi/16)*/
- W3 = 2408, /* 2048*sqrt(2)*cos(3*pi/16)*/
- W5 = 1609, /* 2048*sqrt(2)*cos(5*pi/16)*/
- W6 = 1108, /* 2048*sqrt(2)*cos(6*pi/16)*/
- W7 = 565, /* 2048*sqrt(2)*cos(7*pi/16)*/
- W1pW7 = 3406, /* W1+W7*/
- W1mW7 = 2276, /* W1-W7*/
- W3pW5 = 4017, /* W3+W5*/
- W3mW5 = 799, /* W3-W5*/
- W2pW6 = 3784, /* W2+W6*/
- W2mW6 = 1567, /* W2-W6*/
- R2 = 181 /* 256/sqrt(2)*/
- };
- static
- void
- idct(int b[8*8])
- {
- int x, y, eighty, v;
- int x0, x1, x2, x3, x4, x5, x6, x7, x8;
- int *p;
- /* transform horizontally*/
- for(y=0; y<8; y++){
- eighty = y<<3;
- /* if all non-DC components are zero, just propagate the DC term*/
- p = b+eighty;
- if(p[1]==0)
- if(p[2]==0 && p[3]==0)
- if(p[4]==0 && p[5]==0)
- if(p[6]==0 && p[7]==0){
- v = p[0]<<3;
- p[0] = v;
- p[1] = v;
- p[2] = v;
- p[3] = v;
- p[4] = v;
- p[5] = v;
- p[6] = v;
- p[7] = v;
- continue;
- }
- /* prescale*/
- x0 = (p[0]<<11)+128;
- x1 = p[4]<<11;
- x2 = p[6];
- x3 = p[2];
- x4 = p[1];
- x5 = p[7];
- x6 = p[5];
- x7 = p[3];
- /* first stage*/
- x8 = W7*(x4+x5);
- x4 = x8 + W1mW7*x4;
- x5 = x8 - W1pW7*x5;
- x8 = W3*(x6+x7);
- x6 = x8 - W3mW5*x6;
- x7 = x8 - W3pW5*x7;
- /* second stage*/
- x8 = x0 + x1;
- x0 -= x1;
- x1 = W6*(x3+x2);
- x2 = x1 - W2pW6*x2;
- x3 = x1 + W2mW6*x3;
- x1 = x4 + x6;
- x4 -= x6;
- x6 = x5 + x7;
- x5 -= x7;
- /* third stage*/
- x7 = x8 + x3;
- x8 -= x3;
- x3 = x0 + x2;
- x0 -= x2;
- x2 = (R2*(x4+x5)+128)>>8;
- x4 = (R2*(x4-x5)+128)>>8;
- /* fourth stage*/
- p[0] = (x7+x1)>>8;
- p[1] = (x3+x2)>>8;
- p[2] = (x0+x4)>>8;
- p[3] = (x8+x6)>>8;
- p[4] = (x8-x6)>>8;
- p[5] = (x0-x4)>>8;
- p[6] = (x3-x2)>>8;
- p[7] = (x7-x1)>>8;
- }
- /* transform vertically*/
- for(x=0; x<8; x++){
- /* if all non-DC components are zero, just propagate the DC term*/
- p = b+x;
- if(p[8*1]==0)
- if(p[8*2]==0 && p[8*3]==0)
- if(p[8*4]==0 && p[8*5]==0)
- if(p[8*6]==0 && p[8*7]==0){
- v = (p[8*0]+32)>>6;
- p[8*0] = v;
- p[8*1] = v;
- p[8*2] = v;
- p[8*3] = v;
- p[8*4] = v;
- p[8*5] = v;
- p[8*6] = v;
- p[8*7] = v;
- continue;
- }
- /* prescale*/
- x0 = (p[8*0]<<8)+8192;
- x1 = p[8*4]<<8;
- x2 = p[8*6];
- x3 = p[8*2];
- x4 = p[8*1];
- x5 = p[8*7];
- x6 = p[8*5];
- x7 = p[8*3];
- /* first stage*/
- x8 = W7*(x4+x5) + 4;
- x4 = (x8+W1mW7*x4)>>3;
- x5 = (x8-W1pW7*x5)>>3;
- x8 = W3*(x6+x7) + 4;
- x6 = (x8-W3mW5*x6)>>3;
- x7 = (x8-W3pW5*x7)>>3;
- /* second stage*/
- x8 = x0 + x1;
- x0 -= x1;
- x1 = W6*(x3+x2) + 4;
- x2 = (x1-W2pW6*x2)>>3;
- x3 = (x1+W2mW6*x3)>>3;
- x1 = x4 + x6;
- x4 -= x6;
- x6 = x5 + x7;
- x5 -= x7;
- /* third stage*/
- x7 = x8 + x3;
- x8 -= x3;
- x3 = x0 + x2;
- x0 -= x2;
- x2 = (R2*(x4+x5)+128)>>8;
- x4 = (R2*(x4-x5)+128)>>8;
- /* fourth stage*/
- p[8*0] = (x7+x1)>>14;
- p[8*1] = (x3+x2)>>14;
- p[8*2] = (x0+x4)>>14;
- p[8*3] = (x8+x6)>>14;
- p[8*4] = (x8-x6)>>14;
- p[8*5] = (x0-x4)>>14;
- p[8*6] = (x3-x2)>>14;
- p[8*7] = (x7-x1)>>14;
- }
- }
|