Beispiel #1
0
    private static Texture DecodeMultiframe(ImagingFactory imagingFactory, WicFlags flags, TextureDescription description, BitmapDecoder decoder)
    {
      var texture = new Texture(description);
      Guid dstFormat = ToWic(description.Format, false);

      for (int index = 0; index < description.ArraySize; ++index)
      {
        var image = texture.Images[index];
        using (var frame = decoder.GetFrame(index))
        {
          var pfGuid = frame.PixelFormat;
          var size = frame.Size;

          if (size.Width == description.Width && size.Height == description.Height)
          {
            // This frame does not need resized
            if (pfGuid == dstFormat)
            {
              frame.CopyPixels(image.Data, image.RowPitch);
            }
            else
            {
              using (var converter = new FormatConverter(imagingFactory))
              {
                converter.Initialize(frame, dstFormat, GetWicDither(flags), null, 0, BitmapPaletteType.Custom);
                converter.CopyPixels(image.Data, image.RowPitch);
              }
            }
          }
          else
          {
            // This frame needs resizing
            using (var scaler = new BitmapScaler(imagingFactory))
            {
              scaler.Initialize(frame, description.Width, description.Height, GetWicInterp(flags));

              Guid pfScaler = scaler.PixelFormat;
              if (pfScaler == dstFormat)
              {
                scaler.CopyPixels(image.Data, image.RowPitch);
              }
              else
              {
                // The WIC bitmap scaler is free to return a different pixel format than the source image, so here we
                // convert it to our desired format
                using (var converter = new FormatConverter(imagingFactory))
                {
                  converter.Initialize(scaler, dstFormat, GetWicDither(flags), null, 0, BitmapPaletteType.Custom);
                  converter.CopyPixels(image.Data, image.RowPitch);
                }
              }
            }
          }
        }
      }

      return texture;
    }
Beispiel #2
0
        public WicBitmapImpl(Stream stream, int decodeSize, bool horizontal, Avalonia.Visuals.Media.Imaging.BitmapInterpolationMode interpolationMode)
        {
            _decoder = new BitmapDecoder(Direct2D1Platform.ImagingFactory, stream, DecodeOptions.CacheOnLoad);

            var frame = _decoder.GetFrame(0);

            // now scale that to the size that we want
            var realScale = horizontal ? ((double)frame.Size.Height / frame.Size.Width) : ((double)frame.Size.Width / frame.Size.Height);

            PixelSize desired;

            if (horizontal)
            {
                desired = new PixelSize(decodeSize, (int)(realScale * decodeSize));
            }
            else
            {
                desired = new PixelSize((int)(realScale * decodeSize), decodeSize);
            }

            if (frame.Size.Width != desired.Width || frame.Size.Height != desired.Height)
            {
                using (var scaler = new BitmapScaler(Direct2D1Platform.ImagingFactory))
                {
                    scaler.Initialize(frame, desired.Width, desired.Height, ConvertInterpolationMode(interpolationMode));

                    WicImpl = new Bitmap(Direct2D1Platform.ImagingFactory, scaler, BitmapCreateCacheOption.CacheOnLoad);
                }
            }
            else
            {
                WicImpl = new Bitmap(Direct2D1Platform.ImagingFactory, frame, BitmapCreateCacheOption.CacheOnLoad);
            }

            Dpi = new Vector(96, 96);
        }
Beispiel #3
0
        //-------------------------------------------------------------------------------------
        // Decodes an image array, resizing/format converting as needed
        //-------------------------------------------------------------------------------------
        private static Image DecodeMultiframe(WICFlags flags, ImageDescription metadata, BitmapDecoder decoder)
        {
            var image = Image.New(metadata);

            Guid sourceGuid;

            if (!ToWIC(metadata.Format, out sourceGuid))
            {
                return(null);
            }

            for (int index = 0; index < metadata.ArraySize; ++index)
            {
                var pixelBuffer = image.PixelBuffer[index, 0];

                using (var frame = decoder.GetFrame(index))
                {
                    var pfGuid = frame.PixelFormat;
                    var size   = frame.Size;

                    if (pfGuid == sourceGuid)
                    {
                        if (size.Width == metadata.Width && size.Height == metadata.Height)
                        {
                            // This frame does not need resized or format converted, just copy...
                            frame.CopyPixels(pixelBuffer.RowStride, pixelBuffer.DataPointer, pixelBuffer.BufferStride);
                        }
                        else
                        {
                            // This frame needs resizing, but not format converted
                            using (var scaler = new BitmapScaler(Factory))
                            {
                                scaler.Initialize(frame, metadata.Width, metadata.Height, GetWICInterp(flags));
                                scaler.CopyPixels(pixelBuffer.RowStride, pixelBuffer.DataPointer, pixelBuffer.BufferStride);
                            }
                        }
                    }
                    else
                    {
                        // This frame required format conversion
                        using (var converter = new FormatConverter(Factory))
                        {
                            converter.Initialize(frame, pfGuid, GetWICDither(flags), null, 0, BitmapPaletteType.Custom);

                            if (size.Width == metadata.Width && size.Height == metadata.Height)
                            {
                                converter.CopyPixels(pixelBuffer.RowStride, pixelBuffer.DataPointer, pixelBuffer.BufferStride);
                            }
                            else
                            {
                                // This frame needs resizing, but not format converted
                                using (var scaler = new BitmapScaler(Factory))
                                {
                                    scaler.Initialize(frame, metadata.Width, metadata.Height, GetWICInterp(flags));
                                    scaler.CopyPixels(pixelBuffer.RowStride, pixelBuffer.DataPointer, pixelBuffer.BufferStride);
                                }
                            }
                        }
                    }
                }
            }
            return(image);
        }
Beispiel #4
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);
            }

            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 scaler = new BitmapScaler(factory))
                                using (var output = new MemoryStream())
                                    using (var encoder = new BitmapEncoder(factory, ContainerFormatGuids.Jpeg))
                                    {
                                        // decode the loaded image to a format that can be consumed by D2D
                                        BitmapSource source = decoder.GetFrame(0);

                                        // 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;
                                        }
                                        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();
                                        imageType = ImageType.Jpeg;
                                        return(true);
                                    }
            }
            catch (Exception e)
            {
                // ServiceRegistration.Get<ILogger>().Warn("WICThumbnailProvider: Error loading bitmapSource from file data stream", e);
                return(false);
            }
        }
Beispiel #5
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();
            }
        }
Beispiel #6
0
        private void RenderThread(object obj)
        {
            var providerParam = new KinectImageProvider[1];

            try
            {
                while (!this.Dispatcher.HasShutdownStarted && !this.disposed)
                {
                    try
                    {
                        if (this.renderEvent.Wait(100))
                        {
                            this.renderEvent.Reset();

                            if (this.disposed)
                            {
                                return;
                            }

                            using var frame = Interlocked.Exchange(ref this.lastFrame, null);
                            if (frame != null && frame.Bitmap != null)
                            {
                                var frameSize = frame.Bitmap.Size;
                                var ratio     = 1d;
                                if (this.RenderWidth > 0 && frameSize.Width > frameSize.Height)
                                {
                                    ratio = (double)this.RenderWidth / frameSize.Width;
                                }

                                if (this.RenderHeight > 0 && frameSize.Height > frameSize.Width)
                                {
                                    ratio = (double)this.RenderHeight / frameSize.Height;
                                }

                                ratio = ratio > 1 ? 1 : ratio;

                                var desiredSize = new Size2((int)(frameSize.Width * ratio), (int)(frameSize.Height * ratio));
                                if (this.renderTarget == null || this.renderTargetDescription.Width != desiredSize.Width || this.renderTargetDescription.Height != desiredSize.Height)
                                {
                                    this.renderTarget?.Dispose();
                                    this.cpuRenderTarget?.Dispose();
                                    this.CreateRenderTargets(desiredSize);
                                }

                                using var scale = new BitmapScaler(this.imagingFactory);
                                scale.Initialize(frame.Bitmap, desiredSize.Width, desiredSize.Height, BitmapInterpolationMode.Linear);
                                using var bitmap     = new Bitmap(this.imagingFactory, scale, BitmapCreateCacheOption.NoCache);
                                using var bitmapLock = bitmap.Lock(BitmapLockFlags.Read);
                                DataBox imageDataBox = new DataBox(bitmapLock.Data.DataPointer, bitmapLock.Data.Pitch, bitmapLock.Data.Pitch * bitmapLock.Size.Height);
                                lock (d3dDevice)
                                {
                                    if (!this.d3dDevice.IsDisposed)
                                    {
                                        d3dDevice.ImmediateContext.UpdateSubresource(imageDataBox, this.cpuRenderTarget);
                                        d3dDevice.ImmediateContext.CopyResource(this.cpuRenderTarget, this.renderTarget);
                                        d3dDevice.ImmediateContext.Flush();
                                    }
                                }

                                if (!this.Dispatcher.HasShutdownStarted && !this.disposed)
                                {
                                    providerParam[0] = frame.Provider;
                                    this.Dispatcher.Invoke((InvokeRenderWithProvider)this.RequestRenderForProvider, providerParam);
                                }
                            }
                        }
                    }
                    catch (Exception e) when(!(e is OperationCanceledException))
                    {
                    }
                }
            }
            catch (OperationCanceledException)
            {
            }
        }
Beispiel #7
0
        /// <summary>
        /// Function to read multiple frames from a decoder that supports multiple frames.
        /// </summary>
        /// <param name="wic">WIC interface.</param>
        /// <param name="data">Image data to populate.</param>
        /// <param name="decoder">Decoder for the image.</param>
        private void ReadFrames(GorgonWICImage wic, GorgonImageData data, BitmapDecoder decoder)
        {
            Guid bestPixelFormat = wic.GetGUID(data.Settings.Format);

            // Find the best fit pixel format.
            if (bestPixelFormat == Guid.Empty)
            {
                throw new IOException(string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, data.Settings.Format));
            }

            // Use the image array as the frames.
            int arrayCount = _actualArrayCount.Min(data.Settings.ArrayCount);

            for (int array = 0; array < arrayCount; array++)
            {
                var buffer = data.Buffers[0, array];

                // Get the frame data.
                using (var frame = decoder.GetFrame(array))
                {
                    IntPtr bufferPointer = buffer.Data.BasePointer;
                    Guid   frameFormat   = frame.PixelFormat;
                    int    frameWidth    = frame.Size.Width;
                    int    frameHeight   = frame.Size.Height;
                    var    frameOffset   = GetFrameOffset(frame);

                    // Calculate the pointer offset if we have an offset from the frame.  Only offset if we're clipping the image though.
                    if (((frameOffset.Y != 0) || (frameOffset.X != 0)) && (Clip))
                    {
                        bufferPointer = buffer.Data.BasePointer + (frameOffset.Y * buffer.PitchInformation.RowPitch) + (frameOffset.X * (buffer.PitchInformation.RowPitch / buffer.Width));
                    }

                    // Confirm that we actually need to perform clipping.
                    bool needsSizeAdjust = (frameWidth + frameOffset.X > data.Settings.Width) || (frameHeight + frameOffset.Y > data.Settings.Height);

                    // If the formats match, then we don't need to do conversion.
                    if (bestPixelFormat == frameFormat)
                    {
                        // If the width and height are the same then we can just do a straight copy into the buffer.
                        if (((frameWidth == data.Settings.Width) && (frameHeight == data.Settings.Height)) || ((!needsSizeAdjust) && (Clip)))
                        {
                            frame.CopyPixels(buffer.PitchInformation.RowPitch, bufferPointer, buffer.PitchInformation.SlicePitch);

                            continue;
                        }

                        // We need to scale the image up/down to the size of our image data.
                        if (!Clip)
                        {
                            using (var scaler = new BitmapScaler(wic.Factory))
                            {
                                scaler.Initialize(frame, data.Settings.Width, data.Settings.Height, (BitmapInterpolationMode)Filter);
                                scaler.CopyPixels(buffer.PitchInformation.RowPitch, bufferPointer, buffer.PitchInformation.SlicePitch);
                            }
                            continue;
                        }

                        using (var clipper = new BitmapClipper(wic.Factory))
                        {
                            clipper.Initialize(frame, new Rectangle(0, 0, data.Settings.Width, data.Settings.Height));
                            clipper.CopyPixels(buffer.PitchInformation.RowPitch, bufferPointer, buffer.PitchInformation.SlicePitch);
                        }

                        continue;
                    }

                    // Poop.  We need to convert this image.
                    using (var converter = new FormatConverter(wic.Factory))
                    {
                        converter.Initialize(frame,
                                             bestPixelFormat,
                                             (BitmapDitherType)Dithering,
                                             null,
                                             0.0,
                                             BitmapPaletteType.Custom);

                        if (((frameWidth == data.Settings.Width) && (frameHeight == data.Settings.Height)) ||
                            ((!needsSizeAdjust) && (Clip)))
                        {
                            converter.CopyPixels(buffer.PitchInformation.RowPitch,
                                                 bufferPointer,
                                                 buffer.PitchInformation.SlicePitch);
                            continue;
                        }

                        // And we need to scale the image.
                        if (!Clip)
                        {
                            using (var scaler = new BitmapScaler(wic.Factory))
                            {
                                scaler.Initialize(converter,
                                                  data.Settings.Width,
                                                  data.Settings.Height,
                                                  (BitmapInterpolationMode)Filter);
                                scaler.CopyPixels(buffer.PitchInformation.RowPitch,
                                                  bufferPointer,
                                                  buffer.PitchInformation.SlicePitch);
                            }

                            continue;
                        }

                        using (var clipper = new BitmapClipper(wic.Factory))
                        {
                            clipper.Initialize(frame,
                                               new Rectangle(0, 0, data.Settings.Width, data.Settings.Height));
                            clipper.CopyPixels(buffer.PitchInformation.RowPitch,
                                               bufferPointer,
                                               buffer.PitchInformation.SlicePitch);
                        }
                    }
                }
            }
        }
Beispiel #8
0
        /// <summary>
        /// 從WIC Frame建立貼圖資源(非DDS)
        /// </summary>
        /// <param name="d3dContext">If a Direct3D 11 device context is provided and the current device supports it for the given pixel format, it will auto-generate mipmaps.</param>
        private static Result CreateWICTexture(Device device, DeviceContext d3dContext, BitmapFrameDecode frame, int maxsize, ResourceUsage usage, BindFlags bind, CpuAccessFlags cpuAccess, ResourceOptionFlags option, LoadFlags load, out Resource texture, out ShaderResourceView textureView)
        {
            texture     = null;
            textureView = null;

            if (frame.Size.Width <= 0 || frame.Size.Height <= 0)
            {
                return(Result.InvalidArg);
            }

            if (maxsize == 0)
            {
                switch (device.FeatureLevel)
                {
                case FeatureLevel.Level_9_1:
                case FeatureLevel.Level_9_2:
                    maxsize = 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
                    break;

                case FeatureLevel.Level_9_3:
                    maxsize = 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
                    break;

                case FeatureLevel.Level_10_0:
                case FeatureLevel.Level_10_1:
                    maxsize = 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
                    break;

                default:
                    maxsize = Resource.MaximumTexture2DSize;     /*D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION*/
                    break;
                }
            }

            Size2 frameSize = frame.Size;
            Size2 targetSize;

            if (frameSize.Width > maxsize || frameSize.Height > maxsize)
            {
                double ratio = Convert.ToDouble(frameSize.Height) / Convert.ToDouble(frameSize.Width);
                if (frameSize.Width > frameSize.Height)
                {
                    targetSize.Width  = maxsize;
                    targetSize.Height = Math.Max(1, Convert.ToInt32(maxsize * ratio));
                }
                else
                {
                    targetSize.Height = maxsize;
                    targetSize.Width  = Math.Max(1, Convert.ToInt32(maxsize / ratio));
                }
            }
            else
            {
                targetSize = frameSize;
            }

            #region Determine format
            Guid        sourceFormat = frame.PixelFormat;
            Guid        targetFormat = sourceFormat;
            DXGI.Format format       = sourceFormat.ConvertWICToDXGIFormat();
            int         bpp          = 0;

            if (format == DXGI.Format.Unknown)
            {
                if (sourceFormat == PixelFormat.Format96bppRGBFixedPoint)
                {
                    if (WIC2)
                    {
                        targetFormat = PixelFormat.Format96bppRGBFloat;
                        format       = DXGI.Format.R32G32B32_Float;
                        bpp          = 96;
                    }
                    else
                    {
                        targetFormat = PixelFormat.Format128bppRGBAFloat;
                        format       = DXGI.Format.R32G32B32A32_Float;
                        bpp          = 128;
                    }
                }
                else
                {
                    targetFormat = sourceFormat.ConvertToNearest();
                    format       = targetFormat.ConvertWICToDXGIFormat();
                    bpp          = PixelFormat.GetBitsPerPixel(targetFormat);
                }
                if (format == DXGI.Format.Unknown)
                {
                    return(Result.GetResultFromWin32Error(unchecked ((int)0x80070032)));
                }
            }
            else
            {
                bpp = PixelFormat.GetBitsPerPixel(sourceFormat);
            }

            if (format == DXGI.Format.R32G32B32_Float && d3dContext != null)
            {
                // Special case test for optional device support for autogen mipchains for R32G32B32_FLOAT
                var formatSupport = device.CheckFormatSupport(format);
                if (!formatSupport.HasFlag(FormatSupport.MipAutogen))
                {
                    targetFormat = PixelFormat.Format128bppRGBAFloat;
                    format       = DXGI.Format.R32G32B32A32_Float;
                    bpp          = 128;
                }
            }
            if (bpp == 0)
            {
                return(Result.Fail);
            }

            if (load.HasFlag(LoadFlags.ForceSrgb))
            {
                format = format.MakeSRgb();
            }
            else if (!load.HasFlag(LoadFlags.ignoreSrgb))
            {
                bool sRGB = false;
                try {
                    var metareader      = frame.MetadataQueryReader;
                    var containerFormat = metareader.ContainerFormat;

                    if (containerFormat == ContainerFormatGuids.Png)
                    {
                        // Check for sRGB chunk
                        if (metareader.TryGetMetadataByName("/sRGB/RenderingIntent", out var value) == Result.Ok)
                        {
                            sRGB = true;
                        }
                    }
                    else if (metareader.TryGetMetadataByName("System.Image.ColorSpace", out var value) == Result.Ok)
                    {
                        sRGB = true;
                    }

                    if (sRGB)
                    {
                        format = format.MakeSRgb();
                    }
                } catch (SharpDXException) {
                    // BMP, ICO are not supported.
                }
            }

            // Verify our target format is supported by the current device
            var support = device.CheckFormatSupport(format);
            if (!support.HasFlag(FormatSupport.Texture2D))
            {
                targetFormat = PixelFormat.Format32bppRGBA;
                format       = DXGI.Format.R8G8B8A8_UNorm;
                bpp          = 32;
            }
            #endregion


            int    stride    = (targetSize.Width * bpp + 7) / 8; // round
            int    imageSize = stride * targetSize.Height;
            IntPtr temp      = System.Runtime.InteropServices.Marshal.AllocCoTaskMem(imageSize);

            if (sourceFormat == targetFormat && frameSize == targetSize)   // 不需要格式轉換 且 不需要改變大小
            {
                frame.CopyPixels(stride, new DataPointer(temp, imageSize));
            }
            else if (frameSize == targetSize)     // 需要格式轉換
            {
                using (var factory = new ImagingFactory2())
                    using (var coverter = new FormatConverter(factory)) {
                        if (coverter.CanConvert(sourceFormat, targetFormat))
                        {
                            coverter.Initialize(frame, targetFormat, BitmapDitherType.ErrorDiffusion, null, 0, BitmapPaletteType.MedianCut);
                            coverter.CopyPixels(stride, new DataPointer(temp, imageSize));
                        }
                        else
                        {
                            return(Result.UnexpectedFailure);
                        }
                    }
            }
            else if (sourceFormat == targetFormat)     // 需要改變大小
            {
                using (var factory = new ImagingFactory2())
                    using (var scaler = new BitmapScaler(factory)) {
                        scaler.Initialize(frame, targetSize.Width, targetSize.Height, BitmapInterpolationMode.Fant);
                        var pfScaler = scaler.PixelFormat;
                        if (targetFormat == pfScaler)
                        {
                            scaler.CopyPixels(stride, new DataPointer(temp, imageSize));
                        }
                    }
            }
            else     // 需要格式轉換 且 需要改變大小
            {
                using (var factory = new ImagingFactory2())
                    using (var scaler = new BitmapScaler(factory))
                        using (var coverter = new FormatConverter(factory)) {
                            scaler.Initialize(frame, targetSize.Width, targetSize.Height, BitmapInterpolationMode.Fant);
                            var pfScaler = scaler.PixelFormat;

                            if (coverter.CanConvert(pfScaler, targetFormat))
                            {
                                coverter.Initialize(scaler, targetFormat, BitmapDitherType.ErrorDiffusion, null, 0, BitmapPaletteType.MedianCut);
                                coverter.CopyPixels(stride, new DataPointer(temp, imageSize));
                            }
                            else
                            {
                                return(Result.UnexpectedFailure);
                            }
                        }
            }

            var autogen = false;

            if (d3dContext != null)
            {
                var formatSupport = device.CheckFormatSupport(format);
                if (formatSupport.HasFlag(FormatSupport.MipAutogen))
                {
                    autogen = true;
                }
            }

            var texture2DDescription = new Texture2DDescription()
            {
                Width             = targetSize.Width,
                Height            = targetSize.Height,
                MipLevels         = autogen ? 0 : 1,
                ArraySize         = 1,
                Format            = format,
                SampleDescription = new DXGI.SampleDescription(1, 0),
                Usage             = usage,
                CpuAccessFlags    = cpuAccess,
            };

            if (autogen)
            {
                texture2DDescription.BindFlags   = bind | BindFlags.RenderTarget;
                texture2DDescription.OptionFlags = option | ResourceOptionFlags.GenerateMipMaps;
            }
            else
            {
                texture2DDescription.BindFlags   = bind;
                texture2DDescription.OptionFlags = option;
            }

            Result result = Result.Ok;

            // 建立Texture2D !!!
            try {
                if (autogen)
                {
                    texture = new Texture2D(device, texture2DDescription);
                }
                else
                {
                    texture = new Texture2D(device, texture2DDescription, new DataBox[] { new DataBox(temp, stride, imageSize) });
                }
            } catch (SharpDXException e) {
                System.Diagnostics.Debug.WriteLine(e.ToString());
                result = Result.Fail;
            }

            if (result.Success)
            {
                var SRVDesc = new ShaderResourceViewDescription()
                {
                    Format    = format,
                    Dimension = ShaderResourceViewDimension.Texture2D,
                    Texture2D = new ShaderResourceViewDescription.Texture2DResource()
                    {
                        MipLevels = autogen ? -1 : 1
                    },
                };

                try {
                    textureView = new ShaderResourceView(device, texture, SRVDesc);
                    if (autogen)
                    {
                        DataBox data = new DataBox(temp, stride, imageSize);
                        d3dContext.UpdateSubresource(data, texture);
                        d3dContext.GenerateMips(textureView);
                    }
                } catch (Exception e) {
                    System.Diagnostics.Debug.WriteLine(e.ToString());
                    Utilities.Dispose(ref texture);
                    result = Result.Fail;
                }
            }

            // 釋放 Unmanaged 資源
            System.Runtime.InteropServices.Marshal.FreeCoTaskMem(temp);

            return(result);
        }
        private void displayFileDetails(DATFileEntry entry)
        {
            Text = baseTitle + " - " + entry.Filename;

            savePNGButton.Visible  = false;
            savePNGSButton.Visible = false;

            currentExportBitmap  = null;
            currentExportBitmaps = null;

            switch (entry.Type)
            {
            case "MAP":
                MAPFile map = new MAPFile(entry);
                if (map.Error != "")
                {
                    MessageBox.Show(map.Error, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                Palette palette   = Palette.Default;
                Bitmap  mapBitmap = null;

                // find matching ICO tileset and PCC for palette
                if (entry.Filename.StartsWith("W"))
                {
                    string baseName = entry.Filename.Substring(0, 2);
                    if (container.Entries.ContainsKey(baseName + ".ICO"))
                    {
                        palette = getPaletteFrom(baseName + ".PCC");
                        if (palette == null)
                        {
                            palette = Palette.Default;
                        }
                        else if (baseName != "W2")
                        {
                            addW2Palette(palette);
                        }

                        ICOFile icoFile = new ICOFile(container.Entries[baseName + ".ICO"], palette);
                        int     scale   = 1;
                        mapBitmap           = MAPPainter.Paint(map, icoFile, scale);
                        currentExportBitmap = scale == 1 ? mapBitmap : MAPPainter.Paint(map, icoFile, 1);
                    }
                }

                imgPictureBox.Image = mapBitmap;
                setPaletteImage(palette);
                log($"MAP loaded: name={entry.Filename}, width={map.Width}, height={map.Height}, palette={palette.Name}");
                break;

            case "ARE":
                AREFile area = new AREFile(entry);
                if (area.Error != "")
                {
                    MessageBox.Show(area.Error, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                //imgPictureBox.Image = BitmapScaler.PixelScale(, 3);
                //palettePictureBox.Image = BitmapScaler.PixelScale(Palette.ToBitmap(Palette.Default), 6);
                break;

            case "BOB":
                string name = Path.GetFileNameWithoutExtension(entry.Filename);
                if (container.Entries.ContainsKey(name + ".PCC"))
                {
                    palette = getPaletteFrom(name + ".PCC");
                }
                else if (name.Length == 1)
                {
                    palette = getPaletteFrom("ANTS.PCC");                            // the ants have names like A.BOB to O.BOB
                }
                else
                {
                    palette           = getPaletteFrom("W2.PCC");
                    palette.Colors[0] = Color.Black;
                    palette.Name     += " (mod)";
                }

                BOBFile b = new BOBFile(entry, palette);
                if (b.Error != "")
                {
                    MessageBox.Show(b.Error, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                log($"BOB contains {b.Elements.Count} images");
                currentExportBitmaps = b.Elements.ToArray();
                currentExportBitmap  = BOBPainter.MakeSheet(b);
                imgPictureBox.Image  = BitmapScaler.PixelScale(currentExportBitmap, 3);
                setPaletteImage(palette);
                break;

            case "ICO":     // tileset / spritesheet
                string world = entry.Filename.Contains("W1") ? "W1" : (entry.Filename.Contains("W2") ? "W2" : "W3");
                palette = getPaletteFrom(world + ".PCC");
                if (palette == null)
                {
                    palette = Palette.Default;
                }
                else if (world != "W2")
                {
                    addW2Palette(palette);
                }

                ICOFile ico = new ICOFile(entry, palette);
                if (ico.Error != "")
                {
                    MessageBox.Show("Failed to load ICO, sorry!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                log($"ICO contains {ico.Bitmaps.Length} tiles");
                currentExportBitmaps = ico.Bitmaps;
                currentExportBitmap  = ICOPainter.TileSetFromBitmaps(ico.Bitmaps);
                imgPictureBox.Image  = BitmapScaler.PixelScale(currentExportBitmap, 3);
                setPaletteImage(palette);
                break;


            case "PCC":     // these are actually PCX files, version 5, encoded, 8 bits per pixel
                PCXFile pcx = new PCXFile();
                if (!pcx.Load(entry.Data))
                {
                    MessageBox.Show(pcx.Error, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                currentExportBitmap = pcx.Bitmap;
                imgPictureBox.Image = BitmapScaler.PixelScale(pcx.Bitmap, 4);
                setPaletteImage(Palette.ToBitmap(pcx.Palette), "own");
                log($"PCC loaded: name={entry.Filename}, width={pcx.Bitmap.Width}, height={pcx.Bitmap.Height}, palette=own");
                break;

            default:
                break;
            }

            if (currentExportBitmap != null)
            {
                savePNGButton.Visible = true;
            }
            if (currentExportBitmaps != null && currentExportBitmaps.Length > 0)
            {
                savePNGSButton.Visible = true;
            }
        }
 private void setPaletteImage(Bitmap bmp, string name)
 {
     palettePictureBox.Image = BitmapScaler.PixelScale(bmp, 8);
     paletteNameLabel.Text   = name;
 }