/// <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); } } } } }
private static void LoadTexture(Stream input, out Texture output) { if (input == null) { output = null; return; } var magic = new byte[4]; input.Read(magic, 0, 4); input.Position = 0; var a = (char)magic[0]; var b = (char)magic[1]; var c = (char)magic[2]; var d = (char)magic[3]; if (VisualC.CompareMemory(magic, DDSImage.MagicBytes, 4) == 0) { var test = new DDSImage(input); output = new Texture(test.Texture2D) { Name = "Cubemap (DDS)" }; return; } var faces = new DataRectangle[6]; using (var decoder = new BitmapDecoder(Renderer.ImagingFactory, input, DecodeOptions.CacheOnDemand)) { var frame = decoder.GetFrame(0); var converter = new FormatConverter(Renderer.ImagingFactory); converter.Initialize( frame, PixelFormat.Format32bppPRGBA, BitmapDitherType.None, null, 0.0, BitmapPaletteType.Custom); var width = frame.Size.Width; var height = frame.Size.Height; var ratio = width / (float)height; if (Math.Abs(ratio - 2) < 0.001) // panorama { throw new NotImplementedException(); } if (Math.Abs(ratio - 1.333f) < 0.001) // cubic { var tileDim = (int)(width / 4f); var stride = tileDim * 4; Action <int, int, int> loadFace = delegate(int index, int coordX, int coordY) { var faceStream = new DataStream(tileDim * stride, false, true); using (var crop = new BitmapClipper(Renderer.ImagingFactory)) { crop.Initialize(converter, new RawBox(coordX, coordY, tileDim, tileDim)); crop.CopyPixels(stride, faceStream); } faces[index] = new DataRectangle(faceStream.DataPointer, stride); }; loadFace(0, tileDim * 2, tileDim); loadFace(1, 0, tileDim); loadFace(2, tileDim, 0); loadFace(3, tileDim, tileDim * 2); loadFace(4, tileDim, tileDim); loadFace(5, tileDim * 3, tileDim); var texture2D = new Texture2D(Renderer.Device, new Texture2DDescription { Width = tileDim, Height = tileDim, ArraySize = 6, BindFlags = BindFlags.ShaderResource, Usage = ResourceUsage.Immutable, CpuAccessFlags = CpuAccessFlags.None, Format = Format.R8G8B8A8_UNorm, MipLevels = 1, OptionFlags = ResourceOptionFlags.TextureCube, SampleDescription = new SampleDescription(1, 0) }, faces); converter.Dispose(); output = new Texture(texture2D); output.Name = output.NativeTexture.Tag.ToString(); } else { throw new NotImplementedException(); } } }