试题编号: | 202212-3 |
试题名称: | JPEG 解码 |
时间限制: | 1.0s |
内存限制: | 512.0MB |
问题描述: | 问题背景四年一度的世界杯即将画上尾声。在本次的世界杯比赛中,视频助理裁判(Video Assistant Referee, VAR)的应用可谓是大放异彩。VAR 使用视频回放技术帮助主裁判作出正确判罚决定。西西艾弗岛足球联赛的赛场上也引入了一套 VAR 设备。作为技术供应商的技术主管小C,需要存储和编码 VAR 产生的图像数据。小 C 分析比较发现,JPEG 编码算法可以达到较好的压缩效果,并且质量损失是可以接受的。因此,小 C 决定使用 JPEG 编码算法来存储和传输图像数据。JPEG 是一种常用的图片有损压缩算法,它的压缩率高,但是压缩后的图片质量下降较多。JPEG 图片的压缩率一般在 10:1 到 20:1 之间,一般用于存储照片等图片质量要求不高的场景。 为了简化问题,我们以灰度图片为例,介绍 JPEG 编码算法的过程。一张灰度图片,可以被视为由多个像素点组成。每个像素点对应一个 0 到 255 之间的数值,用于表示像素点的亮度。JPEG 编码算法将图片分割为 8×8 的小块,每个小块被称作一个最小编码单元。对每个小块进行如下的计算:
最后,将得到的各个小块的扫描数据采用哈夫曼编码进行压缩,并置于必要的数据结构中,就能得到一张 JPEG 图片了。 样例输入: 样例输出: 样例说明本组样例即为题目描述中的样例。 子任务对于 20% 的数据,有 𝑇=0; 对于 40% 的数据,有 𝑇=0 或 1; 对于 100% 的数据,有 𝑇∈{0,1,2},且 𝑛∈[0,64],并且量化矩阵中的各个元素 𝑞𝑖,𝑗 满足 0<𝑞𝑖,𝑗<256,扫描序列中的各个元素 𝑚𝑖 满足 −256<𝑚𝑖<256。 提示在 C/C++ 语言中,可以通过包含 在 Python 语言中,可以通过 在 Java 语言中,可以使用 |
import java.util.*;
public class Main {
static int[][] arr;
static int[][] liang;
public Main(int[][] at) {
arr=at;
liang=new int[][]{
{1,2,6,7,15,16,28,29},
{3,5,8,14,17,27,30,43},
{4,9,13,18,26,31,42,44},
{10,12,19,25,32,41,45,54},
{11,20,24,33,40,46,53,55},
{21,23,34,39,47,52,56,61},
{22,35,38,48,51,57,60,62},
{36,37,49,50,58,59,63,64}};
}
public static void getliang(String l) {
String[] input=l.split(" ");
for(int i=0;i<8;i++){
for(int j=0;j<8;j++){
int temp=liang[i][j];
if(temp>input.length){
liang[i][j]=0;
}else{
liang[i][j]=Integer.parseInt(input[temp-1]);
}
}
}
}
public static void display(){
for(int i=0;i<8;i++){
for(int j=0;j<7;j++){
System.out.print(liang[i][j]+" ");
}
System.out.println(liang[i][7]);
}
}
public static void cheng(){
for(int i=0;i<8;i++){
for(int j=0;j<8;j++){
int temp=liang[i][j];
liang[i][j]=temp*arr[i][j];
}
}
}
public static double geta(int a){
if(a==0){
return Math.sqrt((double) 1/2);
}else{
return 1;
}
}
public static void change(){
double[][] newliang=new double[8][8];
for(int i=0;i<8;i++){
for(int j=0;j<8;j++){
double num=0;
for(int u=0;u<8;u++){
for(int v=0;v<8;v++){
double t1=geta(u);
double t2=geta(v);
double t3=Math.cos(Math.PI/8*(i+ (double) 1 /2)*u);
double t4=Math.cos(Math.PI/8*(j+ (double) 1 /2)*v);
num+=t1*t2*liang[u][v]*t3*t4;
}
}
newliang[i][j]=(float)1/4*num;
}
}
for(int i=0;i<8;i++){
for(int j=0;j<8;j++){
liang[i][j]= Math.round((float) newliang[i][j]+128);
if(liang[i][j]>255){
liang[i][j]=255;
}
if(liang[i][j]<0){
liang[i][j]=0;
}
}
}
}
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int[][] at=new int[8][8];
for(int i=0;i<8;i++){
String[] input=in.nextLine().split(" ");
for(int j=0;j<8;j++){
at[i][j]=Integer.parseInt(input[j]);
}
}
int num=in.nextInt();
int t=in.nextInt();
in.nextLine();
String liang=in.nextLine();
Main ts=new Main(at);
getliang(liang);
if(t==0){
display();
}else if(t==1){
ts.cheng();
display();
}else if(t==2){
ts.cheng();
change();
display();
}
}
}