public class TJUnitTest {
- private static final String classname=new TJUnitTest().getClass().getName();
-
- private static void usage() {
- System.out.println("\nUSAGE: java "+classname+" [options]\n");
- System.out.println("Options:\n");
- System.out.println("-yuv = test YUV encoding/decoding support\n");
- System.out.println("-bi = test BufferedImage support\n");
- System.exit(1);
- }
-
- private final static String _subnamel[]=
- {"4:4:4", "4:2:2", "4:2:0", "GRAY"};
- private final static String _subnames[]=
- {"444", "422", "420", "GRAY"};
- private final static int _hsf[]={1, 2, 2, 1};
- private final static int _vsf[]={1, 1, 2, 1};
-
- private final static String _pixformatstr[]=
- {"RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "Grayscale"};
- private final static int biType[]=
- {0, BufferedImage.TYPE_3BYTE_BGR, BufferedImage.TYPE_INT_BGR,
- BufferedImage.TYPE_INT_RGB, 0, 0, BufferedImage.TYPE_BYTE_GRAY};
-
- private final static int _3byteFormats[]=
- {TJ.PF_RGB, TJ.PF_BGR};
- private final static int _3byteFormatsBI[]=
- {TJ.PF_BGR};
- private final static int _4byteFormats[]=
- {TJ.PF_RGBX, TJ.PF_BGRX, TJ.PF_XBGR, TJ.PF_XRGB};
- private final static int _4byteFormatsBI[]=
- {TJ.PF_RGBX, TJ.PF_BGRX};
- private final static int _onlyGray[]=
- {TJ.PF_GRAY};
- private final static int _onlyRGB[]=
- {TJ.PF_RGB};
-
- private final static int YUVENCODE=1, YUVDECODE=2;
- private static int yuv=0;
- private static boolean bi=false;
-
- private static int exitstatus=0;
-
- private static double gettime()
- {
- return (double)System.nanoTime()/1.0e9;
- }
-
- private final static byte pixels[][]=
- {
- {0, (byte)255, 0},
- {(byte)255, 0, (byte)255},
- {(byte)255, (byte)255, 0},
- {0, 0, (byte)255},
- {0, (byte)255, (byte)255},
- {(byte)255, 0, 0},
- {(byte)255, (byte)255, (byte)255},
- {0, 0, 0},
- {(byte)255, 0, 0}
- };
-
- private static void initbuf(byte [] buf, int w, int pitch, int h, int pf,
- int flags) throws Exception
- {
- int roffset=TJ.getRedShift(pf)/8;
- int goffset=TJ.getGreenShift(pf)/8;
- int boffset=TJ.getBlueShift(pf)/8;
- int ps=TJ.getPixelSize(pf);
- int i, _i, j;
-
- Arrays.fill(buf, (byte)0);
- if(pf==TJ.PF_GRAY)
- {
- for(_i=0; _i<16; _i++)
- {
- if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
- for(j=0; j<w; j++)
- {
- if(((_i/8)+(j/8))%2==0) buf[pitch*i+j]=(byte)255;
- else buf[pitch*i+j]=76;
- }
- }
- for(_i=16; _i<h; _i++)
- {
- if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
- for(j=0; j<w; j++)
- {
- if(((_i/8)+(j/8))%2==0) buf[pitch*i+j]=0;
- else buf[pitch*i+j]=(byte)226;
- }
- }
- return;
- }
- for(_i=0; _i<16; _i++)
- {
- if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
- for(j=0; j<w; j++)
- {
- buf[pitch*i+j*ps+roffset]=(byte)255;
- if(((_i/8)+(j/8))%2==0)
- {
- buf[pitch*i+j*ps+goffset]=(byte)255;
- buf[pitch*i+j*ps+boffset]=(byte)255;
- }
- }
- }
- for(_i=16; _i<h; _i++)
- {
- if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
- for(j=0; j<w; j++)
- {
- if(((_i/8)+(j/8))%2!=0)
- {
- buf[pitch*i+j*ps+roffset]=(byte)255;
- buf[pitch*i+j*ps+goffset]=(byte)255;
- }
- }
- }
- }
-
- private static void initintbuf(int [] buf, int w, int pitch, int h, int pf,
- int flags) throws Exception
- {
- int rshift=TJ.getRedShift(pf);
- int gshift=TJ.getGreenShift(pf);
- int bshift=TJ.getBlueShift(pf);
- int i, _i, j;
-
- Arrays.fill(buf, 0);
- for(_i=0; _i<16; _i++)
- {
- if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
- for(j=0; j<w; j++)
- {
- buf[pitch*i+j]=(255 << rshift);
- if(((_i/8)+(j/8))%2==0)
- {
- buf[pitch*i+j]|=(255 << gshift);
- buf[pitch*i+j]|=(255 << bshift);
- }
- }
- }
- for(_i=16; _i<h; _i++)
- {
- if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
- for(j=0; j<w; j++)
- {
- if(((_i/8)+(j/8))%2!=0)
- {
- buf[pitch*i+j]=(255 << rshift);
- buf[pitch*i+j]|=(255 << gshift);
- }
- }
- }
- }
-
- private static void initimg(BufferedImage img, int pf, int flags)
- throws Exception
- {
- WritableRaster wr=img.getRaster();
- int imgtype=img.getType();
- if(imgtype==BufferedImage.TYPE_INT_RGB
- || imgtype==BufferedImage.TYPE_INT_BGR)
- {
- SinglePixelPackedSampleModel sm=
- (SinglePixelPackedSampleModel)img.getSampleModel();
- int pitch=sm.getScanlineStride();
- DataBufferInt db=(DataBufferInt)wr.getDataBuffer();
- int [] buf = db.getData();
- initintbuf(buf, img.getWidth(), pitch, img.getHeight(), pf, flags);
- }
- else
- {
- ComponentSampleModel sm=
- (ComponentSampleModel)img.getSampleModel();
- int pitch=sm.getScanlineStride();
- DataBufferByte db=(DataBufferByte)wr.getDataBuffer();
- byte [] buf = db.getData();
- initbuf(buf, img.getWidth(), pitch, img.getHeight(), pf, flags);
- }
- }
-
- private static void checkval(int i, int j, int v, String vname, int cv)
- throws Exception
- {
- v=(v<0)? v+256:v;
- if(v<cv-1 || v>cv+1)
- {
- throw new Exception("\nComp. "+vname+" at "+i+","+j+" should be "+cv
- +", not "+v+"\n");
- }
- }
-
- private static void checkval0(int i, int j, int v, String vname)
- throws Exception
- {
- v=(v<0)? v+256:v;
- if(v>1)
- {
- throw new Exception("\nComp. "+vname+" at "+i+","+j+" should be 0, not "
- +v+"\n");
- }
- }
-
- private static void checkval255(int i, int j, int v, String vname)
- throws Exception
- {
- v=(v<0)? v+256:v;
- if(v<254 && !(v==217 && i==0 && j==21))
- {
- throw new Exception("\nComp. "+vname+" at "+i+","+j+" should be 255, not "
- +v+"\n");
- }
- }
-
- private static int checkbuf(byte [] buf, int w, int pitch, int h, int pf,
- int subsamp, int scale_num, int scale_denom, int flags) throws Exception
- {
- int roffset=TJ.getRedShift(pf)/8;
- int goffset=TJ.getGreenShift(pf)/8;
- int boffset=TJ.getBlueShift(pf)/8;
- int ps=TJ.getPixelSize(pf);
- int i, _i, j, retval=1;
- int halfway=16*scale_num/scale_denom, blocksize=8*scale_num/scale_denom;
-
- try
- {
- for(_i=0; _i<halfway; _i++)
- {
- if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
- for(j=0; j<w; j++)
- {
- byte r=buf[pitch*i+j*ps+roffset], g=buf[pitch*i+j*ps+goffset],
- b=buf[pitch*i+j*ps+boffset];
- if(((_i/blocksize)+(j/blocksize))%2==0)
- {
- checkval255(_i, j, r, "R");
- checkval255(_i, j, g, "G");
- checkval255(_i, j, b, "B");
- }
- else
- {
- if(subsamp==TJ.SAMP_GRAY)
- {
- checkval(_i, j, r, "R", 76);
- checkval(_i, j, g, "G", 76);
- checkval(_i, j, b, "B", 76);
- }
- else
- {
- checkval255(_i, j, r, "R");
- checkval0(_i, j, g, "G");
- checkval0(_i, j, b, "B");
- }
- }
- }
- }
- for(_i=halfway; _i<h; _i++)
- {
- if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
- for(j=0; j<w; j++)
- {
- byte r=buf[pitch*i+j*ps+roffset], g=buf[pitch*i+j*ps+goffset],
- b=buf[pitch*i+j*ps+boffset];
- if(((_i/blocksize)+(j/blocksize))%2==0)
- {
- checkval0(_i, j, r, "R");
- checkval0(_i, j, g, "G");
- }
- else
- {
- if(subsamp==TJ.SAMP_GRAY)
- {
- checkval(_i, j, r, "R", 226);
- checkval(_i, j, g, "G", 226);
- checkval(_i, j, b, "B", 226);
- }
- else
- {
- checkval255(_i, j, r, "R");
- checkval255(_i, j, g, "G");
- checkval0(_i, j, b, "B");
- }
- }
- }
- }
- }
- catch(Exception e)
- {
- System.out.println(e);
- retval=0;
- }
-
- if(retval==0)
- {
- System.out.print("\n");
- for(i=0; i<h; i++)
- {
- for(j=0; j<w; j++)
- {
- int r=buf[pitch*i+j*ps+roffset];
- int g=buf[pitch*i+j*ps+goffset];
- int b=buf[pitch*i+j*ps+boffset];
- if(r<0) r+=256; if(g<0) g+=256; if(b<0) b+=256;
- System.out.format("%3d/%3d/%3d ", r, g, b);
- }
- System.out.print("\n");
- }
- }
- return retval;
- }
-
- private static int checkintbuf(int [] buf, int w, int pitch, int h, int pf,
- int subsamp, int scale_num, int scale_denom, int flags) throws Exception
- {
- int rshift=TJ.getRedShift(pf);
- int gshift=TJ.getGreenShift(pf);
- int bshift=TJ.getBlueShift(pf);
- int i, _i, j, retval=1;
- int halfway=16*scale_num/scale_denom, blocksize=8*scale_num/scale_denom;
-
- try
- {
- for(_i=0; _i<halfway; _i++)
- {
- if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
- for(j=0; j<w; j++)
- {
- int r=(buf[pitch*i+j] >> rshift) & 0xFF;
- int g=(buf[pitch*i+j] >> gshift) & 0xFF;
- int b=(buf[pitch*i+j] >> bshift) & 0xFF;
- if(((_i/blocksize)+(j/blocksize))%2==0)
- {
- checkval255(_i, j, r, "R");
- checkval255(_i, j, g, "G");
- checkval255(_i, j, b, "B");
- }
- else
- {
- if(subsamp==TJ.SAMP_GRAY)
- {
- checkval(_i, j, r, "R", 76);
- checkval(_i, j, g, "G", 76);
- checkval(_i, j, b, "B", 76);
- }
- else
- {
- checkval255(_i, j, r, "R");
- checkval0(_i, j, g, "G");
- checkval0(_i, j, b, "B");
- }
- }
- }
- }
- for(_i=halfway; _i<h; _i++)
- {
- if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
- for(j=0; j<w; j++)
- {
- int r=(buf[pitch*i+j] >> rshift) & 0xFF;
- int g=(buf[pitch*i+j] >> gshift) & 0xFF;
- int b=(buf[pitch*i+j] >> bshift) & 0xFF;
- if(((_i/blocksize)+(j/blocksize))%2==0)
- {
- checkval0(_i, j, r, "R");
- checkval0(_i, j, g, "G");
- }
- else
- {
- if(subsamp==TJ.SAMP_GRAY)
- {
- checkval(_i, j, r, "R", 226);
- checkval(_i, j, g, "G", 226);
- checkval(_i, j, b, "B", 226);
- }
- else
- {
- checkval255(_i, j, r, "R");
- checkval255(_i, j, g, "G");
- checkval0(_i, j, b, "B");
- }
- }
- }
- }
- }
- catch(Exception e)
- {
- System.out.println(e);
- retval=0;
- }
-
- if(retval==0)
- {
- System.out.print("\n");
- for(i=0; i<h; i++)
- {
- for(j=0; j<w; j++)
- {
- int r=(buf[pitch*i+j] >> rshift) & 0xFF;
- int g=(buf[pitch*i+j] >> gshift) & 0xFF;
- int b=(buf[pitch*i+j] >> bshift) & 0xFF;
- if(r<0) r+=256; if(g<0) g+=256; if(b<0) b+=256;
- System.out.format("%3d/%3d/%3d ", r, g, b);
- }
- System.out.print("\n");
- }
- }
- return retval;
- }
-
- private static int checkimg(BufferedImage img, int pf,
- int subsamp, int scale_num, int scale_denom, int flags) throws Exception
- {
- WritableRaster wr=img.getRaster();
- int imgtype=img.getType();
- if(imgtype==BufferedImage.TYPE_INT_RGB
- || imgtype==BufferedImage.TYPE_INT_BGR)
- {
- SinglePixelPackedSampleModel sm=
- (SinglePixelPackedSampleModel)img.getSampleModel();
- int pitch=sm.getScanlineStride();
- DataBufferInt db=(DataBufferInt)wr.getDataBuffer();
- int [] buf = db.getData();
- return checkintbuf(buf, img.getWidth(), pitch, img.getHeight(), pf,
- subsamp, scale_num, scale_denom, flags);
- }
- else
- {
- ComponentSampleModel sm=
- (ComponentSampleModel)img.getSampleModel();
- int pitch=sm.getScanlineStride();
- DataBufferByte db=(DataBufferByte)wr.getDataBuffer();
- byte [] buf = db.getData();
- return checkbuf(buf, img.getWidth(), pitch, img.getHeight(), pf, subsamp,
- scale_num, scale_denom, flags);
- }
- }
-
- private static int PAD(int v, int p)
- {
- return ((v+(p)-1)&(~((p)-1)));
- }
-
- private static int checkbufyuv(byte [] buf, int size, int w, int h,
- int subsamp)
- {
- int i, j;
- int hsf=_hsf[subsamp], vsf=_vsf[subsamp];
- int pw=PAD(w, hsf), ph=PAD(h, vsf);
- int cw=pw/hsf, ch=ph/vsf;
- int ypitch=PAD(pw, 4), uvpitch=PAD(cw, 4);
- int retval=1;
- int correctsize=ypitch*ph + (subsamp==TJ.SAMP_GRAY? 0:uvpitch*ch*2);
-
- try
- {
- if(size!=correctsize)
- throw new Exception("\nIncorrect size "+size+". Should be "
- +correctsize);
-
- for(i=0; i<16; i++)
- {
- for(j=0; j<pw; j++)
- {
- byte y=buf[ypitch*i+j];
- if(((i/8)+(j/8))%2==0) checkval255(i, j, y, "Y");
- else checkval(i, j, y, "Y", 76);
- }
- }
- for(i=16; i<ph; i++)
- {
- for(j=0; j<pw; j++)
- {
- byte y=buf[ypitch*i+j];
- if(((i/8)+(j/8))%2==0) checkval0(i, j, y, "Y");
- else checkval(i, j, y, "Y", 226);
- }
- }
- if(subsamp!=TJ.SAMP_GRAY)
- {
- for(i=0; i<16/vsf; i++)
- {
- for(j=0; j<cw; j++)
- {
- byte u=buf[ypitch*ph + (uvpitch*i+j)],
- v=buf[ypitch*ph + uvpitch*ch + (uvpitch*i+j)];
- if(((i*vsf/8)+(j*hsf/8))%2==0)
- {
- checkval(i, j, u, "U", 128); checkval(i, j, v, "V", 128);
- }
- else
- {
- checkval(i, j, u, "U", 85); checkval255(i, j, v, "V");
- }
- }
- }
- for(i=16/vsf; i<ch; i++)
- {
- for(j=0; j<cw; j++)
- {
- byte u=buf[ypitch*ph + (uvpitch*i+j)],
- v=buf[ypitch*ph + uvpitch*ch + (uvpitch*i+j)];
- if(((i*vsf/8)+(j*hsf/8))%2==0)
- {
- checkval(i, j, u, "U", 128); checkval(i, j, v, "V", 128);
- }
- else
- {
- checkval0(i, j, u, "U"); checkval(i, j, v, "V", 149);
- }
- }
- }
- }
- }
- catch(Exception e)
- {
- System.out.println(e);
- retval=0;
- }
-
- if(retval==0)
- {
- for(i=0; i<ph; i++)
- {
- for(j=0; j<pw; j++)
- {
- int y=buf[ypitch*i+j];
- if(y<0) y+=256;
- System.out.format("%3d ", y);
- }
- System.out.print("\n");
- }
- System.out.print("\n");
- for(i=0; i<ch; i++)
- {
- for(j=0; j<cw; j++)
- {
- int u=buf[ypitch*ph + (uvpitch*i+j)];
- if(u<0) u+=256;
- System.out.format("%3d ", u);
- }
- System.out.print("\n");
- }
- System.out.print("\n");
- for(i=0; i<ch; i++)
- {
- for(j=0; j<cw; j++)
- {
- int v=buf[ypitch*ph + uvpitch*ch + (uvpitch*i+j)];
- if(v<0) v+=256;
- System.out.format("%3d ", v);
- }
- System.out.print("\n");
- }
- System.out.print("\n");
- }
-
- return retval;
- }
-
- private static void writejpeg(byte [] jpegbuf, int jpgbufsize,
- String filename) throws Exception
- {
- File file=new File(filename);
- FileOutputStream fos=new FileOutputStream(file);
- fos.write(jpegbuf, 0, jpgbufsize);
- fos.close();
- }
-
- private static int gentestjpeg(TJCompressor tjc, byte [] jpegbuf, int w,
- int h, int pf, String basefilename, int subsamp, int qual,
- int flags) throws Exception
- {
- String tempstr; byte [] bmpbuf=null; BufferedImage img=null;
- String pixformat; double t;
- int size=0, ps=TJ.getPixelSize(pf);
-
- pixformat=_pixformatstr[pf];
-
- System.out.print(pixformat+" ");
- if((flags&TJ.BOTTOMUP)!=0) System.out.print("Bottom-Up");
- else System.out.print("Top-Down ");
- System.out.print(" -> "+_subnamel[subsamp]+" ");
- if(yuv==YUVENCODE) System.out.print("YUV ... ");
- else System.out.print("Q"+qual+" ... ");
-
- if(bi)
- {
- img=new BufferedImage(w, h, biType[pf]);
- initimg(img, pf, flags);
- tempstr=basefilename+"_enc_"+pixformat+"_"
- +(((flags&TJ.BOTTOMUP)!=0)? "BU":"TD")+"_"+_subnames[subsamp]
- +"_Q"+qual+".png";
- File file=new File(tempstr);
- ImageIO.write(img, "png", file);
- }
- else
- {
- bmpbuf=new byte[w*h*ps+1];
- initbuf(bmpbuf, w, w*ps, h, pf, flags);
- }
- Arrays.fill(jpegbuf, (byte)0);
-
- t=gettime();
- tjc.setSubsamp(subsamp);
- tjc.setJPEGQuality(qual);
- if(bi)
- {
- if(yuv==YUVENCODE) tjc.encodeYUV(img, jpegbuf, flags);
- else tjc.compress(img, jpegbuf, flags);
- }
- else
- {
- tjc.setBitmapBuffer(bmpbuf, w, 0, h, pf);
- if(yuv==YUVENCODE) tjc.encodeYUV(jpegbuf, flags);
- else tjc.compress(jpegbuf, flags);
- }
- size=tjc.getCompressedSize();
- t=gettime()-t;
-
- if(yuv==YUVENCODE)
- tempstr=basefilename+"_enc_"+pixformat+"_"
- +(((flags&TJ.BOTTOMUP)!=0)? "BU":"TD")+"_"+_subnames[subsamp]+".yuv";
- else
- tempstr=basefilename+"_enc_"+pixformat+"_"
- +(((flags&TJ.BOTTOMUP)!=0)? "BU":"TD")+"_"+_subnames[subsamp]
- +"_Q"+qual+".jpg";
- writejpeg(jpegbuf, size, tempstr);
-
- if(yuv==YUVENCODE)
- {
- if(checkbufyuv(jpegbuf, size, w, h, subsamp)==1)
- System.out.print("Passed.");
- else {System.out.print("FAILED!"); exitstatus=-1;}
- }
- else System.out.print("Done.");
- System.out.format(" %.6f ms\n", t*1000.);
- System.out.println(" Result in "+tempstr);
-
- return size;
- }
-
- private static void _gentestbmp(TJDecompressor tjd, byte [] jpegbuf,
- int jpegsize, int w, int h, int pf, String basefilename, int subsamp,
- int flags, int scale_num, int scale_denom) throws Exception
- {
- String pixformat, tempstr; int _hdrw=0, _hdrh=0, _hdrsubsamp=-1;
- double t;
- int scaledw=(w*scale_num+scale_denom-1)/scale_denom;
- int scaledh=(h*scale_num+scale_denom-1)/scale_denom;
- int temp1, temp2;
- BufferedImage img=null; byte [] bmpbuf=null;
-
- if(yuv==YUVENCODE) return;
-
- pixformat=_pixformatstr[pf];
- System.out.print("JPEG -> ");
- if(yuv==YUVDECODE)
- System.out.print("YUV "+_subnames[subsamp]+" ... ");
- else
- {
- System.out.print(pixformat+" ");
- if((flags&TJ.BOTTOMUP)!=0) System.out.print("Bottom-Up ");
- else System.out.print("Top-Down ");
- if(scale_num!=1 || scale_denom!=1)
- System.out.print(scale_num+"/"+scale_denom+" ... ");
- else System.out.print("... ");
- }
-
- t=gettime();
- tjd.setJPEGBuffer(jpegbuf, jpegsize);
- if(tjd.getWidth()!=w || tjd.getHeight()!=h || tjd.getSubsamp()!=subsamp)
- throw new Exception("Incorrect JPEG header");
-
- temp1=scaledw; temp2=scaledh;
- temp1=tjd.getScaledWidth(temp1, temp2);
- temp2=tjd.getScaledHeight(temp1, temp2);
- if(temp1!=scaledw || temp2!=scaledh)
- throw new Exception("Scaled size mismatch");
-
- if(yuv==YUVDECODE) bmpbuf=tjd.decompressToYUV(flags);
- else
- {
- if(bi) img=tjd.decompress(scaledw, scaledh, biType[pf], flags);
- else bmpbuf=tjd.decompress(scaledw, 0, scaledh, pf, flags);
- }
- t=gettime()-t;
-
- if(bi)
- {
- tempstr=basefilename+"_dec_"+pixformat+"_"
- +(((flags&TJ.BOTTOMUP)!=0)? "BU":"TD")+"_"+_subnames[subsamp]
- +"_"+(double)scale_num/(double)scale_denom+"x"+".png";
- File file=new File(tempstr);
- ImageIO.write(img, "png", file);
- }
-
- if(yuv==YUVDECODE)
- {
- if(checkbufyuv(bmpbuf, bmpbuf.length, w, h, subsamp)==1)
- System.out.print("Passed.");
- else {System.out.print("FAILED!"); exitstatus=-1;}
- }
- else
- {
- if((bi && checkimg(img, pf, subsamp, scale_num, scale_denom, flags)==1)
- || (!bi && checkbuf(bmpbuf, scaledw, scaledw*TJ.getPixelSize(pf),
- scaledh, pf, subsamp, scale_num, scale_denom, flags)==1))
- System.out.print("Passed.");
- else
- {
- System.out.print("FAILED!"); exitstatus=-1;
- }
- }
- System.out.format(" %.6f ms\n", t*1000.);
- }
-
- private static void gentestbmp(TJDecompressor tjd, byte [] jpegbuf,
- int jpegsize, int w, int h, int pf, String basefilename, int subsamp,
- int flags) throws Exception
- {
- int i;
- if((subsamp==TJ.SAMP_444 || subsamp==TJ.SAMP_GRAY) && yuv==0)
- {
- TJ.ScalingFactor sf []=TJ.getScalingFactors();
- for(i=0; i<sf.length; i++)
- _gentestbmp(tjd, jpegbuf, jpegsize, w, h, pf, basefilename, subsamp,
- flags, sf[i].num, sf[i].denom);
- }
- else
- _gentestbmp(tjd, jpegbuf, jpegsize, w, h, pf, basefilename, subsamp,
- flags, 1, 1);
- System.out.print("\n");
- }
-
- private static void dotest(int w, int h, int [] formats, int subsamp,
- String basefilename) throws Exception
- {
- TJCompressor tjc=null; TJDecompressor tjd=null;
- int size; int pfstart, pfend;
- byte [] jpegbuf;
-
- if(yuv==YUVENCODE) jpegbuf=new byte[TJ.bufSizeYUV(w, h, subsamp)];
- else jpegbuf=new byte[TJ.bufSize(w, h)];
-
- try
- {
- tjc=new TJCompressor();
- tjd=new TJDecompressor();
-
- for(int pf : formats)
- {
- for(int i=0; i<2; i++)
- {
- int flags=0;
- if(i==1)
- {
- if(yuv==YUVDECODE)
- {
- tjc.close(); tjd.close(); return;
- }
- else flags|=TJ.BOTTOMUP;
- }
- size=gentestjpeg(tjc, jpegbuf, w, h, pf, basefilename, subsamp, 100,
- flags);
- gentestbmp(tjd, jpegbuf, size, w, h, pf, basefilename, subsamp,
- flags);
- }
- }
- }
- catch(Exception e)
- {
- if(tjc!=null) tjc.close();
- if(tjd!=null) tjd.close();
- throw e;
- }
- if(tjc!=null) tjc.close();
- if(tjd!=null) tjd.close();
- }
-
- private final static int MAXLENGTH=2048;
-
- private static void dotest1() throws Exception
- {
- int i, j, i2; byte [] bmpbuf, jpgbuf;
- TJCompressor tjc=null;
-
- try
- {
- tjc=new TJCompressor();
- System.out.println("Buffer size regression test");
- for(j=1; j<48; j++)
- {
- for(i=1; i<(j==1?MAXLENGTH:48); i++)
- {
- if(i%100==0) System.out.format("%04d x %04d\b\b\b\b\b\b\b\b\b\b\b",
- i, j);
- bmpbuf=new byte[i*j*4];
- jpgbuf=new byte[TJ.bufSize(i, j)];
- Arrays.fill(bmpbuf, (byte)0);
- for(i2=0; i2<i*j; i2++)
- {
- bmpbuf[i2*4]=pixels[i2%9][2];
- bmpbuf[i2*4+1]=pixels[i2%9][1];
- bmpbuf[i2*4+2]=pixels[i2%9][0];
- }
- tjc.setBitmapBuffer(bmpbuf, i, 0, j, TJ.PF_BGRX);
- tjc.setSubsamp(TJ.SAMP_444);
- tjc.setJPEGQuality(100);
- tjc.compress(jpgbuf, 0);
-
- bmpbuf=new byte[j*i*4];
- jpgbuf=new byte[TJ.bufSize(j, i)];
- for(i2=0; i2<j*i; i2++)
- {
- if(i2%2==0) bmpbuf[i2*4]=bmpbuf[i2*4+1]=bmpbuf[i2*4+2]=(byte)0xFF;
- else bmpbuf[i2*4]=bmpbuf[i2*4+1]=bmpbuf[i2*4+2]=0;
- }
- tjc.setBitmapBuffer(bmpbuf, j, 0, i, TJ.PF_BGRX);
- tjc.compress(jpgbuf, 0);
- }
- }
- System.out.println("Done. ");
- }
- catch(Exception e)
- {
- if(tjc!=null) tjc.close();
- throw e;
- }
- if(tjc!=null) tjc.close();
- }
-
- public static void main(String argv[])
- {
- try
- {
- boolean doyuv=false;
- for(int i=0; i<argv.length; i++)
- {
- if(argv[i].equalsIgnoreCase("-yuv")) doyuv=true;
- if(argv[i].substring(0, 1).equalsIgnoreCase("-h")
- || argv[i].equalsIgnoreCase("-?"))
- usage();
- if(argv[i].equalsIgnoreCase("-bi")) bi=true;
- }
- if(doyuv) yuv=YUVENCODE;
- dotest(35, 39, bi? _3byteFormatsBI:_3byteFormats, TJ.SAMP_444, "test");
- dotest(39, 41, bi? _4byteFormatsBI:_4byteFormats, TJ.SAMP_444, "test");
- if(doyuv)
- {
- dotest(41, 35, bi? _3byteFormatsBI:_3byteFormats, TJ.SAMP_422, "test");
- dotest(35, 39, bi? _4byteFormatsBI:_4byteFormats, TJ.SAMP_422, "test");
- dotest(39, 41, bi? _3byteFormatsBI:_3byteFormats, TJ.SAMP_420, "test");
- dotest(41, 35, bi? _4byteFormatsBI:_4byteFormats, TJ.SAMP_420, "test");
- }
- dotest(35, 39, _onlyGray, TJ.SAMP_GRAY, "test");
- dotest(39, 41, bi? _3byteFormatsBI:_3byteFormats, TJ.SAMP_GRAY, "test");
- dotest(41, 35, bi? _4byteFormatsBI:_4byteFormats, TJ.SAMP_GRAY, "test");
- if(!doyuv && !bi) dotest1();
- if(doyuv && !bi)
- {
- yuv=YUVDECODE;
- dotest(48, 48, _onlyRGB, TJ.SAMP_444, "test");
- dotest(35, 39, _onlyRGB, TJ.SAMP_444, "test");
- dotest(48, 48, _onlyRGB, TJ.SAMP_422, "test");
- dotest(39, 41, _onlyRGB, TJ.SAMP_422, "test");
- dotest(48, 48, _onlyRGB, TJ.SAMP_420, "test");
- dotest(41, 35, _onlyRGB, TJ.SAMP_420, "test");
- dotest(48, 48, _onlyRGB, TJ.SAMP_GRAY, "test");
- dotest(35, 39, _onlyRGB, TJ.SAMP_GRAY, "test");
- dotest(48, 48, _onlyGray, TJ.SAMP_GRAY, "test");
- dotest(39, 41, _onlyGray, TJ.SAMP_GRAY, "test");
- }
- }
- catch(Exception e)
- {
- System.out.println(e);
- exitstatus=-1;
- }
- System.exit(exitstatus);
- }
+ private static final String classname =
+ new TJUnitTest().getClass().getName();
+
+ private static void usage() {
+ System.out.println("\nUSAGE: java " + classname + " [options]\n");
+ System.out.println("Options:\n");
+ System.out.println("-yuv = test YUV encoding/decoding support\n");
+ System.out.println("-bi = test BufferedImage support\n");
+ System.exit(1);
+ }
+
+ private final static String subNameLong[] = {
+ "4:4:4", "4:2:2", "4:2:0", "GRAY"
+ };
+ private final static String subName[] = {
+ "444", "422", "420", "GRAY"
+ };
+ private final static int horizSampFactor[] = {
+ 1, 2, 2, 1
+ };
+ private final static int vertSampFactor[] = {
+ 1, 1, 2, 1
+ };
+
+ private final static String pixFormatStr[] = {
+ "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "Grayscale"
+ };
+ private final static int biType[] = {
+ 0, BufferedImage.TYPE_3BYTE_BGR, BufferedImage.TYPE_INT_BGR,
+ BufferedImage.TYPE_INT_RGB, 0, 0, BufferedImage.TYPE_BYTE_GRAY
+ };
+
+ private final static int _3byteFormats[] = {
+ TJ.PF_RGB, TJ.PF_BGR
+ };
+ private final static int _3byteFormatsBI[] = {
+ TJ.PF_BGR
+ };
+ private final static int _4byteFormats[] = {
+ TJ.PF_RGBX, TJ.PF_BGRX, TJ.PF_XBGR, TJ.PF_XRGB
+ };
+ private final static int _4byteFormatsBI[] = {
+ TJ.PF_RGBX, TJ.PF_BGRX
+ };
+ private final static int onlyGray[] = {
+ TJ.PF_GRAY
+ };
+ private final static int onlyRGB[] = {
+ TJ.PF_RGB
+ };
+
+ private final static int YUVENCODE = 1;
+ private final static int YUVDECODE = 2;
+ private static int yuv = 0;
+ private static boolean bi = false;
+
+ private static int exitStatus = 0;
+
+ private static double getTime() {
+ return (double)System.nanoTime() / 1.0e9;
+ }
+
+ private final static byte pixels[][] = {
+ {0, (byte)255, 0},
+ {(byte)255, 0, (byte)255},
+ {(byte)255, (byte)255, 0},
+ {0, 0, (byte)255},
+ {0, (byte)255, (byte)255},
+ {(byte)255, 0, 0},
+ {(byte)255, (byte)255, (byte)255},
+ {0, 0, 0},
+ {(byte)255, 0, 0}
+ };
+
+ private static void initBuf(byte[] buf, int w, int pitch, int h, int pf,
+ int flags) throws Exception {
+ int roffset = TJ.getRedShift(pf) / 8;
+ int goffset = TJ.getGreenShift(pf) / 8;
+ int boffset = TJ.getBlueShift(pf) / 8;
+ int ps = TJ.getPixelSize(pf);
+ int i, _i, j;
+
+ Arrays.fill(buf, (byte)0);
+ if(pf == TJ.PF_GRAY) {
+ for(_i = 0; _i < 16; _i++) {
+ if((flags & TJ.BOTTOMUP) != 0) i = h - _i - 1;
+ else i = _i;
+ for(j = 0; j < w; j++) {
+ if(((_i / 8) + (j / 8)) % 2 == 0) buf[pitch * i + j] = (byte)255;
+ else buf[pitch * i + j] = 76;
+ }
+ }
+ for(_i = 16; _i < h; _i++) {
+ if((flags & TJ.BOTTOMUP) != 0) i = h - _i - 1;
+ else i = _i;
+ for(j = 0; j < w; j++) {
+ if(((_i / 8) + (j / 8)) % 2 == 0) buf[pitch * i + j] = 0;
+ else buf[pitch * i + j] = (byte)226;
+ }
+ }
+ return;
+ }
+ for(_i = 0; _i < 16; _i++) {
+ if((flags & TJ.BOTTOMUP) != 0) i = h - _i - 1;
+ else i = _i;
+ for(j = 0; j < w; j++) {
+ buf[pitch * i + j * ps + roffset] = (byte)255;
+ if(((_i / 8) + (j / 8)) % 2 == 0) {
+ buf[pitch * i + j * ps + goffset] = (byte)255;
+ buf[pitch * i + j * ps + boffset] = (byte)255;
+ }
+ }
+ }
+ for(_i = 16; _i < h; _i++) {
+ if((flags & TJ.BOTTOMUP) != 0) i = h - _i - 1;
+ else i = _i;
+ for(j = 0; j < w; j++) {
+ if(((_i / 8) + (j / 8)) % 2 != 0) {
+ buf[pitch * i + j * ps + roffset] = (byte)255;
+ buf[pitch * i + j * ps + goffset] = (byte)255;
+ }
+ }
+ }
+ }
+
+ private static void initIntBuf(int[] buf, int w, int pitch, int h, int pf,
+ int flags) throws Exception {
+ int rshift = TJ.getRedShift(pf);
+ int gshift = TJ.getGreenShift(pf);
+ int bshift = TJ.getBlueShift(pf);
+ int i, _i, j;
+
+ Arrays.fill(buf, 0);
+ for(_i = 0; _i < 16; _i++) {
+ if((flags & TJ.BOTTOMUP) != 0) i = h - _i - 1;
+ else i = _i;
+ for(j = 0; j < w; j++) {
+ buf[pitch * i + j] = (255 << rshift);
+ if(((_i / 8) + (j / 8)) % 2 == 0) {
+ buf[pitch * i + j] |= (255 << gshift);
+ buf[pitch * i + j] |= (255 << bshift);
+ }
+ }
+ }
+ for(_i = 16; _i < h; _i++) {
+ if((flags & TJ.BOTTOMUP) != 0) i = h - _i - 1;
+ else i = _i;
+ for(j = 0; j < w; j++) {
+ if(((_i / 8) + (j / 8)) % 2 != 0) {
+ buf[pitch * i + j] = (255 << rshift);
+ buf[pitch * i + j] |= (255 << gshift);
+ }
+ }
+ }
+ }
+
+ private static void initImg(BufferedImage img, int pf, int flags)
+ throws Exception {
+ WritableRaster wr = img.getRaster();
+ int imgtype = img.getType();
+ if(imgtype == BufferedImage.TYPE_INT_RGB
+ || imgtype == BufferedImage.TYPE_INT_BGR) {
+ SinglePixelPackedSampleModel sm =
+ (SinglePixelPackedSampleModel)img.getSampleModel();
+ int pitch = sm.getScanlineStride();
+ DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
+ int[] buf = db.getData();
+ initIntBuf(buf, img.getWidth(), pitch, img.getHeight(), pf, flags);
+ }
+ else {
+ ComponentSampleModel sm = (ComponentSampleModel)img.getSampleModel();
+ int pitch = sm.getScanlineStride();
+ DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
+ byte[] buf = db.getData();
+ initBuf(buf, img.getWidth(), pitch, img.getHeight(), pf, flags);
+ }
+ }
+
+ private static void checkVal(int i, int j, int v, String vname, int cv)
+ throws Exception {
+ v = (v < 0) ? v + 256 : v;
+ if(v < cv - 1 || v > cv + 1) {
+ throw new Exception("\nComp. " + vname + " at " + i + "," + j
+ + " should be " + cv + ", not " + v + "\n");
+ }
+ }
+
+ private static void checkVal0(int i, int j, int v, String vname)
+ throws Exception {
+ v = (v < 0) ? v + 256 : v;
+ if(v > 1) {
+ throw new Exception("\nComp. " + vname + " at " + i + "," + j
+ + " should be 0, not " + v + "\n");
+ }
+ }
+
+ private static void checkVal255(int i, int j, int v, String vname)
+ throws Exception {
+ v = (v < 0) ? v + 256 : v;
+ if(v < 254) {
+ throw new Exception("\nComp. " + vname + " at " + i + "," + j
+ + " should be 255, not " + v + "\n");
+ }
+ }
+
+ private static int checkBuf(byte[] buf, int w, int pitch, int h, int pf,
+ int subsamp, int scaleNum, int scaleDenom, int flags) throws Exception {
+ int roffset = TJ.getRedShift(pf) / 8;
+ int goffset = TJ.getGreenShift(pf) / 8;
+ int boffset = TJ.getBlueShift(pf) / 8;
+ int ps = TJ.getPixelSize(pf);
+ int i, _i, j, retval = 1;
+ int halfway = 16 * scaleNum / scaleDenom;
+ int blockSize = 8 * scaleNum / scaleDenom;
+
+ try {
+ for(_i = 0; _i < halfway; _i++) {
+ if((flags & TJ.BOTTOMUP) != 0) i = h - _i - 1;
+ else i = _i;
+ for(j = 0; j < w; j++) {
+ byte r = buf[pitch * i + j * ps + roffset];
+ byte g = buf[pitch * i + j * ps + goffset];
+ byte b = buf[pitch * i + j * ps + boffset];
+ if(((_i / blockSize) + (j / blockSize)) % 2 == 0) {
+ checkVal255(_i, j, r, "R");
+ checkVal255(_i, j, g, "G");
+ checkVal255(_i, j, b, "B");
+ }
+ else {
+ if(subsamp == TJ.SAMP_GRAY) {
+ checkVal(_i, j, r, "R", 76);
+ checkVal(_i, j, g, "G", 76);
+ checkVal(_i, j, b, "B", 76);
+ }
+ else {
+ checkVal255(_i, j, r, "R");
+ checkVal0(_i, j, g, "G");
+ checkVal0(_i, j, b, "B");
+ }
+ }
+ }
+ }
+ for(_i = halfway; _i < h; _i++) {
+ if((flags & TJ.BOTTOMUP) != 0) i = h - _i - 1;
+ else i = _i;
+ for(j = 0; j < w; j++) {
+ byte r = buf[pitch * i + j * ps + roffset];
+ byte g = buf[pitch * i + j * ps + goffset];
+ byte b = buf[pitch * i + j * ps + boffset];
+ if(((_i / blockSize) + (j / blockSize)) % 2 == 0) {
+ checkVal0(_i, j, r, "R");
+ checkVal0(_i, j, g, "G");
+ }
+ else {
+ if(subsamp == TJ.SAMP_GRAY) {
+ checkVal(_i, j, r, "R", 226);
+ checkVal(_i, j, g, "G", 226);
+ checkVal(_i, j, b, "B", 226);
+ }
+ else {
+ checkVal255(_i, j, r, "R");
+ checkVal255(_i, j, g, "G");
+ checkVal0(_i, j, b, "B");
+ }
+ }
+ }
+ }
+ }
+ catch(Exception e) {
+ System.out.println(e);
+ retval = 0;
+ }
+
+ if(retval == 0) {
+ System.out.print("\n");
+ for(i = 0; i < h; i++) {
+ for(j = 0; j < w; j++) {
+ int r = buf[pitch * i + j * ps + roffset];
+ int g = buf[pitch * i + j * ps + goffset];
+ int b = buf[pitch * i + j * ps + boffset];
+ if(r < 0) r += 256; if(g < 0) g += 256; if(b < 0) b += 256;
+ System.out.format("%3d/%3d/%3d ", r, g, b);
+ }
+ System.out.print("\n");
+ }
+ }
+ return retval;
+ }
+
+ private static int checkIntBuf(int[] buf, int w, int pitch, int h, int pf,
+ int subsamp, int scaleNum, int scaleDenom, int flags) throws Exception {
+ int rshift = TJ.getRedShift(pf);
+ int gshift = TJ.getGreenShift(pf);
+ int bshift = TJ.getBlueShift(pf);
+ int i, _i, j, retval = 1;
+ int halfway = 16 * scaleNum / scaleDenom;
+ int blockSize = 8 * scaleNum / scaleDenom;
+
+ try {
+ for(_i = 0; _i < halfway; _i++) {
+ if((flags & TJ.BOTTOMUP) != 0) i = h - _i - 1;
+ else i = _i;
+ for(j = 0; j < w; j++) {
+ int r = (buf[pitch * i + j] >> rshift) & 0xFF;
+ int g = (buf[pitch * i + j] >> gshift) & 0xFF;
+ int b = (buf[pitch * i + j] >> bshift) & 0xFF;
+ if(((_i / blockSize) + (j / blockSize)) % 2 == 0) {
+ checkVal255(_i, j, r, "R");
+ checkVal255(_i, j, g, "G");
+ checkVal255(_i, j, b, "B");
+ }
+ else {
+ if(subsamp == TJ.SAMP_GRAY) {
+ checkVal(_i, j, r, "R", 76);
+ checkVal(_i, j, g, "G", 76);
+ checkVal(_i, j, b, "B", 76);
+ }
+ else {
+ checkVal255(_i, j, r, "R");
+ checkVal0(_i, j, g, "G");
+ checkVal0(_i, j, b, "B");
+ }
+ }
+ }
+ }
+ for(_i = halfway; _i < h; _i++) {
+ if((flags & TJ.BOTTOMUP) != 0) i = h - _i - 1;
+ else i = _i;
+ for(j = 0; j < w; j++) {
+ int r = (buf[pitch * i + j] >> rshift) & 0xFF;
+ int g = (buf[pitch * i + j] >> gshift) & 0xFF;
+ int b = (buf[pitch * i + j] >> bshift) & 0xFF;
+ if(((_i / blockSize) + (j / blockSize)) % 2 == 0) {
+ checkVal0(_i, j, r, "R");
+ checkVal0(_i, j, g, "G");
+ }
+ else {
+ if(subsamp == TJ.SAMP_GRAY) {
+ checkVal(_i, j, r, "R", 226);
+ checkVal(_i, j, g, "G", 226);
+ checkVal(_i, j, b, "B", 226);
+ }
+ else {
+ checkVal255(_i, j, r, "R");
+ checkVal255(_i, j, g, "G");
+ checkVal0(_i, j, b, "B");
+ }
+ }
+ }
+ }
+ }
+ catch(Exception e) {
+ System.out.println(e);
+ retval = 0;
+ }
+
+ if(retval == 0) {
+ System.out.print("\n");
+ for(i = 0; i < h; i++) {
+ for(j = 0; j < w; j++) {
+ int r = (buf[pitch * i + j] >> rshift) & 0xFF;
+ int g = (buf[pitch * i + j] >> gshift) & 0xFF;
+ int b = (buf[pitch * i + j] >> bshift) & 0xFF;
+ if(r < 0) r += 256; if(g < 0) g += 256; if(b < 0) b += 256;
+ System.out.format("%3d/%3d/%3d ", r, g, b);
+ }
+ System.out.print("\n");
+ }
+ }
+ return retval;
+ }
+
+ private static int checkImg(BufferedImage img, int pf,
+ int subsamp, int scaleNum, int scaleDenom, int flags) throws Exception {
+ WritableRaster wr = img.getRaster();
+ int imgtype = img.getType();
+ if(imgtype == BufferedImage.TYPE_INT_RGB
+ || imgtype == BufferedImage.TYPE_INT_BGR) {
+ SinglePixelPackedSampleModel sm =
+ (SinglePixelPackedSampleModel)img.getSampleModel();
+ int pitch = sm.getScanlineStride();
+ DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
+ int[] buf = db.getData();
+ return checkIntBuf(buf, img.getWidth(), pitch, img.getHeight(), pf,
+ subsamp, scaleNum, scaleDenom, flags);
+ }
+ else {
+ ComponentSampleModel sm = (ComponentSampleModel)img.getSampleModel();
+ int pitch = sm.getScanlineStride();
+ DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
+ byte[] buf = db.getData();
+ return checkBuf(buf, img.getWidth(), pitch, img.getHeight(), pf, subsamp,
+ scaleNum, scaleDenom, flags);
+ }
+ }
+
+ private static int PAD(int v, int p) {
+ return ((v + (p) - 1) & (~((p) - 1)));
+ }
+
+ private static int checkBufYUV(byte[] buf, int size, int w, int h,
+ int subsamp) {
+ int i, j;
+ int hsf = horizSampFactor[subsamp], vsf = vertSampFactor[subsamp];
+ int pw = PAD(w, hsf), ph = PAD(h, vsf);
+ int cw = pw / hsf, ch = ph / vsf;
+ int ypitch = PAD(pw, 4), uvpitch = PAD(cw, 4);
+ int retval = 1;
+ int correctsize = ypitch * ph
+ + (subsamp == TJ.SAMP_GRAY ? 0 : uvpitch * ch * 2);
+
+ try {
+ if(size != correctsize)
+ throw new Exception("\nIncorrect size " + size + ". Should be "
+ + correctsize);
+
+ for(i = 0; i < 16; i++) {
+ for(j = 0; j < pw; j++) {
+ byte y = buf[ypitch * i + j];
+ if(((i / 8) + (j / 8)) % 2 == 0) checkVal255(i, j, y, "Y");
+ else checkVal(i, j, y, "Y", 76);
+ }
+ }
+ for(i = 16; i < ph; i++) {
+ for(j = 0; j < pw; j++) {
+ byte y = buf[ypitch * i + j];
+ if(((i / 8) + (j / 8)) % 2 == 0) checkVal0(i, j, y, "Y");
+ else checkVal(i, j, y, "Y", 226);
+ }
+ }
+ if(subsamp != TJ.SAMP_GRAY) {
+ for(i = 0; i < 16 / vsf; i++) {
+ for(j = 0; j < cw; j++) {
+ byte u = buf[ypitch * ph + (uvpitch * i + j)],
+ v = buf[ypitch * ph + uvpitch * ch + (uvpitch * i + j)];
+ if(((i * vsf / 8) + (j * hsf / 8)) % 2 == 0) {
+ checkVal(i, j, u, "U", 128); checkVal(i, j, v, "V", 128);
+ }
+ else {
+ checkVal(i, j, u, "U", 85); checkVal255(i, j, v, "V");
+ }
+ }
+ }
+ for(i = 16 / vsf; i < ch; i++) {
+ for(j = 0; j < cw; j++) {
+ byte u = buf[ypitch * ph + (uvpitch * i + j)],
+ v = buf[ypitch * ph + uvpitch * ch + (uvpitch * i + j)];
+ if(((i * vsf / 8) + (j * hsf / 8)) % 2 == 0) {
+ checkVal(i, j, u, "U", 128); checkVal(i, j, v, "V", 128);
+ }
+ else {
+ checkVal0(i, j, u, "U"); checkVal(i, j, v, "V", 149);
+ }
+ }
+ }
+ }
+ }
+ catch(Exception e) {
+ System.out.println(e);
+ retval = 0;
+ }
+
+ if(retval == 0) {
+ for(i = 0; i < ph; i++) {
+ for(j = 0; j < pw; j++) {
+ int y = buf[ypitch * i + j];
+ if(y < 0) y += 256;
+ System.out.format("%3d ", y);
+ }
+ System.out.print("\n");
+ }
+ System.out.print("\n");
+ for(i = 0; i < ch; i++) {
+ for(j = 0; j < cw; j++) {
+ int u = buf[ypitch * ph + (uvpitch * i + j)];
+ if(u < 0) u += 256;
+ System.out.format("%3d ", u);
+ }
+ System.out.print("\n");
+ }
+ System.out.print("\n");
+ for(i = 0; i < ch; i++) {
+ for(j = 0; j < cw; j++) {
+ int v = buf[ypitch * ph + uvpitch * ch + (uvpitch * i + j)];
+ if(v < 0) v += 256;
+ System.out.format("%3d ", v);
+ }
+ System.out.print("\n");
+ }
+ System.out.print("\n");
+ }
+
+ return retval;
+ }
+
+ private static void writeJPEG(byte[] jpegBuf, int jpegBufSize,
+ String filename) throws Exception {
+ File file = new File(filename);
+ FileOutputStream fos = new FileOutputStream(file);
+ fos.write(jpegBuf, 0, jpegBufSize);
+ fos.close();
+ }
+
+ private static int genTestJPEG(TJCompressor tjc, byte[] jpegBuf, int w,
+ int h, int pf, String baseFilename, int subsamp, int qual,
+ int flags) throws Exception {
+ String tempstr;
+ byte[] bmpBuf = null;
+ BufferedImage img = null;
+ String pfStr;
+ double t;
+ int size = 0, ps = TJ.getPixelSize(pf);
+
+ pfStr = pixFormatStr[pf];
+
+ System.out.print(pfStr + " ");
+ if((flags & TJ.BOTTOMUP) != 0) System.out.print("Bottom-Up");
+ else System.out.print("Top-Down ");
+ System.out.print(" -> " + subNameLong[subsamp] + " ");
+ if(yuv == YUVENCODE) System.out.print("YUV ... ");
+ else System.out.print("Q" + qual + " ... ");
+
+ if(bi) {
+ img = new BufferedImage(w, h, biType[pf]);
+ initImg(img, pf, flags);
+ tempstr = baseFilename + "_enc_" + pfStr + "_"
+ + (((flags & TJ.BOTTOMUP) != 0) ? "BU" : "TD") + "_"
+ + subName[subsamp] + "_Q" + qual + ".png";
+ File file = new File(tempstr);
+ ImageIO.write(img, "png", file);
+ }
+ else {
+ bmpBuf = new byte[w * h * ps + 1];
+ initBuf(bmpBuf, w, w * ps, h, pf, flags);
+ }
+ Arrays.fill(jpegBuf, (byte)0);
+
+ t = getTime();
+ tjc.setSubsamp(subsamp);
+ tjc.setJPEGQuality(qual);
+ if(bi) {
+ if(yuv == YUVENCODE) tjc.encodeYUV(img, jpegBuf, flags);
+ else tjc.compress(img, jpegBuf, flags);
+ }
+ else {
+ tjc.setBitmapBuffer(bmpBuf, w, 0, h, pf);
+ if(yuv == YUVENCODE) tjc.encodeYUV(jpegBuf, flags);
+ else tjc.compress(jpegBuf, flags);
+ }
+ size = tjc.getCompressedSize();
+ t = getTime() - t;
+
+ if(yuv == YUVENCODE)
+ tempstr = baseFilename + "_enc_" + pfStr + "_"
+ + (((flags & TJ.BOTTOMUP) != 0) ? "BU" : "TD") + "_"
+ + subName[subsamp] + ".yuv";
+ else
+ tempstr = baseFilename + "_enc_" + pfStr + "_"
+ + (((flags & TJ.BOTTOMUP) != 0) ? "BU" : "TD") + "_"
+ + subName[subsamp] + "_Q" + qual + ".jpg";
+ writeJPEG(jpegBuf, size, tempstr);
+
+ if(yuv == YUVENCODE) {
+ if(checkBufYUV(jpegBuf, size, w, h, subsamp) == 1)
+ System.out.print("Passed.");
+ else {
+ System.out.print("FAILED!"); exitStatus = -1;
+ }
+ }
+ else System.out.print("Done.");
+ System.out.format(" %.6f ms\n", t * 1000.);
+ System.out.println(" Result in " + tempstr);
+
+ return size;
+ }
+
+ private static void genTestBMP(TJDecompressor tjd, byte[] jpegBuf,
+ int jpegsize, int w, int h, int pf, String baseFilename, int subsamp,
+ int flags, int scaleNum, int scaleDenom) throws Exception {
+ String pfStr, tempstr;
+ double t;
+ int scaledWidth = (w * scaleNum + scaleDenom - 1) / scaleDenom;
+ int scaledHeight = (h * scaleNum + scaleDenom - 1) / scaleDenom;
+ int temp1, temp2;
+ BufferedImage img = null;
+ byte[] bmpBuf = null;
+
+ if(yuv == YUVENCODE) return;
+
+ pfStr = pixFormatStr[pf];
+ System.out.print("JPEG -> ");
+ if(yuv == YUVDECODE)
+ System.out.print("YUV " + subName[subsamp] + " ... ");
+ else {
+ System.out.print(pfStr + " ");
+ if((flags & TJ.BOTTOMUP) != 0) System.out.print("Bottom-Up ");
+ else System.out.print("Top-Down ");
+ if(scaleNum != 1 || scaleDenom != 1)
+ System.out.print(scaleNum + "/" + scaleDenom + " ... ");
+ else System.out.print("... ");
+ }
+
+ t = getTime();
+ tjd.setJPEGBuffer(jpegBuf, jpegsize);
+ if(tjd.getWidth() != w || tjd.getHeight() != h
+ || tjd.getSubsamp() != subsamp)
+ throw new Exception("Incorrect JPEG header");
+
+ temp1 = scaledWidth;
+ temp2 = scaledHeight;
+ temp1 = tjd.getScaledWidth(temp1, temp2);
+ temp2 = tjd.getScaledHeight(temp1, temp2);
+ if(temp1 != scaledWidth || temp2 != scaledHeight)
+ throw new Exception("Scaled size mismatch");
+
+ if(yuv == YUVDECODE) bmpBuf = tjd.decompressToYUV(flags);
+ else {
+ if(bi)
+ img = tjd.decompress(scaledWidth, scaledHeight, biType[pf], flags);
+ else bmpBuf = tjd.decompress(scaledWidth, 0, scaledHeight, pf, flags);
+ }
+ t = getTime() - t;
+
+ if(bi) {
+ tempstr = baseFilename + "_dec_" + pfStr + "_"
+ + (((flags & TJ.BOTTOMUP) != 0) ? "BU" : "TD") + "_"
+ + subName[subsamp] + "_" + (double)scaleNum / (double)scaleDenom
+ + "x" + ".png";
+ File file = new File(tempstr);
+ ImageIO.write(img, "png", file);
+ }
+
+ if(yuv == YUVDECODE) {
+ if(checkBufYUV(bmpBuf, bmpBuf.length, w, h, subsamp) == 1)
+ System.out.print("Passed.");
+ else {
+ System.out.print("FAILED!"); exitStatus = -1;
+ }
+ }
+ else {
+ if((bi && checkImg(img, pf, subsamp, scaleNum, scaleDenom, flags) == 1)
+ || (!bi && checkBuf(bmpBuf, scaledWidth, scaledWidth
+ * TJ.getPixelSize(pf), scaledHeight, pf, subsamp, scaleNum,
+ scaleDenom, flags) == 1))
+ System.out.print("Passed.");
+ else {
+ System.out.print("FAILED!"); exitStatus = -1;
+ }
+ }
+ System.out.format(" %.6f ms\n", t * 1000.);
+ }
+
+ private static void genTestBMP(TJDecompressor tjd, byte[] jpegBuf,
+ int jpegsize, int w, int h, int pf, String baseFilename, int subsamp,
+ int flags) throws Exception {
+ int i;
+ if((subsamp == TJ.SAMP_444 || subsamp == TJ.SAMP_GRAY) && yuv == 0) {
+ TJ.ScalingFactor sf[] = TJ.getScalingFactors();
+ for(i = 0; i < sf.length; i++)
+ genTestBMP(tjd, jpegBuf, jpegsize, w, h, pf, baseFilename, subsamp,
+ flags, sf[i].num, sf[i].denom);
+ }
+ else
+ genTestBMP(tjd, jpegBuf, jpegsize, w, h, pf, baseFilename, subsamp,
+ flags, 1, 1);
+ System.out.print("\n");
+ }
+
+ private static void doTest(int w, int h, int[] formats, int subsamp,
+ String baseFilename) throws Exception {
+ TJCompressor tjc = null;
+ TJDecompressor tjd = null;
+ int size, pfstart, pfend;
+ byte[] jpegBuf;
+
+ if(yuv == YUVENCODE) jpegBuf = new byte[TJ.bufSizeYUV(w, h, subsamp)];
+ else jpegBuf = new byte[TJ.bufSize(w, h)];
+
+ try {
+ tjc = new TJCompressor();
+ tjd = new TJDecompressor();
+
+ for(int pf : formats) {
+ for(int i = 0; i < 2; i++) {
+ int flags = 0;
+ if(i == 1) {
+ if(yuv == YUVDECODE) {
+ tjc.close(); tjd.close(); return;
+ }
+ else flags |= TJ.BOTTOMUP;
+ }
+ size = genTestJPEG(tjc, jpegBuf, w, h, pf, baseFilename, subsamp,
+ 100, flags);
+ genTestBMP(tjd, jpegBuf, size, w, h, pf, baseFilename, subsamp,
+ flags);
+ }
+ }
+ }
+ catch(Exception e) {
+ if(tjc != null) tjc.close();
+ if(tjd != null) tjd.close();
+ throw e;
+ }
+ if(tjc != null) tjc.close();
+ if(tjd != null) tjd.close();
+ }
+
+ private final static int MAXLENGTH = 2048;
+
+ private static void doTest1() throws Exception {
+ int i, j, i2;
+ byte[] bmpBuf, jpegBuf;
+ TJCompressor tjc = null;
+
+ try {
+ tjc = new TJCompressor();
+ System.out.println("Buffer size regression test");
+ for(j = 1; j < 48; j++) {
+ for(i = 1; i < (j == 1 ? MAXLENGTH : 48); i++) {
+ if(i % 100 == 0)
+ System.out.format("%04d x %04d\b\b\b\b\b\b\b\b\b\b\b", i, j);
+ bmpBuf = new byte[i * j * 4];
+ jpegBuf = new byte[TJ.bufSize(i, j)];
+ Arrays.fill(bmpBuf, (byte)0);
+ for(i2 = 0; i2 < i * j; i2++) {
+ bmpBuf[i2 * 4] = pixels[i2 % 9][2];
+ bmpBuf[i2 * 4 + 1] = pixels[i2 % 9][1];
+ bmpBuf[i2 * 4 + 2] = pixels[i2 % 9][0];
+ }
+ tjc.setBitmapBuffer(bmpBuf, i, 0, j, TJ.PF_BGRX);
+ tjc.setSubsamp(TJ.SAMP_444);
+ tjc.setJPEGQuality(100);
+ tjc.compress(jpegBuf, 0);
+
+ bmpBuf = new byte[j * i * 4];
+ jpegBuf = new byte[TJ.bufSize(j, i)];
+ for(i2 = 0; i2 < j * i; i2++) {
+ if(i2 % 2 == 0) bmpBuf[i2 * 4] =
+ bmpBuf[i2 * 4 + 1] = bmpBuf[i2 * 4 + 2] = (byte)0xFF;
+ else bmpBuf[i2 * 4] = bmpBuf[i2 * 4 + 1] = bmpBuf[i2 * 4 + 2] = 0;
+ }
+ tjc.setBitmapBuffer(bmpBuf, j, 0, i, TJ.PF_BGRX);
+ tjc.compress(jpegBuf, 0);
+ }
+ }
+ System.out.println("Done. ");
+ }
+ catch(Exception e) {
+ if(tjc != null) tjc.close();
+ throw e;
+ }
+ if(tjc != null) tjc.close();
+ }
+
+ public static void main(String argv[]) {
+ try {
+ boolean doyuv = false;
+ for(int i = 0; i < argv.length; i++) {
+ if(argv[i].equalsIgnoreCase("-yuv")) doyuv = true;
+ if(argv[i].substring(0, 1).equalsIgnoreCase("-h")
+ || argv[i].equalsIgnoreCase("-?"))
+ usage();
+ if(argv[i].equalsIgnoreCase("-bi")) bi = true;
+ }
+ if(doyuv) yuv = YUVENCODE;
+ doTest(35, 39, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_444, "test");
+ doTest(39, 41, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_444, "test");
+ if(doyuv) {
+ doTest(41, 35, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_422,
+ "test");
+ doTest(35, 39, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_422,
+ "test");
+ doTest(39, 41, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_420,
+ "test");
+ doTest(41, 35, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_420,
+ "test");
+ }
+ doTest(35, 39, onlyGray, TJ.SAMP_GRAY, "test");
+ doTest(39, 41, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_GRAY,
+ "test");
+ doTest(41, 35, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_GRAY,
+ "test");
+ if(!doyuv && !bi) doTest1();
+ if(doyuv && !bi) {
+ yuv = YUVDECODE;
+ doTest(48, 48, onlyRGB, TJ.SAMP_444, "test");
+ doTest(35, 39, onlyRGB, TJ.SAMP_444, "test");
+ doTest(48, 48, onlyRGB, TJ.SAMP_422, "test");
+ doTest(39, 41, onlyRGB, TJ.SAMP_422, "test");
+ doTest(48, 48, onlyRGB, TJ.SAMP_420, "test");
+ doTest(41, 35, onlyRGB, TJ.SAMP_420, "test");
+ doTest(48, 48, onlyRGB, TJ.SAMP_GRAY, "test");
+ doTest(35, 39, onlyRGB, TJ.SAMP_GRAY, "test");
+ doTest(48, 48, onlyGray, TJ.SAMP_GRAY, "test");
+ doTest(39, 41, onlyGray, TJ.SAMP_GRAY, "test");
+ }
+ }
+ catch(Exception e) {
+ System.out.println(e);
+ exitStatus = -1;
+ }
+ System.exit(exitStatus);
+ }
}