Beispiel #1
0
    /// <summary>
    /// Resizes the texture. (If original texture has mipmaps, all mipmap levels are automatically
    /// recreated.)
    /// </summary>
    /// <param name="width">The new width.</param>
    /// <param name="height">The new height.</param>
    /// <param name="depth">The new depth. Must be 1 for 2D textures and cube map textures.</param>
    /// <param name="filter">The filter to use for resizing.</param>
    /// <param name="alphaTransparency">
    /// <see langword="true"/> if the image contains uses non-premultiplied alpha; otherwise,
    /// <see langword="false"/> if the image uses premultiplied alpha or has no alpha.
    /// </param>
    /// <param name="wrapMode">
    /// The texture address mode that will be used for sampling the at runtime.
    /// </param>
    /// <returns>The resized texture.</returns>
    public Texture Resize(int width, int height, int depth, ResizeFilter filter, bool alphaTransparency, TextureAddressMode wrapMode)
    {
      var description = Description;
      description.Width = width;
      description.Height = height;
      description.Depth = depth;

      var resizedTexture = new Texture(description);

      // Resize mipmap level 0.
      for (int arrayIndex = 0; arrayIndex < description.ArraySize; arrayIndex++)
        TextureHelper.Resize(this, 0, arrayIndex, resizedTexture, 0, arrayIndex, filter, alphaTransparency, wrapMode);

      // Regenerate mipmap levels, if necessary.
      if (description.MipLevels > 1)
        resizedTexture.GenerateMipmaps(filter, alphaTransparency, wrapMode);

      return resizedTexture;
    }
Beispiel #2
0
    public static void Save(Image image, Stream stream)
    {
      if (image == null)
        throw new ArgumentNullException("image");
      if (stream == null)
        throw new ArgumentNullException("stream");

      var convFlags = ConversionFlags.None;
      var header = EncodeTgaHeader(image, ref convFlags);

      // Write header.
      stream.WriteStruct(header);

      // Determine memory required for image data.
      int rowPitch = (convFlags & ConversionFlags.Format888) != 0 ? image.Width * 3 : image.RowPitch;

      // Write pixels.
      using (var sourceStream = new MemoryStream(image.Data, false))
      using (var reader = new BinaryReader(sourceStream))

      using (var writer = new BinaryWriter(stream, Encoding.Default, true))
#else
      using (var writer = new BinaryWriter(stream, Encoding.Default))   // Warning: Closes the stream!

      {
        for (int y = 0; y < image.Height; y++)
        {
          if ((convFlags & ConversionFlags.Format888) != 0)
          {
            Copy24BppScanline(reader, image.RowPitch, writer);
          }
          else if ((convFlags & ConversionFlags.Swizzle) != 0)
          {
            TextureHelper.SwizzleScanline(reader, image.RowPitch, writer, rowPitch, image.Format, ScanlineFlags.None);
          }
          else
          {
            TextureHelper.CopyScanline(reader, image.RowPitch, writer, rowPitch, image.Format, ScanlineFlags.None);
          }
        }
      }
    }
Beispiel #3
0
    /// <summary>
    /// Determines whether conversion to the specified texture format is supported.
    /// </summary>
    /// <param name="format">The desired texture format.</param>
    /// <returns>
    /// <see langword="true"/> if the conversion from the current format to <paramref name="format"/>
    /// is supported; otherwise, <see langword="false"/>.
    /// </returns>
    public bool CanConvertTo(DataFormat format)
    {
      var srcFormat = Description.Format;
      var dstFormat = format;

      // srcFormat -> dstFormat
      if (TextureHelper.CanConvert(srcFormat, dstFormat))
        return true;

      // srcFormat -> R32G32B32A32_FLOAT -> dstFormat
      if (TextureHelper.CanConvert(srcFormat, DataFormat.R32G32B32A32_FLOAT)
          && TextureHelper.CanConvert(DataFormat.R32G32B32A32_FLOAT, dstFormat))
        return true;

      // srcFormat -> R8G8B8A8_UNORM -> dstFormat
      if (TextureHelper.CanConvert(srcFormat, DataFormat.R8G8B8A8_UNORM)
          && TextureHelper.CanConvert(DataFormat.R8G8B8A8_UNORM, dstFormat))
        return true;

      return false;
    }
        /// <summary>
        /// Gets the pixel at the specified position.
        /// </summary>
        /// <param name="x">The x position.</param>
        /// <param name="y">The y position.</param>
        /// <param name="wrapMode">The wrap mode.</param>
        /// <returns>The pixel color.</returns>
        public Vector4 GetPixel(int x, int y, TextureAddressMode wrapMode)
        {
            switch (wrapMode)
            {
            case TextureAddressMode.Clamp:
                x = TextureHelper.WrapClamp(x, _width);
                y = TextureHelper.WrapClamp(y, _height);
                break;

            case TextureAddressMode.Repeat:
                x = TextureHelper.WrapRepeat(x, _width);
                y = TextureHelper.WrapRepeat(y, _height);
                break;

            case TextureAddressMode.Mirror:
                x = TextureHelper.WrapMirror(x, _width);
                y = TextureHelper.WrapMirror(y, _height);
                break;
            }

            return(GetPixel(y * _width + x));
        }
Beispiel #5
0
    /// <summary>
    /// (Re-)Generates all mipmap levels.
    /// </summary>
    /// <param name="filter">The filter to use for resizing.</param>
    /// <param name="alphaTransparency">
    /// <see langword="true"/> if the image contains uses non-premultiplied alpha; otherwise,
    /// <see langword="false"/> if the image uses premultiplied alpha or has no alpha.
    /// </param>
    /// <param name="wrapMode">
    /// The texture address mode that will be used for sampling the at runtime.
    /// </param>
    public void GenerateMipmaps(ResizeFilter filter, bool alphaTransparency, TextureAddressMode wrapMode)
    {
      var oldDescription = Description;
      var newDescription = Description;

      // Determine number of mipmap levels.
      if (oldDescription.Dimension == TextureDimension.Texture3D)
        newDescription.MipLevels = TextureHelper.CalculateMipLevels(oldDescription.Width, oldDescription.Height, oldDescription.Depth);
      else
        newDescription.MipLevels = TextureHelper.CalculateMipLevels(oldDescription.Width, oldDescription.Height);

      if (oldDescription.MipLevels != newDescription.MipLevels)
      {
        // Update Description and Images.
        var oldImages = Images;
        Description = newDescription;

        ValidateTexture(newDescription);

        // Recreate image collection. (Mipmap level 0 is copied from existing image collection.)
        Images = CreateImageCollection(newDescription, true);
        for (int arrayIndex = 0; arrayIndex < newDescription.ArraySize; arrayIndex++)
        {
          for (int zIndex = 0; zIndex < newDescription.Depth; zIndex++)
          {
            int oldIndex = oldDescription.GetImageIndex(0, arrayIndex, zIndex);
            int newIndex = newDescription.GetImageIndex(0, arrayIndex, zIndex);
            Images[newIndex] = oldImages[oldIndex];
          }
        }
      }

      // Downsample mipmap levels.
      for (int arrayIndex = 0; arrayIndex < newDescription.ArraySize; arrayIndex++)
        for (int mipIndex = 0; mipIndex < newDescription.MipLevels - 1; mipIndex++)
          TextureHelper.Resize(this, mipIndex, arrayIndex, this, mipIndex + 1, arrayIndex, filter, alphaTransparency, wrapMode);
    }
Beispiel #6
0
    /// <summary>
    /// Determines the number of image array entries and pixel size.
    /// </summary>
    /// <param name="description">The texture description.</param>
    /// <param name="nImages">The number of entries in the image array.</param>
    /// <param name="pixelSize">The total pixel size.</param>
    private static void DetermineImages(TextureDescription description, out int nImages, out int pixelSize)
    {
      Debug.Assert(description.Width > 0 && description.Height > 0 && description.Depth > 0);
      Debug.Assert(description.ArraySize > 0);
      Debug.Assert(description.MipLevels > 0);

      pixelSize = 0;
      nImages = 0;

      switch (description.Dimension)
      {
        case TextureDimension.Texture1D:
        case TextureDimension.Texture2D:
        case TextureDimension.TextureCube:
          for (int item = 0; item < description.ArraySize; item++)
          {
            int w = description.Width;
            int h = description.Height;

            for (int level = 0; level < description.MipLevels; level++)
            {
              int rowPitch, slicePitch;
              TextureHelper.ComputePitch(description.Format, w, h, out rowPitch, out slicePitch, ComputePitchFlags.None);
              pixelSize += slicePitch;
              nImages++;

              if (h > 1)
                h >>= 1;

              if (w > 1)
                w >>= 1;
            }
          }
          break;

        case TextureDimension.Texture3D:
          {
            int w = description.Width;
            int h = description.Height;
            int d = description.Depth;

            for (int level = 0; level < description.MipLevels; level++)
            {
              int rowPitch, slicePitch;
              TextureHelper.ComputePitch(description.Format, w, h, out rowPitch, out slicePitch, ComputePitchFlags.None);

              for (int slice = 0; slice < d; slice++)
              {
                pixelSize += slicePitch;
                nImages++;
              }

              if (h > 1)
                h >>= 1;

              if (w > 1)
                w >>= 1;

              if (d > 1)
                d >>= 1;
            }
          }
          break;

        default:
          Debug.Fail("Unexpected texture dimension");
          break;
      }
    }
Beispiel #7
0
    private static TextureDescription DecodeMetadata(ImagingFactory imagingFactory, WicFlags flags, BitmapDecoder decoder, BitmapFrameDecode frame, out Guid pixelFormat)
    {
      var size = frame.Size;

      var description = new TextureDescription
      {
        Dimension = TextureDimension.Texture2D,
        Width = size.Width,
        Height = size.Height,
        Depth = 1,
        MipLevels = 1,
        ArraySize = (flags & WicFlags.AllFrames) != 0 ? decoder.FrameCount : 1,
        Format = DetermineFormat(imagingFactory, frame.PixelFormat, flags, out pixelFormat)
      };

      if (description.Format == DataFormat.Unknown)
        throw new NotSupportedException("The pixel format is not supported.");

      if ((flags & WicFlags.IgnoreSrgb) == 0)
      {
        // Handle sRGB.
#pragma warning disable 168
        try
        {
          Guid containerFormat = decoder.ContainerFormat;
          var metareader = frame.MetadataQueryReader;
          if (metareader != null)
          {
            // Check for sRGB color space metadata.
            bool sRgb = false;

            if (containerFormat == ContainerFormatGuids.Png)
            {
              // Check for sRGB chunk.
              if (metareader.GetMetadataByName("/sRGB/RenderingIntent") != null)
                sRgb = true;
            }
            else if (containerFormat == ContainerFormatGuids.Jpeg)
            {
              if (Equals(metareader.GetMetadataByName("/app1/ifd/exif/{ushort=40961}"), 1))
                sRgb = true;
            }
            else if (containerFormat == ContainerFormatGuids.Tiff)
            {
              if (Equals(metareader.GetMetadataByName("/ifd/exif/{ushort=40961}"), 1))
                sRgb = true;
            }
            else
            {
              if (Equals(metareader.GetMetadataByName("System.Image.ColorSpace"), 1))
                sRgb = true;
            }

            if (sRgb)
              description.Format = TextureHelper.MakeSRgb(description.Format);
          }
        }
        // ReSharper disable once EmptyGeneralCatchClause
        catch (Exception exception)
        {
          // Some formats just don't support metadata (BMP, ICO, etc.).
        }
      }
#pragma warning restore 168

      return description;
    }