📄 j2kview.cs
字号:
using System;using System.IO;using System.Text;using System.Text.RegularExpressions;using System.Drawing;using System.Windows.Forms;using System.Runtime.InteropServices;using System.Security.Cryptography;using System.Xml;using System.Xml.Serialization;unsafe class J2000 { const int J2K_MAXRLVLS=33; const int J2K_MAXBANDS=3*J2K_MAXRLVLS+1; public class Math { static public int ceildiv(int a, int b) { return (a+b-1)/b; } } [StructLayout(LayoutKind.Sequential)] public struct j2k_comp_t { public int dx, dy; public int prec; public int sgnd; public int *data; }; [StructLayout(LayoutKind.Sequential)] public struct j2k_image_t { public int x0, y0; public int x1, y1; public int numcomps; public j2k_comp_t *comps; }; [StructLayout(LayoutKind.Sequential)] public struct j2k_stepsize_t { public int expn; public int mant; }; [StructLayout(LayoutKind.Sequential)] public struct j2k_tccp_t { public int csty; public int numresolutions; public int cblkw; public int cblkh; public int cblksty; public int qmfbid; public int qntstypublic ; [MarshalAs(UnmanagedType.ByValArray, SizeConst=J2K_MAXBANDS)] public j2k_stepsize_t[] stepsizes; public int numgbits; public int roishift; [MarshalAs(UnmanagedType.ByValArray, SizeConst=J2K_MAXRLVLS)] public int[] prcw; [MarshalAs(UnmanagedType.ByValArray, SizeConst=J2K_MAXRLVLS)] public int[] prch; }; [StructLayout(LayoutKind.Sequential)] public struct j2k_poc_t { public int resno0, compno0; public int layno1, resno1, compno1; public int prg; }; [StructLayout(LayoutKind.Sequential)] public struct j2k_tcp_t { public int csty; public int prg; public int numlayers; public int mct; [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)] public int[] rates; public int numpocs; [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)] public j2k_poc_t[] pocs; public j2k_tccp_t *tccps; } [StructLayout(LayoutKind.Sequential)] public struct j2k_cp_t { public int tx0, ty0; public int tdx, tdy; public int tw, th; public j2k_tcp_t *tcps; } [DllImport("libj2k.dll", EntryPoint="j2k_decode")] static extern int j2k_decode(byte *src, int len, j2k_image_t **i, j2k_cp_t **cp); static public j2k_image_t* Decode(byte[] src) { j2k_image_t *img; j2k_cp_t *cp; fixed (byte *p=src) { j2k_decode(p, src.Length, &img, &cp); } return img; } static public Bitmap BitmapFromComp(j2k_image_t *img, int compno, out string hash) { j2k_comp_t *comp=&img->comps[compno]; int w=Math.ceildiv(img->x1-img->x0, comp->dx); int h=Math.ceildiv(img->y1-img->y0, comp->dy); int prec=comp->prec; bool sgnd=comp->sgnd!=0; Bitmap bmp=new Bitmap(w, h); HashAlgorithm md5=new MD5CryptoServiceProvider(); CryptoStream cs=new CryptoStream(Stream.Null, md5, CryptoStreamMode.Write); BinaryWriter bw=new BinaryWriter(cs); for (int j=0; j<h; j++) { for (int i=0; i<w; i++) { int v, c; v=comp->data[i+j*w]; if (sgnd) c=(int)(128+v*127.0/(1<<(prec-1))); else c=(int)(v*255.0/(1<<prec)); bmp.SetPixel(i, j, Color.FromArgb(255, c, c, c)); bw.Write(v); } } bw.Close(); hash=Convert.ToBase64String(md5.Hash); return bmp; }}unsafe class J2KView:Form { J2000.j2k_image_t *img; public static int Main(string[] args) { try { Application.Run(new J2KView(args[0])); } catch (Exception e) { Console.WriteLine(e.Message); Console.ReadLine(); } return 0; } string[] hash; TabControl tc; public J2KView(string filename) { FileStream fs=new FileStream(filename, FileMode.Open, FileAccess.Read); BinaryReader br=new BinaryReader(fs); byte[] src=new byte[fs.Length]; br.Read(src, 0, src.Length); img=J2000.Decode(src); Text="J2000.J2KView"; tc=new TabControl(); Controls.Add(tc); System.Console.WriteLine("numcomps="+img->numcomps); hash=new string[img->numcomps]; for (int i=0; i<img->numcomps; i++) { TabPage tp=new TabPage(); tp.Text="c"+i; tc.Controls.Add(tp); PictureBox pb=new PictureBox(); pb.Image=J2000.BitmapFromComp(img, i, out hash[i]); pb.SizeMode=PictureBoxSizeMode.AutoSize; tp.Controls.Add(pb); tp.AutoScroll=true; ContextMenu cm=new ContextMenu(); cm.MenuItems.Add("&MD5", new EventHandler(PrintHashCode)); cm.MenuItems.Add("&PSNR", new EventHandler(PrintPSNR)); tp.ContextMenu=cm; } tc.Dock=DockStyle.Fill; } private void PrintHashCode(object sender, EventArgs e) { MessageBox.Show(hash[tc.SelectedIndex], "MD5"); } private void PrintPSNR(object sender, EventArgs e) { OpenFileDialog d=new OpenFileDialog(); d.Filter="PGX files (*.pgx)|*.pgx"; if (d.ShowDialog()!=DialogResult.OK) return; try { double psnr=CalcPSNR(tc.SelectedIndex, d.FileName); MessageBox.Show(20*Math.Log10(psnr)+" dB", "PSNR"); } catch (Exception ex) { MessageBox.Show("Failed to compute PSNR. "+ex.Message, "Error"); } } private static string ReadLine(BinaryReader br) { StringBuilder sb=new StringBuilder(); char c; while ((c=br.ReadChar())!='\n') { sb.Append(c); } return sb.ToString(); } private double CalcPSNR(int compno, string filename) { J2000.j2k_comp_t *comp=&img->comps[compno]; FileStream f=new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read); BinaryReader br=new BinaryReader(f); Regex r=new Regex(@"[\s]+"); string[] head=r.Split(ReadLine(br)); if (head[0]!="PG") throw new Exception("Not a PGX file"); bool bigendian=head[1]=="ML"; int prec=Math.Abs(int.Parse(head[2])); bool sgnd=int.Parse(head[2])<0; int w=int.Parse(head[3]); int h=int.Parse(head[4]); if (prec!=comp->prec) throw new Exception("Precision mismatch"); if (sgnd!=(comp->sgnd!=0)) throw new Exception("Signedness mismatch"); if (w!=J2000.Math.ceildiv(img->x1-img->x0, comp->dx) || h!=J2000.Math.ceildiv(img->y1-img->y0, comp->dy)) throw new Exception("Dimensions mismatch"); double s=0, n=0; for (int j=0; j<h; j++) { for (int i=0; i<w; i++) { int v1, v2; v1=comp->data[i+j*w]; if (prec<=8) { v2=sgnd?(int)br.ReadSByte():(int)br.ReadByte(); } else if (prec<=16) { v2=sgnd?(int)br.ReadInt16():(int)br.ReadUInt16(); if (bigendian) v2=System.Net.IPAddress.HostToNetworkOrder((short)v2); } else { v2=sgnd?(int)br.ReadInt32():(int)br.ReadUInt32(); if (bigendian) v2=System.Net.IPAddress.HostToNetworkOrder(v2); } s+=Math.Pow((double)v1, 2); n+=Math.Pow((double)(v1-v2), 2); } } double psnr=Math.Sqrt(s/n); return psnr; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -