gpt4 book ai didi

java - Jpeg DCT 和 IDCT 计算不正确

转载 作者:行者123 更新时间:2023-11-30 11:35:15 25 4
gpt4 key购买 nike

我正在尝试计算输入图像的 DCT 和 IDCT,并将 IDCT 输出显示为结果图像。但是我的 IDCT 值超过 300。我的输入图像是“.rgb”图像。我还将输入图像的高度和宽度视为常数,即 352*288

我将每个像素的输入红色、绿色和蓝色整数表示为 rgb[3][64][1583],其中 [3] -> 红色/绿色/蓝色索引和 [64] -> 像素索引在每个 block 和 [1583]->8*8 block 的索引,即1583个 block 中的一个 block 。

最后,我保留我的量化表,因为它具有统一的值 -> 2^N,其中 N 作为参数传递。在此代码中,quantLevel 是上面的 N。

以下是我的代码:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Jpeg {
double rgb[][][]=new double[3][64][1584];
double rgbfinal[][][]=new double[3][64][1584];
double R[][]=new double[64][1584];
double G[][]=new double[64][1584];
double B[][]=new double[64][1584];

public void go(String fname, int quantLevel){
int numBlocks=(352*288)/64;

String fileName = fname;
int width=352,height=288;
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

try {
File file = new File(fname);
InputStream is = new FileInputStream(file);

long len = file.length();
byte[] bytes = new byte[(int)len];

int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}
int ind = 0;
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
byte r = bytes[ind];
byte g = bytes[ind+height*width];
byte b = bytes[ind+height*width*2];
int pix = 0xff000000 | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
img.setRGB(x,y,pix);
ind++;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

int indexRow=0,indexCol=0,indexBlock=0,indexBits=0,indexPixelBlock=0,indexPixel=0;
long count=0L;
String binary="";

indexPixel=0;
indexBlock=0;
int i=0;
while(count!=(long)(numBlocks*64)){
int pix = img.getRGB(indexCol, indexRow);
int red = (pix >> 16) & 0x000000FF;
int green = (pix >>8 ) & 0x000000FF;
int blue = (pix) & 0x000000FF;

rgb[0][indexPixel][indexBlock]=red;
rgb[1][indexPixel][indexBlock]=green;
rgb[2][indexPixel][indexBlock]=blue;

count++;
indexPixel++;

if(indexCol==width-1 && indexRow==height-1)
break;

if(indexCol%7==0 && indexCol!=0 && indexPixel%8==0)
{
indexPixel=indexPixelBlock;
indexBlock++;
}

if(indexPixel%8==0 && indexCol%7!=0 && indexBlock!=1583)
{
indexPixel=indexPixelBlock;
indexBlock++;
}

if(indexCol==width-1)
{
indexCol=0;
indexRow++;
}
else
indexCol++;

if((indexPixel)%8==0 && indexBlock==numBlocks-1 && indexCol%7==0)
{
indexBlock=0;
indexPixelBlock=indexPixel;
}
}
calcQuantizedDCT(quantLevel);
calcInverseDCT(quantLevel);

JFrame frame = new JFrame();
frame.setLocation(0,0);
frame.setSize(1024, 720);
frame.getContentPane().setBackground(Color.WHITE);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JPanel p=new JPanel();
p.setLayout(new FlowLayout(FlowLayout.LEFT));
p.setLocation(100,100);

JLabel label = new JLabel(new ImageIcon(img));
label.setLocation(0,0);
label.setSize(352,288);

p.add(label);
frame.add(p);
frame.setVisible(true);

return;
}

void calcQuantizedDCT(int quantLevel)
{
String binary="";
int indexBlock=0,indexPixel=0,indexBits=0,red=0,green=0,blue=0,x=0,y=0,indexPixelTemp=0,u=0,v=0;

double sumRed=0,sumGreen=0,sumBlue=0;
String substr="";
int i=0;
for(indexBlock=0;indexBlock<1584;indexBlock++)
{
indexPixel=0;
//
while(indexPixel!=64 && u<8)
{
while(indexPixelTemp<64 && x<8)
{
red=(int)rgb[0][indexPixelTemp][indexBlock];
green=(int)rgb[1][indexPixelTemp][indexBlock];
blue=(int)rgb[2][indexPixelTemp][indexBlock];
// System.out.println(red);
sumRed+=red*Math.cos((Math.PI*(2*y+1)*u)/(2*8))*Math.cos((Math.PI*(2*x+1)*v)/(2*8));
sumGreen+=green*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));
sumBlue+=blue*Math.cos((Math.PI*(2*x+1)*u)/(16))*Math.cos((Math.PI*(2*y+1)*v)/(16));

indexPixelTemp++;
y++;
if(y==8)
{
x++;
y=0;
}

}
//System.out.println("SumRed :"+sumRed);

if(u==0 && v==0)
{
//System.out.println("U & V & Pixel & Block "+u+" "+v+" "+indexPixel+" "+indexBlock);
R[indexPixel][indexBlock]=(Math.sqrt(1.0/64.0)*sumRed)/Math.pow(2,quantLevel);
G[indexPixel][indexBlock]=(Math.sqrt(1.0/64.0)*sumGreen)/Math.pow(2,quantLevel);
B[indexPixel][indexBlock]=(Math.sqrt(1.0/64.0)*sumBlue)/Math.pow(2,quantLevel);
}
else
{
//System.out.println("U & V & Pixel & Block "+u+" "+v+" "+indexPixel+" "+indexBlock);
R[indexPixel][indexBlock]=(Math.sqrt(2.0/32.0)*sumRed)/Math.pow(2,quantLevel);
G[indexPixel][indexBlock]=(Math.sqrt(2.0/32.0)*sumGreen)/Math.pow(2,quantLevel);
B[indexPixel][indexBlock]=(Math.sqrt(2.0/32.0)*sumBlue)/Math.pow(2,quantLevel);
}

indexPixel++;

if(indexPixel==64)
break;
indexPixelTemp=0;
v++;

if(v==8)
{
v=0;
u++;
}
x=0;y=0;sumGreen=0;sumRed=0;sumBlue=0;
}

u=0;v=0;
}

/* for(int j=0;j<64;j++)
{
System.out.print(R[j][0]+" ");
if(j%7==0 && j!=0)
System.out.println();
}
*/
}

void calcInverseDCT(int quantLevel)
{
String binary="";
int indexBlock=0,indexPixel=0,indexBits=0,u=0,v=0,x=0,y=0,indexPixelTemp=0,sumRed=0,sumGreen=0,sumBlue=0,red=0,green=0,blue=0;

for(indexBlock=0;indexBlock<1584;indexBlock++)
{
for(indexPixel=0;indexPixel<64;indexPixel++)
{
R[indexPixel][indexBlock]=R[indexPixel][indexBlock]*Math.pow(2,quantLevel);
G[indexPixel][indexBlock]=G[indexPixel][indexBlock]*Math.pow(2,quantLevel);
B[indexPixel][indexBlock]=B[indexPixel][indexBlock]*Math.pow(2,quantLevel);

}
}
int i=0;
indexPixelTemp=0;
indexPixel=0;
for(indexBlock=0;indexBlock<1584;indexBlock++)
{
indexPixel=0;
while(indexPixel<64 && x<8)
{
indexPixelTemp=0;
while(indexPixelTemp<64 && u<8)
{
red=(int)R[indexPixelTemp][indexBlock];
if(u==0 && v==0)
sumRed+=Math.sqrt(1.0/2.0)*red*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));
else
sumRed+=red*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));

green=(int)G[indexPixelTemp][indexBlock];
if(u==0 && v==0)
sumGreen+=Math.sqrt(1.0/2.0)*green*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));
else
sumGreen+=green*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));

blue=(int)B[indexPixelTemp][indexBlock];
if(u==0 && v==0)
sumBlue+=Math.sqrt(1.0/2.0)*blue*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));
else
sumBlue+=blue*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));

indexPixelTemp++;
v++;
if(v==8)
{
u++;
v=0;
}
}

rgbfinal[0][indexPixel][indexBlock]=sumRed;
rgbfinal[1][indexPixel][indexBlock]=sumGreen;
rgbfinal[2][indexPixel][indexBlock]=sumBlue;

indexPixel++;
indexPixelTemp=0;
y++;

if(y==8)
{
y=0;
x++;
}
u=0;v=0;sumGreen=0;sumRed=0;sumBlue=0;
}
if(i==3)
break;
x=0;y=0;
}

System.out.println();
/*for(i=0;i<64;i++)
{
System.out.print(rgbfinal[0][i][0]+" ");
if(i%7==0 && i!=0)
System.out.println();
}*/
}

public static void main(String args[]){
Jpeg a = new Jpeg();
a.go("src/image2.rgb",0);
}
}

我没有尝试显示输出图像,因为我检查过的红色 IDCT 输出超过 255。

请帮忙。

最佳答案

首先,您是否希望创建一个与 JPEG 兼容的编解码器?或者您只是在玩弄多媒体编码概念?如果是后者,那么给你更多的力量。如果是前者,您还有很多工作要做。

直接回答您的问题:使用 2D 前向 DCT 转换 8x8 block 并获得超过 255 的数字是正常的。前向 DCT 的低级实现通常采用无符号 8 位样本的 8x8 vector 作为输入并输出带符号的 16 位样本的 8x8 vector 。

如果您真的希望创建一个与 JPEG 兼容的编解码器,您仍然有一些主题需要研究。对于初学者,JPEG 不压缩 RGB。 RGB 数据被转换为 YUV,这些 block 被转换(然后量化、之字形和熵编码)。

关于java - Jpeg DCT 和 IDCT 计算不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15215216/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com