Example #1
0
        private Image CreateImage(GeckoWebBrowser browser)
        {
            if (_syncControl.InvokeRequired)
            {
                return((Image)_syncControl.Invoke(new Func <GeckoWebBrowser, Image>(CreateImage), browser));
            }

#if __MonoCS__
            var offscreenBrowser = browser as OffScreenGeckoWebBrowser;
            Debug.Assert(offscreenBrowser != null);

            return(offscreenBrowser.GetBitmap(browser.Width, browser.Height));
#else
            var    creator    = new ImageCreator(browser);
            byte[] imageBytes = creator.CanvasGetPngImage((uint)browser.Width, (uint)browser.Height);
            // Ensure image is still valid after the MemoryStream closes.
            using (var stream = new MemoryStream(imageBytes))
            {
                using (var image = new Bitmap(stream))
                {
                    return(new Bitmap((image)));
                }
            }
#endif
        }
Example #2
0
        public void LinuxSend()
        {
            ImageCreator ic = new ImageCreator(geckoWebBrowser1);

            // TODO: Clean and speed up this nonsense!
            byte[] b = ic.CanvasGetPngImage(0, 0, (uint)geckoWebBrowser1.Width, (uint)geckoWebBrowser1.Height);
            using (MemoryStream ms = new MemoryStream(b))
            {
                using (Image img = Image.FromStream(ms))
                {
                    using (Bitmap bmp = new Bitmap(img, 800, 450))
                    {
                        MemoryStream res = new MemoryStream();
                        bmp.Save(res, ImageFormat.Png);
                        byte[] result = res.ToArray();
                        byte[] len    = BitConverter.GetBytes((int)res.Length);
                        Program.STDOut.Write(len, 0, 4);
                        Program.STDOut.Write(result, 0, (int)res.Length);
                        Program.STDOut.Flush();
                    }
                }
            }
        }
Example #3
0
        private Image CreateImage(GeckoWebBrowser browser, Color coverColor, int top, int bottom)
        {
            if (_syncControl.InvokeRequired)
            {
                return((Image)_syncControl.Invoke(new Func <GeckoWebBrowser, Color, int, int, Image>(CreateImage), browser,
                                                  coverColor, top, bottom));
            }
            // It's REALLY tricky to get the thumbnail created so that it reliably shows the image.
            // See BL-4170 and then BL-6257. We tried all kinds of tricks to tell when the image is
            // loaded into the document, such as checking image.completed and image.naturalWidth > 0
            // and waiting for two cycles of window.requestAnimationFrame (which is supposed to cover
            // starting and completing painting images) after the onload event fires. None of this
            // helped appreciably. A 400ms delay was enough for most images on a fast desktop, but
            // there was no way to tell how long would be enough on a slow laptop.
            // So, we finally came up with this technique, which is to examine the actual bitmap
            // that is produced to see whether there is something drawn in the image region of the
            // page. Even that did not prove to be enough: it's quite possible (especially with a tall
            // PNG image) for CanvasGetPngImage to return an image with the cover picture only partly
            // drawn. Fortunately, it seems to consistently draw from the top down, so we can be pretty
            // sure there is no more image to come if we do two cycles and there is no change in the
            // last line that is drawn.
            // On a typical tall PNG this loop has three iterations.
            // image is partly drawn (~40ms); ~140ms to find last line
            // image is fully drawn (~80ms); 1ms to find last line
            // image is fully drawn again (~28ms); 1ms to find last line
            // On a typical wide png, 2 iterations:
            // ~40 to draw image, ~80 to find last line (and repeat)
            // For jpg we seem to typically have three also:
            // ~20ms to make image; ~200ms to determine nothing is there
            // ~600ms to make image; ~40 to find last line
            // ~120 to redraw; ~40 to find last line
            while (true)             // Exit when we settle on an image and return it.
            {
                var watch = new Stopwatch();
                watch.Start();
                int lastLineOfImage = -1;
                while (true)
                {
                    var    creator    = new ImageCreator(browser);
                    byte[] imageBytes = creator.CanvasGetPngImage((uint)browser.Width, (uint)browser.Height);
                    using (var stream = new MemoryStream(imageBytes))
                    {
                        using (var image = new Bitmap(stream))
                        {
                            if (watch.ElapsedMilliseconds > 5000)
                            {
                                // Maybe there's no image or it's color perfectly mathches the background?
                                // When we used to do this with a simple delay 400ms was usually enough;
                                // if we can't get it in 5s give up, and use whatever we've got.
                                watch.Stop();
                                Debug.WriteLine("returned possibly incomplete thumnail after more than 5000ms");
                                return(new Bitmap(image));
                            }

                            if (top < 0)
                            {
                                // no image to wait for, go with what we have.
                                return(new Bitmap(image));
                            }

                            // I'm not sure how top or bottom can get to be greater than image.Height, but if they do,
                            // it causes a crash. It makes no sense to look for the last line drawn beyond the end of the
                            // image, so if something tries, just start looking at the bottom.
                            var newLastLine = GetLastLineOfImage(coverColor, Math.Min(top, image.Height), Math.Min(bottom, image.Height), image);

                            // If nothing has been drawn yet, we want to keep trying until something is.
                            // If something has been drawn, we want to keep trying until a cycle when
                            // nothing more gets added.
                            if (newLastLine == -1 || newLastLine > lastLineOfImage)
                            {
                                lastLineOfImage = newLastLine;
                                // This is meant to give the browser more of a chance to load it.
                                // It may well have been working on it anyway in another thread
                                // while we were checking pixels. Not too sure about the best length
                                // for this delay; longer might mean less time wasted checking pixels,
                                // but the minimum delay is two times this interval, so we don't want
                                // it too long. 50ms, at least on my desktop, usually doesn't result
                                // in any wasted iterations, nor much delay.
                                Thread.Sleep(50);
                                continue;                                 // try again
                            }

                            // No more image drawn than the last iteration, and we got something, so assume we have the whole thing.
                            watch.Stop();
                            Debug.WriteLine("Got image after waiting " + watch.ElapsedMilliseconds);
                            return(new Bitmap(image));
                        }
                    }
                }
            }
        }