Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }