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; jdata[i+j*w]; if (sgnd) c=(int)(128+v*127.0/(1<<(prec-1))); else c=(int)(v*255.0/(1<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; jdata[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; } }