📄 jpegencoder.java
字号:
System.out.println("IO Error: " + e.getMessage()); } if (c == 0xFF) { try { outStream.write(0); } catch (IOException e) { System.out.println("IO Error: " + e.getMessage()); } } PutBuffer <<= 8; PutBits -= 8; } bufferPutBuffer = PutBuffer; bufferPutBits = PutBits; } void flushBuffer(BufferedOutputStream outStream) { int PutBuffer = bufferPutBuffer; int PutBits = bufferPutBits; while (PutBits >= 8) { int c = ((PutBuffer >> 16) & 0xFF); try { outStream.write(c); } catch (IOException e) { System.out.println("IO Error: " + e.getMessage()); } if (c == 0xFF) { try { outStream.write(0); } catch (IOException e) { System.out.println("IO Error: " + e.getMessage()); } } PutBuffer <<= 8; PutBits -= 8; } if (PutBits > 0) { int c = ((PutBuffer >> 16) & 0xFF); try { outStream.write(c); } catch (IOException e) { System.out.println("IO Error: " + e.getMessage()); } } } /* * Initialisation of the Huffman codes for Luminance and Chrominance. * This code results in the same tables created in the IJG Jpeg-6a * library. */ public void initHuf() { DC_matrix0=new int[12][2]; DC_matrix1=new int[12][2]; AC_matrix0=new int[255][2]; AC_matrix1=new int[255][2]; DC_matrix = new Object[2]; AC_matrix = new Object[2]; int p, l, i, lastp, si, code; int[] huffsize = new int[257]; int[] huffcode= new int[257]; /* * init of the DC values for the chrominance * [][0] is the code [][1] is the number of bit */ p = 0; for (l = 1; l <= 16; l++) { for (i = 1; i <= bitsDCchrominance[l]; i++) { huffsize[p++] = l; } } huffsize[p] = 0; lastp = p; code = 0; si = huffsize[0]; p = 0; while(huffsize[p] != 0) { while(huffsize[p] == si) { huffcode[p++] = code; code++; } code <<= 1; si++; } for (p = 0; p < lastp; p++) { DC_matrix1[valDCchrominance[p]][0] = huffcode[p]; DC_matrix1[valDCchrominance[p]][1] = huffsize[p]; } /* * Init of the AC hufmann code for the chrominance * matrix [][][0] is the code & matrix[][][1] is the number of bit needed */ p = 0; for (l = 1; l <= 16; l++) { for (i = 1; i <= bitsACchrominance[l]; i++) { huffsize[p++] = l; } } huffsize[p] = 0; lastp = p; code = 0; si = huffsize[0]; p = 0; while(huffsize[p] != 0) { while(huffsize[p] == si) { huffcode[p++] = code; code++; } code <<= 1; si++; } for (p = 0; p < lastp; p++) { AC_matrix1[valACchrominance[p]][0] = huffcode[p]; AC_matrix1[valACchrominance[p]][1] = huffsize[p]; } /* * init of the DC values for the luminance * [][0] is the code [][1] is the number of bit */ p = 0; for (l = 1; l <= 16; l++) { for (i = 1; i <= bitsDCluminance[l]; i++) { huffsize[p++] = l; } } huffsize[p] = 0; lastp = p; code = 0; si = huffsize[0]; p = 0; while(huffsize[p] != 0) { while(huffsize[p] == si) { huffcode[p++] = code; code++; } code <<= 1; si++; } for (p = 0; p < lastp; p++) { DC_matrix0[valDCluminance[p]][0] = huffcode[p]; DC_matrix0[valDCluminance[p]][1] = huffsize[p]; } /* * Init of the AC hufmann code for luminance * matrix [][][0] is the code & matrix[][][1] is the number of bit */ p = 0; for (l = 1; l <= 16; l++) { for (i = 1; i <= bitsACluminance[l]; i++) { huffsize[p++] = l; } } huffsize[p] = 0; lastp = p; code = 0; si = huffsize[0]; p = 0; while(huffsize[p] != 0) { while(huffsize[p] == si) { huffcode[p++] = code; code++; } code <<= 1; si++; } for (int q = 0; q < lastp; q++) { AC_matrix0[valACluminance[q]][0] = huffcode[q]; AC_matrix0[valACluminance[q]][1] = huffsize[q]; } DC_matrix[0] = DC_matrix0; DC_matrix[1] = DC_matrix1; AC_matrix[0] = AC_matrix0; AC_matrix[1] = AC_matrix1; }}/* * JpegInfo - Given an image, sets default information about it and divides * it into its constituant components, downsizing those that need to be. */class JpegInfo{ String Comment; public Image imageobj; public int imageHeight; public int imageWidth; public int BlockWidth[]; public int BlockHeight[];// the following are set as the default public int Precision = 8; public int NumberOfComponents = 3; public Object Components[]; public int[] CompID = {1, 2, 3}; //public int[] HsampFactor = {1, 1, 1}; //public int[] VsampFactor = {1, 1, 1}; public int[] HsampFactor = {2, 1, 1}; public int[] VsampFactor = {2, 1, 1}; public int[] QtableNumber = {0, 1, 1}; public int[] DCtableNumber = {0, 1, 1}; public int[] ACtableNumber = {0, 1, 1}; public boolean[] lastColumnIsDummy = {false, false, false}; public boolean[] lastRowIsDummy = {false, false, false}; public int Ss = 0; public int Se = 63; public int Ah = 0; public int Al = 0; public int compWidth[], compHeight[]; public int MaxHsampFactor; public int MaxVsampFactor; public JpegInfo(Image image, String comment) { Components = new Object[NumberOfComponents]; compWidth = new int[NumberOfComponents]; compHeight = new int[NumberOfComponents]; BlockWidth = new int[NumberOfComponents]; BlockHeight = new int[NumberOfComponents]; imageobj = image; imageWidth = image.getWidth(null); imageHeight = image.getHeight(null); //Comment = "JPEG Encoder Copyright 1998, James R. Weeks and BioElectroMech. "; Comment = comment; getYCCArray(); } public void setComment(String comment) { Comment.concat(comment); } public String getComment() { return Comment; } /* * This method creates and fills three arrays, Y, Cb, and Cr using the * input image. */ private void getYCCArray() { int values[] = new int[imageWidth * imageHeight]; int r, g, b, y, x;// In order to minimize the chance that grabPixels will throw an exception// it may be necessary to grab some pixels every few scanlines and process// those before going for more. The time expense may be prohibitive.// However, for a situation where memory overhead is a concern, this may be// the only choice. PixelGrabber grabber = new PixelGrabber(imageobj.getSource(), 0, 0, imageWidth, imageHeight, values, 0, imageWidth); MaxHsampFactor = 1; MaxVsampFactor = 1; for (y = 0; y < NumberOfComponents; y++) { MaxHsampFactor = Math.max(MaxHsampFactor, HsampFactor[y]); MaxVsampFactor = Math.max(MaxVsampFactor, VsampFactor[y]); }if(false) { for (y = 0; y < NumberOfComponents; y++) { compWidth[y] = (((imageWidth%8 != 0) ? ((int) Math.ceil((double) imageWidth/8.0))*8 : imageWidth)/MaxHsampFactor)*HsampFactor[y]; if (compWidth[y] != ((imageWidth/MaxHsampFactor)*HsampFactor[y])) { lastColumnIsDummy[y] = true; } // results in a multiple of 8 for compWidth // this will make the rest of the program fail for the unlikely // event that someone tries to compress an 16 x 16 pixel image // which would of course be worse than pointless BlockWidth[y] = (int) Math.ceil((double) compWidth[y]/8.0); compHeight[y] = (((imageHeight%8 != 0) ? ((int) Math.ceil((double) imageHeight/8.0))*8: imageHeight)/MaxVsampFactor)*VsampFactor[y]; if (compHeight[y] != ((imageHeight/MaxVsampFactor)*VsampFactor[y])) { lastRowIsDummy[y] = true; } BlockHeight[y] = (int) Math.ceil((double) compHeight[y]/8.0); }} else { for (y = 0; y < NumberOfComponents; y++) { compWidth[y] = (( (imageWidth%8 != 0) ? ((int) Math.ceil((double) imageWidth/8.0))*8 : imageWidth) /MaxHsampFactor)*HsampFactor[y]; if (compWidth[y] != ((imageWidth/MaxHsampFactor)*HsampFactor[y])) { lastColumnIsDummy[y] = true; } // results in a multiple of 8 for compWidth // this will make the rest of the program fail for the unlikely // event that someone tries to compress an 16 x 16 pixel image // which would of course be worse than pointless BlockWidth[y] = (int) Math.ceil((double) compWidth[y]/8.0); compHeight[y] = (( (imageHeight%8 != 0) ? ((int) Math.ceil((double) imageHeight/8.0))*8: imageHeight) /MaxVsampFactor)*VsampFactor[y]; if (compHeight[y] != ((imageHeight/MaxVsampFactor)*VsampFactor[y])) { lastRowIsDummy[y] = true; } BlockHeight[y] = (int) Math.ceil((double) compHeight[y]/8.0); }} try { if(grabber.grabPixels() != true) { try { throw new AWTException("Grabber returned false: " + grabber.getStatus()); } catch (Exception e) {}; } } catch (InterruptedException e) {}; float Y[][] = new float[compHeight[0]][compWidth[0]]; float Cr1[][] = new float[compHeight[0]][compWidth[0]]; float Cb1[][] = new float[compHeight[0]][compWidth[0]]; float Cb2[][] = new float[compHeight[1]][compWidth[1]]; float Cr2[][] = new float[compHeight[2]][compWidth[2]]; int index = 0; for (y = 0; y < imageHeight; ++y) { for (x = 0; x < imageWidth; ++x) { r = ((values[index] >> 16) & 0xff); g = ((values[index] >> 8) & 0xff); b = (values[index] & 0xff);// The following three lines are a more correct color conversion but// the current conversion technique is sufficient and results in a higher// compression rate.// Y[y][x] = 16 + (float)(0.8588*(0.299 * (float)r + 0.587 * (float)g + 0.114 * (float)b ));// Cb1[y][x] = 128 + (float)(0.8784*(-0.16874 * (float)r - 0.33126 * (float)g + 0.5 * (float)b));// Cr1[y][x] = 128 + (float)(0.8784*(0.5 * (float)r - 0.41869 * (float)g - 0.08131 * (float)b)); Y[y][x] = (float)((0.299 * (float)r + 0.587 * (float)g + 0.114 * (float)b)); Cb1[y][x] = 128 + (float)((-0.16874 * (float)r - 0.33126 * (float)g + 0.5 * (float)b)); Cr1[y][x] = 128 + (float)((0.5 * (float)r - 0.41869 * (float)g - 0.08131 * (float)b)); index++; } }// Need a way to set the H and V sample factors before allowing downsampling.// For now (04/04/98) downsampling must be hard coded.// Until a better downsampler is implemented, this will not be done.// Downsampling is currently supported. The downsampling method here// is a simple box filter. Components[0] = Y; if (false) { // Cb2 = DownSample(Cb1, 1); Components[1] = Cb1; // Cr2 = DownSample(Cr1, 2); Components[2] = Cr1; } else { Cb2 = DownSample(Cb1, 1); Components[1] = Cb2; Cr2 = DownSample(Cr1, 2); Components[2] = Cr2; } } float[][] DownSample(float[][] C, int comp) { int inrow, incol; int outrow, outcol; float output[][]; float temp; int bias; inrow = 0; incol = 0; output = new float[compHeight[comp]][compWidth[comp]]; for (outrow = 0; outrow < compHeight[comp]; outrow++) { bias = 1; for (outcol = 0; outcol < compWidth[comp]; outcol++) {//System.out.println("outcol="+outcol); temp = C[inrow][incol++]; // 00 temp += C[inrow++][incol--]; // 01 temp += C[inrow][incol++]; // 10 temp += C[inrow--][incol++] + (float)bias; // 11 -> 02 output[outrow][outcol] = temp/(float)4.0; bias ^= 3; } inrow += 2; incol = 0; } return output; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -