private static List <GfxImage> UnpackIco(byte[] pb) { if (pb == null) { Debug.Assert(false); return(null); } const int SizeICONDIR = 6; const int SizeICONDIRENTRY = 16; Debug.Assert(BitConverter.ToInt32(new byte[] { 1, 2, 3, 4 }, 0) == 0x04030201); // Little-endian if (pb.Length < SizeICONDIR) { return(null); } if (BitConverter.ToUInt16(pb, 0) != 0) { return(null); // Reserved, 0 } if (BitConverter.ToUInt16(pb, 2) != 1) { return(null); // ICO type, 1 } int n = BitConverter.ToUInt16(pb, 4); if (n < 0) { Debug.Assert(false); return(null); } int cbDir = SizeICONDIR + (n * SizeICONDIRENTRY); if (pb.Length < cbDir) { return(null); } List <GfxImage> l = new List <GfxImage>(); int iOffset = SizeICONDIR; for (int i = 0; i < n; ++i) { int w = pb[iOffset]; int h = pb[iOffset + 1]; if ((w < 0) || (h < 0)) { Debug.Assert(false); return(null); } int cb = BitConverter.ToInt32(pb, iOffset + 8); if (cb <= 0) { return(null); // Data must have header (even BMP) } int p = BitConverter.ToInt32(pb, iOffset + 12); if (p < cbDir) { return(null); } if ((p + cb) > pb.Length) { return(null); } try { byte[] pbImage = MemUtil.Mid <byte>(pb, p, cb); GfxImage img = new GfxImage(pbImage, w, h); l.Add(img); } catch (Exception) { Debug.Assert(false); return(null); } iOffset += SizeICONDIRENTRY; } return(l); }
private static Image ExtractBestImageFromIco(byte[] pb) { List <GfxImage> l = UnpackIco(pb); if ((l == null) || (l.Count == 0)) { return(null); } long qMax = 0; foreach (GfxImage gi in l) { if (gi.Width == 0) { gi.Width = 256; } if (gi.Height == 0) { gi.Height = 256; } qMax = Math.Max(qMax, (long)gi.Width * (long)gi.Height); } byte[] pbHdrPng = new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; byte[] pbHdrJpeg = new byte[] { 0xFF, 0xD8, 0xFF }; Image imgBest = null; int bppBest = -1; foreach (GfxImage gi in l) { if (((long)gi.Width * (long)gi.Height) < qMax) { continue; } byte[] pbImg = gi.Data; Image img = null; try { if ((pbImg.Length > pbHdrPng.Length) && MemUtil.ArraysEqual(pbHdrPng, MemUtil.Mid <byte>(pbImg, 0, pbHdrPng.Length))) { img = GfxUtil.LoadImage(pbImg); } else if ((pbImg.Length > pbHdrJpeg.Length) && MemUtil.ArraysEqual(pbHdrJpeg, MemUtil.Mid <byte>(pbImg, 0, pbHdrJpeg.Length))) { img = GfxUtil.LoadImage(pbImg); } else { MemoryStream ms = new MemoryStream(pb, false); try { Icon ico = new Icon(ms, gi.Width, gi.Height); img = ico.ToBitmap(); ico.Dispose(); } finally { ms.Close(); } } } catch (Exception) { Debug.Assert(false); } if (img == null) { continue; } if ((img.Width < gi.Width) || (img.Height < gi.Height)) { Debug.Assert(false); img.Dispose(); continue; } int bpp = GetBitsPerPixel(img.PixelFormat); if (bpp > bppBest) { if (imgBest != null) { imgBest.Dispose(); } imgBest = img; bppBest = bpp; } else { img.Dispose(); } } return(imgBest); }