コード例 #1
0
        public bool GetThumbnail(Stream stream, int width, int height, bool cachedOnly, out byte[] imageData, out ImageType imageType)
        {
            imageData = null;
            imageType = ImageType.Unknown;
            // No support for cache
            if (cachedOnly)
            {
                return(false);
            }

            Bitmap cachedBitmap = null; // used only for rotation

            try
            {
                if (stream.CanSeek)
                {
                    stream.Seek(0, SeekOrigin.Begin);
                }

                // open the image file for reading
                using (var factory = new ImagingFactory2())
                    using (var inputStream = new WICStream(factory, stream))
                        using (var decoder = new BitmapDecoder(factory, inputStream, DecodeOptions.CacheOnLoad))
                            using (var rotator = new BitmapFlipRotator(factory))
                                using (var scaler = new BitmapScaler(factory))
                                    using (var output = new MemoryStream())
                                    {
                                        // decode the loaded image to a format that can be consumed by D2D
                                        BitmapSource source = decoder.GetFrame(0);

                                        // Prefer PNG output for source PNG and for source formats with Alpha channel
                                        var usePngOutput = decoder.DecoderInfo.FriendlyName.StartsWith("PNG") || PixelFormat.GetBitsPerPixel(source.PixelFormat) == 32;

                                        BitmapTransformOptions bitmapTransformationOptions = BitmapTransformOptions.Rotate0;
                                        BitmapFrameDecode      frame = source as BitmapFrameDecode;
                                        if (frame != null)
                                        {
                                            const string EXIF_ORIENTATION_TAG = "/app1/{ushort=0}/{ushort=274}";
                                            ushort?      orientation          = null;
                                            try
                                            {
                                                // Not supported on all input types, i.e. BMP will fail here
                                                orientation = (ushort?)frame.MetadataQueryReader.TryGetMetadataByName(EXIF_ORIENTATION_TAG); //0x0112
                                            }
                                            catch { }

                                            // If the EXIF orientation specifies that the image needs to be flipped or rotated before display, set that up to happen
                                            if (orientation.HasValue)
                                            {
                                                switch (orientation.Value)
                                                {
                                                case 1: break; // No rotation required.

                                                case 2: bitmapTransformationOptions = BitmapTransformOptions.Rotate0 | BitmapTransformOptions.FlipHorizontal; break;

                                                case 3: bitmapTransformationOptions = BitmapTransformOptions.Rotate180; break;

                                                case 4: bitmapTransformationOptions = BitmapTransformOptions.Rotate180 | BitmapTransformOptions.FlipHorizontal; break;

                                                case 5: bitmapTransformationOptions = BitmapTransformOptions.Rotate270 | BitmapTransformOptions.FlipHorizontal; break;

                                                case 6: bitmapTransformationOptions = BitmapTransformOptions.Rotate90; break;

                                                case 7: bitmapTransformationOptions = BitmapTransformOptions.Rotate90 | BitmapTransformOptions.FlipHorizontal; break;

                                                case 8: bitmapTransformationOptions = BitmapTransformOptions.Rotate270; break;
                                                }
                                            }
                                        }

                                        // Scale down larger images
                                        int sourceWidth  = source.Size.Width;
                                        int sourceHeight = source.Size.Height;
                                        if (width > 0 && height > 0 && (sourceWidth > width || sourceHeight > height))
                                        {
                                            if (sourceWidth <= height)
                                            {
                                                width = sourceWidth;
                                            }

                                            int newHeight = sourceHeight * height / sourceWidth;
                                            if (newHeight > height)
                                            {
                                                // Resize with height instead
                                                width     = sourceWidth * height / sourceHeight;
                                                newHeight = height;
                                            }

                                            scaler.Initialize(source, width, newHeight, BitmapInterpolationMode.Fant);
                                            source = scaler;
                                        }

                                        // Rotate
                                        if (bitmapTransformationOptions != BitmapTransformOptions.Rotate0)
                                        {
                                            // For fast rotation a cached bitmap is needed, otherwise only per-pixel-decoding happens which makes the process extremly slow.
                                            // See https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/5ff2b52b-602f-4b22-9fb2-371539ff5ebb/hang-in-createbitmapfromwicbitmap-when-using-iwicbitmapfliprotator?forum=windowswic
                                            cachedBitmap = new Bitmap(factory, source, BitmapCreateCacheOption.CacheOnLoad);
                                            rotator.Initialize(cachedBitmap, bitmapTransformationOptions);
                                            source = rotator;
                                        }

                                        Guid formatGuid = ContainerFormatGuids.Jpeg;
                                        imageType = ImageType.Jpeg;

                                        if (usePngOutput)
                                        {
                                            formatGuid = ContainerFormatGuids.Png;
                                            imageType  = ImageType.Png;
                                        }

                                        using (var encoder = new BitmapEncoder(factory, formatGuid))
                                        {
                                            encoder.Initialize(output);
                                            using (var bitmapFrameEncode = new BitmapFrameEncode(encoder))
                                            {
                                                // Create image encoder
                                                var wicPixelFormat = PixelFormat.FormatDontCare;
                                                bitmapFrameEncode.Initialize();
                                                bitmapFrameEncode.SetSize(source.Size.Width, source.Size.Height);
                                                bitmapFrameEncode.SetPixelFormat(ref wicPixelFormat);
                                                bitmapFrameEncode.WriteSource(source);
                                                bitmapFrameEncode.Commit();
                                                encoder.Commit();
                                            }
                                        }
                                        imageData = output.ToArray();
                                        return(true);
                                    }
            }
            catch (Exception)
            {
                //ServiceRegistration.Get<ILogger>().Warn("WICThumbnailProvider: Error loading bitmapSource from file data stream", ex);
                return(false);
            }
            finally
            {
                cachedBitmap?.Dispose();
            }
        }
コード例 #2
0
 public static IBitmapSource <TPixel> CreateBitmapFlipRotator <TPixel>(this IImagingFactory factory, IBitmapSource <TPixel> source, BitmapTransformOptions options) where TPixel : struct, INaturalPixelInfo =>
 ((IBitmapSource <TPixel>)factory.CreateBitmapFlipRotator(source, options));
コード例 #3
0
 public IBitmapSource CreateBitmapFlipRotator(IBitmapSource source, BitmapTransformOptions options) =>
 base.innerRefT.CreateBitmapFlipRotator(source, options);