MODULE  YUVStuff;

(* $StackChk- $OvflChk- $RangeChk- $CaseChk- $ReturnChk- $NilChk- $TypeChk- $OddChk- $ClearVars- *)

(* /// ------------------------------- "IMPORT" -------------------------------- *)
IMPORT  e:=Exec,
        ol:=OberonLib,
        y:=SYSTEM;
(* \\\ ------------------------------------------------------------------------- *)

(* /// -------------------------------- "CONST" -------------------------------- *)
CONST   maxJSample=255;
        centerJSample=128;
(* \\\ ------------------------------------------------------------------------- *)

(* /// -------------------------------- "TYPE" --------------------------------- *)
TYPE    YUVTab * =ARRAY 256 OF LONGINT;
        YUVTablePtr * =UNTRACED POINTER TO YUVTable;
        YUVTable * =STRUCT
            ubTab * : YUVTab;
            vrTab * : YUVTab;
            ugTab * : YUVTab;
            vgTab * : YUVTab;
            yTab * : YUVTab;
        END;

        YUVBufferPtr * =UNTRACED POINTER TO YUVBuffer;
        YUVBuffer * =STRUCT
            yBuf * : e.LSTRPTR;
            uBuf * : e.LSTRPTR;
            vBuf * : e.LSTRPTR;
        END;

        RangeLimit=ARRAY 5*(maxJSample+1)+centerJSample OF CHAR;
        RangeLimitPtr * =UNTRACED POINTER TO RangeLimit;

        RemapTable * =ARRAY 256 OF STRUCT
            alpha * : CHAR;
            red * : CHAR;
            green * : CHAR;
            blue * : CHAR;
        END;
        RemapTablePtr * =UNTRACED POINTER TO RemapTable;
(* \\\ ------------------------------------------------------------------------- *)

(* /// --------------------------------- "VAR" --------------------------------- *)
VAR     sampLimit: RangeLimitPtr;
        rngLimit: RangeLimitPtr;
        yuvTab: YUVTablePtr;
        yuvBuf: YUVBufferPtr;
(* \\\ ------------------------------------------------------------------------- *)

(* /// ------------------------- "PROCEDURE AddPtr()" -------------------------- *)
PROCEDURE AddPtr(ptr: e.APTR;
                 inc: LONGINT): e.APTR;
BEGIN
  RETURN y.VAL(e.APTR,y.VAL(LONGINT,ptr)+inc);
END AddPtr;
(* \\\ ------------------------------------------------------------------------- *)

(* /// --------------------- "PROCEDURE InitLimitTables()" --------------------- *)
PROCEDURE InitLimitTablesNew(): RangeLimitPtr;

VAR     table: RangeLimitPtr;
        cnt: INTEGER;
        off: INTEGER;

BEGIN
  IF sampLimit=NIL THEN
    NEW(sampLimit);
    table:=sampLimit;
    rngLimit:=y.VAL(RangeLimitPtr,y.VAL(LONGINT,sampLimit)+maxJSample+1);
    sampLimit^:=RangeLimit("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
                           "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
                           "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F"
                           "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F"
                           "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F"
                           "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F"
                           "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F"
                           "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F"
                           "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
                           "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
                           "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
                           "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF"
                           "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF"
                           "\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF"
                           "\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF"
                           "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
                           "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
                           "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F"
                           "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F"
                           "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F"
                           "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F"
                           "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F"
                           "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F");
  END;
  RETURN rngLimit;
END InitLimitTablesNew;
(* \\\ ------------------------------------------------------------------------- *)

(* /// --------------------- "PROCEDURE InitLimitTables()" --------------------- *)
PROCEDURE InitLimitTables * (): RangeLimitPtr;

VAR     table: RangeLimitPtr;
        cnt: INTEGER;
        off: INTEGER;

BEGIN
  IF sampLimit=NIL THEN
    NEW(sampLimit);
    rngLimit:=AddPtr(sampLimit,maxJSample+1);
    table:=sampLimit;
    FOR cnt:=0 TO maxJSample DO table[cnt]:=00X; END;
    table:=AddPtr(sampLimit,maxJSample+1);
    FOR cnt:=0 TO maxJSample DO table[cnt]:=CHR(cnt); END;
    table:=AddPtr(table,centerJSample);
    FOR cnt:=centerJSample TO 2*(maxJSample+1)-1 DO table[cnt]:=CHR(maxJSample); END;

    FOR cnt:=2*(maxJSample+1) TO 4*(maxJSample+1)-centerJSample-1 DO table[cnt]:=00X; END;
    off:=4*(maxJSample+1)-centerJSample;
    FOR cnt:=4*(maxJSample+1)-centerJSample TO 4*(maxJSample+1)-1 DO table[cnt]:=sampLimit[maxJSample+1+cnt-off]; END;
  END;
  RETURN rngLimit;
END InitLimitTables;
(* \\\ ------------------------------------------------------------------------- *)

(* /// --------------------- "PROCEDURE AllocMCUBuffers()" --------------------- *)
PROCEDURE AllocMCUBuffers * (w: LONGINT;
                             h: LONGINT): YUVBufferPtr;

CONST   dctSize=64;

BEGIN
  IF yuvBuf=NIL THEN
    NEW(yuvBuf);
  ELSE
    DISPOSE(yuvBuf.yBuf);
    DISPOSE(yuvBuf.uBuf);
    DISPOSE(yuvBuf.vBuf);
  END;
  w:=((w+15) DIV 16)*4;
  h:=(h+15) DIV 16;
  IF ODD(h) THEN INC(h); END;
  ol.New(yuvBuf.yBuf,w*dctSize);
  ol.New(yuvBuf.uBuf,w*dctSize);
  ol.New(yuvBuf.vBuf,w*dctSize);
  RETURN yuvBuf;
END AllocMCUBuffers;
(* \\\ ------------------------------------------------------------------------- *)

(* /// ---------------------- "PROCEDURE GenYUVTables()" ----------------------- *)
PROCEDURE GenYUVTables * (): YUVTablePtr;

VAR     ub: e.FLOAT;
        vr: e.FLOAT;
        ug: e.FLOAT;
        vg: e.FLOAT;
        cnt: LONGINT;
        x: e.FLOAT;

BEGIN
  IF yuvTab=NIL THEN
    NEW(yuvTab);
    ub:=(1.77200/2)*64+0.5;
    vr:=(1.40200/2)*64+0.5;
    ug:=(0.34414/2)*64+0.5;
    vg:=(0.71414/2)*64+0.5;
    FOR cnt:=0 TO 255 DO
      x:=2*cnt-255;
      yuvTab.ubTab[cnt]:=ENTIER(ub*x+32);
      yuvTab.vrTab[cnt]:=ENTIER(vr*x+32);
      yuvTab.ugTab[cnt]:=ENTIER(-ug*x);
      yuvTab.vgTab[cnt]:=ENTIER(-vg*x+32);
      yuvTab.yTab[cnt]:=y.LSH(cnt,6)+y.LSH(cnt,-2);
    END;
  END;
  RETURN yuvTab;
END GenYUVTables;
(* \\\ ------------------------------------------------------------------------- *)

END YUVStuff.

