/// <summary>
        /// Swizzles (RGB &lt;-&gt; BGR) an image row with optional clearing of alpha value to 1.0.
        /// (Can be used in place as well; otherwise copies the image row unmodified.)
        /// </summary>
        internal static void SwizzleScanline(BinaryReader reader, int inSize, BinaryWriter writer, int outSize, DataFormat format, ScanlineFlags flags)
        {
            Debug.Assert(reader != null && inSize > 0);
              Debug.Assert(writer != null && outSize > 0);
              Debug.Assert(IsValidDds(format) && !IsPlanar(format) && !IsPalettized(format));

              switch (format)
              {
            //---------------------------------------------------------------------------------
            case DataFormat.R10G10B10A2_TYPELESS:
            case DataFormat.R10G10B10A2_UNORM:
            case DataFormat.R10G10B10A2_UINT:
            case DataFormat.R10G10B10_XR_BIAS_A2_UNORM:
            case DataFormat.R10G10B10_SNORM_A2_UNORM:
              if (inSize >= 4 && outSize >= 4)
              {
            if ((flags & ScanlineFlags.Legacy) != 0)
            {
              // Swap Red (R) and Blue (B) channel (used for D3DFMT_A2R10G10B10 legacy sources)
              int size = Math.Min(outSize, inSize);
              for (int count = 0; count < (size - 3); count += 4)
              {
                uint t = reader.ReadUInt32();

                uint t1 = (t & 0x3ff00000) >> 20;
                uint t2 = (t & 0x000003ff) << 20;
                uint t3 = (t & 0x000ffc00);
                uint ta = (flags & ScanlineFlags.SetAlpha) != 0 ? 0xC0000000 : (t & 0xC0000000);

                writer.Write((uint)(t1 | t2 | t3 | ta));
              }
              return;
            }
              }
              break;

            //---------------------------------------------------------------------------------
            case DataFormat.R8G8B8A8_TYPELESS:
            case DataFormat.R8G8B8A8_UNORM:
            case DataFormat.R8G8B8A8_UNORM_SRGB:
            case DataFormat.B8G8R8A8_UNORM:
            case DataFormat.B8G8R8X8_UNORM:
            case DataFormat.B8G8R8A8_TYPELESS:
            case DataFormat.B8G8R8A8_UNORM_SRGB:
            case DataFormat.B8G8R8X8_TYPELESS:
            case DataFormat.B8G8R8X8_UNORM_SRGB:
              if (inSize >= 4 && outSize >= 4)
              {
            // Swap Red (R) and Blue (B) channels (used to convert from DXGI 1.1 BGR formats to DXGI 1.0 RGB)
            int size = Math.Min(outSize, inSize);
            for (int count = 0; count < (size - 3); count += 4)
            {
              uint t = reader.ReadUInt32();

              uint t1 = (t & 0x00ff0000) >> 16;
              uint t2 = (t & 0x000000ff) << 16;
              uint t3 = (t & 0x0000ff00);
              uint ta = (flags & ScanlineFlags.SetAlpha) != 0 ? 0xff000000 : (t & 0xFF000000);

              writer.Write((uint)(t1 | t2 | t3 | ta));
            }
            return;
              }
              break;

            //---------------------------------------------------------------------------------
            case DataFormat.YUY2:
              if (inSize >= 4 && outSize >= 4)
              {
            if ((flags & ScanlineFlags.Legacy) != 0)
            {
              // Reorder YUV components (used to convert legacy UYVY -> YUY2)
              int size = Math.Min(outSize, inSize);
              for (int count = 0; count < (size - 3); count += 4)
              {
                uint t = reader.ReadUInt32();

                uint t1 = (t & 0x000000ff) << 8;
                uint t2 = (t & 0x0000ff00) >> 8;
                uint t3 = (t & 0x00ff0000) << 8;
                uint t4 = (t & 0xff000000) >> 8;

                writer.Write((uint)(t1 | t2 | t3 | t4));
              }
              return;
            }
              }
              break;
              }

              // Fall-through case is to just use memcpy (assuming this is not an in-place operation)
              byte[] scanline = reader.ReadBytes(Math.Min(inSize, outSize));
              writer.Write(scanline);
        }
        //--------------------------------------------------------------
        /// <summary>
        /// Copies an image row with optional clearing of alpha value to 1.0.
        /// </summary>
        internal static void CopyScanline(BinaryReader reader, int inSize, BinaryWriter writer, int outSize, DataFormat format, ScanlineFlags flags)
        {
            Debug.Assert(reader != null && inSize > 0);
              Debug.Assert(writer != null && outSize > 0);
              Debug.Assert(IsValidDds(format) && !IsPalettized(format));

              if ((flags & ScanlineFlags.SetAlpha) != 0)
              {
            switch (format)
            {
              //-----------------------------------------------------------------------------
              case DataFormat.R32G32B32A32_TYPELESS:
              case DataFormat.R32G32B32A32_FLOAT:
              case DataFormat.R32G32B32A32_UINT:
              case DataFormat.R32G32B32A32_SINT:
            if (inSize >= 16 && outSize >= 16)
            {
              uint alpha;
              if (format == DataFormat.R32G32B32A32_FLOAT)
                alpha = 0x3f800000;
              else if (format == DataFormat.R32G32B32A32_SINT)
                alpha = 0x7fffffff;
              else
                alpha = 0xffffffff;

              int size = Math.Min(outSize, inSize);
              for (int count = 0; count < (size - 15); count += 16)
              {
                writer.Write(reader.ReadInt32());
                writer.Write(reader.ReadInt32());
                writer.Write(reader.ReadInt32());
                reader.ReadInt32(); // Ignore
                writer.Write(alpha);
              }
            }
            return;

              //-----------------------------------------------------------------------------
              case DataFormat.R16G16B16A16_TYPELESS:
              case DataFormat.R16G16B16A16_FLOAT:
              case DataFormat.R16G16B16A16_UNORM:
              case DataFormat.R16G16B16A16_UINT:
              case DataFormat.R16G16B16A16_SNORM:
              case DataFormat.R16G16B16A16_SINT:
              case DataFormat.Y416:
            if (inSize >= 8 && outSize >= 8)
            {
              ushort alpha;
              if (format == DataFormat.R16G16B16A16_FLOAT)
                alpha = 0x3c00;
              else if (format == DataFormat.R16G16B16A16_SNORM || format == DataFormat.R16G16B16A16_SINT)
                alpha = 0x7fff;
              else
                alpha = 0xffff;

              int size = Math.Min(outSize, inSize);
              for (int count = 0; count < (size - 7); count += 8)
              {
                writer.Write(reader.ReadUInt16());
                writer.Write(reader.ReadUInt16());
                writer.Write(reader.ReadUInt16());
                reader.ReadUInt16(); // Ignore
                writer.Write(alpha);
              }
            }
            return;

              //-----------------------------------------------------------------------------
              case DataFormat.R10G10B10A2_TYPELESS:
              case DataFormat.R10G10B10A2_UNORM:
              case DataFormat.R10G10B10A2_UINT:
              case DataFormat.R10G10B10_XR_BIAS_A2_UNORM:
              case DataFormat.Y410:
              case DataFormat.R10G10B10_7E3_A2_FLOAT:
              case DataFormat.R10G10B10_6E4_A2_FLOAT:
              case DataFormat.R10G10B10_SNORM_A2_UNORM:
            if (inSize >= 4 && outSize >= 4)
            {
              int size = Math.Min(outSize, inSize);
              for (int count = 0; count < (size - 3); count += 4)
              {
                writer.Write(reader.ReadUInt32() | 0xC0000000);
              }
            }
            return;

              //-----------------------------------------------------------------------------
              case DataFormat.R8G8B8A8_TYPELESS:
              case DataFormat.R8G8B8A8_UNORM:
              case DataFormat.R8G8B8A8_UNORM_SRGB:
              case DataFormat.R8G8B8A8_UINT:
              case DataFormat.R8G8B8A8_SNORM:
              case DataFormat.R8G8B8A8_SINT:
              case DataFormat.B8G8R8A8_UNORM:
              case DataFormat.B8G8R8A8_TYPELESS:
              case DataFormat.B8G8R8A8_UNORM_SRGB:
              case DataFormat.AYUV:
            if (inSize >= 4 && outSize >= 4)
            {
              uint alpha = (format == DataFormat.R8G8B8A8_SNORM || format == DataFormat.R8G8B8A8_SINT) ? 0x7f000000 : 0xff000000;

              int size = Math.Min(outSize, inSize);
              for (int count = 0; count < (size - 3); count += 4)
              {
                uint t = reader.ReadUInt32() & 0xFFFFFF;
                t |= alpha;
                writer.Write(t);
              }
            }
            return;

              //-----------------------------------------------------------------------------
              case DataFormat.B5G5R5A1_UNORM:
            if (inSize >= 2 && outSize >= 2)
            {
              int size = Math.Min(outSize, inSize);
              for (int count = 0; count < (size - 1); count += 2)
              {
                writer.Write((ushort)(reader.ReadUInt16() | 0x8000));
              }
            }
            return;

              //-----------------------------------------------------------------------------
              case DataFormat.A8_UNORM:
            for (int i = 0; i < outSize; i++)
              writer.Write((byte)0xff);
            return;

              //-----------------------------------------------------------------------------
              case DataFormat.B4G4R4A4_UNORM:
            if (inSize >= 2 && outSize >= 2)
            {
              int size = Math.Min(outSize, inSize);
              for (int count = 0; count < (size - 1); count += 2)
              {
                writer.Write((ushort)(reader.ReadUInt16() | 0xF000));
              }
            }
            return;
            }
              }

              // Fall-through case is to just use memcpy (assuming this is not an in-place operation)
              byte[] scanline = reader.ReadBytes(Math.Min(inSize, outSize));
              writer.Write(scanline);
        }
        /// <summary>
        /// Converts an image row with optional clearing of alpha value to 1.0.
        /// </summary>
        internal static bool ExpandScanline(BinaryReader reader, int inSize, DataFormat inFormat, BinaryWriter writer, int outSize, DataFormat outFormat, ScanlineFlags flags)
        {
            Debug.Assert(reader != null && inSize > 0);
              Debug.Assert(writer != null && outSize > 0);
              Debug.Assert(IsValidDds(inFormat) && !IsPlanar(inFormat) && !IsPalettized(inFormat));
              Debug.Assert(IsValidDds(outFormat) && !IsPlanar(outFormat) && !IsPalettized(outFormat));

              bool setAlpha = (flags & ScanlineFlags.SetAlpha) != 0;
              switch (inFormat)
              {
            case DataFormat.B5G6R5_UNORM:
              if (outFormat != DataFormat.R8G8B8A8_UNORM)
            return false;

              // DXGI_FORMAT_B5G6R5_UNORM -> DXGI_FORMAT_R8G8B8A8_UNORM
              if (inSize >= 2 && outSize >= 4)
              {
            for (int ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4)
            {
              ushort t = reader.ReadUInt16();
              writer.Write(DataFormatHelper.Bgr565ToRgba8888(t));
            }
            return true;
              }
              return false;

            case DataFormat.B5G5R5A1_UNORM:
              if (outFormat != DataFormat.R8G8B8A8_UNORM)
            return false;

              // DXGI_FORMAT_B5G5R5A1_UNORM -> DXGI_FORMAT_R8G8B8A8_UNORM
              if (inSize >= 2 && outSize >= 4)
              {
            for (int ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4)
            {
              ushort color = reader.ReadUInt16();
              writer.Write(DataFormatHelper.Bgra5551ToRgba8888(color, setAlpha));
            }
            return true;
              }
              return false;

            case DataFormat.B4G4R4A4_UNORM:
              if (outFormat != DataFormat.R8G8B8A8_UNORM)
            return false;

              // DXGI_FORMAT_B4G4R4A4_UNORM -> DXGI_FORMAT_R8G8B8A8_UNORM
              if (inSize >= 2 && outSize >= 4)
              {
            for (int ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4)
            {
              ushort color = reader.ReadUInt16();
              writer.Write(DataFormatHelper.Bgra4444ToRgba8888(color, setAlpha));
            }
            return true;
              }
              return false;
              }

              return false;
        }
Example #4
0
        /// <summary>
        // Converts an image row with optional clearing of alpha value to 1.0
        /// </summary>
        /// <param name="pDestination"></param>
        /// <param name="outSize"></param>
        /// <param name="outFormat"></param>
        /// <param name="pSource"></param>
        /// <param name="inSize"></param>
        /// <param name="inFormat"></param>
        /// <param name="pal8"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        static unsafe bool LegacyExpandScanline( IntPtr pDestination, int outSize, PixelFormat outFormat, 
                                            IntPtr pSource, int inSize, TEXP_LEGACY_FORMAT inFormat,
                                            uint* pal8, ScanlineFlags flags )
        {
            switch (inFormat)
            {
                case TEXP_LEGACY_FORMAT.R8G8B8:
                    if (outFormat != PixelFormat.R8G8B8A8_UNorm)
                        return false;

                    // D3DFMT_R8G8B8 -> PixelFormat.R8G8B8A8_UNorm
                    {
                        var sPtr = (byte*) (pSource);
                        var dPtr = (uint*) (pDestination);

                        for (int ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 3, ocount += 4)
                        {
                            // 24bpp Direct3D 9 files are actually BGR, so need to swizzle as well
                            uint t1 = (uint)(*(sPtr) << 16);
                            uint t2 = (uint)(*(sPtr + 1) << 8);
                            uint t3 = *(sPtr + 2);

                            *(dPtr++) = (t1 | t2 | t3 | 0xff000000);
                            sPtr += 3;
                        }
                    }
                    return true;

                case TEXP_LEGACY_FORMAT.R3G3B2:
                    switch (outFormat)
                    {
                        case PixelFormat.R8G8B8A8_UNorm:
                            // D3DFMT_R3G3B2 -> PixelFormat.R8G8B8A8_UNorm
                            {
                                var sPtr = (byte*) (pSource);
                                var dPtr = (uint*) (pDestination);

                                for (int ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); ++icount, ocount += 4)
                                {
                                    byte t = *(sPtr++);

                                    uint t1 = (uint)((t & 0xe0) | ((t & 0xe0) >> 3) | ((t & 0xc0) >> 6));
                                    uint t2 = (uint)(((t & 0x1c) << 11) | ((t & 0x1c) << 8) | ((t & 0x18) << 5));
                                    uint t3 = (uint)(((t & 0x03) << 22) | ((t & 0x03) << 20) | ((t & 0x03) << 18) | ((t & 0x03) << 16));

                                    *(dPtr++) = (t1 | t2 | t3 | 0xff000000);
                                }
                            }
                            return true;

                        case PixelFormat.B5G6R5_UNorm:
                            // D3DFMT_R3G3B2 -> PixelFormat.B5G6R5_UNorm
                            {
                                var sPtr = (byte*) (pSource);
                                var dPtr = (short*) (pDestination);

                                for (int ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); ++icount, ocount += 2)
                                {
                                    byte t = *(sPtr++);

                                    var t1 = (uint) (((t & 0xe0) << 8) | ((t & 0xc0) << 5));
                                    var t2 = (uint) (((t & 0x1c) << 6) | ((t & 0x1c) << 3));
                                    var t3 = (uint) (((t & 0x03) << 3) | ((t & 0x03) << 1) | ((t & 0x02) >> 1));

                                    *(dPtr++) = (short) (t1 | t2 | t3);
                                }
                            }
                            return true;
                    }
                    break;

                case TEXP_LEGACY_FORMAT.A8R3G3B2:
                    if (outFormat != PixelFormat.R8G8B8A8_UNorm)
                        return false;

                    // D3DFMT_A8R3G3B2 -> PixelFormat.R8G8B8A8_UNorm
                    {
                        var sPtr = (short*) (pSource);
                        var dPtr = (uint*) (pDestination);

                        for (int ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4)
                        {
                            short t = *(sPtr++);

                            uint t1 = (uint)((t & 0x00e0) | ((t & 0x00e0) >> 3) | ((t & 0x00c0) >> 6));
                            uint t2 = (uint)(((t & 0x001c) << 11) | ((t & 0x001c) << 8) | ((t & 0x0018) << 5));
                            uint t3 = (uint)(((t & 0x0003) << 22) | ((t & 0x0003) << 20) | ((t & 0x0003) << 18) | ((t & 0x0003) << 16));
                            uint ta = ((flags & ScanlineFlags.SetAlpha) != 0 ? 0xff000000 : (uint) ((t & 0xff00) << 16));

                            *(dPtr++) = (t1 | t2 | t3 | ta);
                        }
                    }
                    return true;

                case TEXP_LEGACY_FORMAT.P8:
                    if ((outFormat != PixelFormat.R8G8B8A8_UNorm) || pal8 == null)
                        return false;

                    // D3DFMT_P8 -> PixelFormat.R8G8B8A8_UNorm
                    {
                        byte* sPtr = (byte*) (pSource);
                        var dPtr = (uint*) (pDestination);

                        for (int ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); ++icount, ocount += 4)
                        {
                            byte t = *(sPtr++);

                            *(dPtr++) = pal8[t];
                        }
                    }
                    return true;

                case TEXP_LEGACY_FORMAT.A8P8:
                    if ((outFormat != PixelFormat.R8G8B8A8_UNorm) || pal8 == null)
                        return false;

                    // D3DFMT_A8P8 -> PixelFormat.R8G8B8A8_UNorm
                    {
                        short* sPtr = (short*) (pSource);
                        int* dPtr = (int*) (pDestination);

                        for (int ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4)
                        {
                            short t = *(sPtr++);

                            uint t1 = pal8[t & 0xff];
                            uint ta = ((flags & ScanlineFlags.SetAlpha) != 0 ? 0xff000000 : (uint) ((t & 0xff00) << 16));

                            *(dPtr++) = (int) (t1 | ta);
                        }
                    }
                    return true;

                case TEXP_LEGACY_FORMAT.A4L4:
                    switch (outFormat)
                    {
#if DIRECTX11_1
                case PixelFormat.B4G4R4A4_UNorm :
                    // D3DFMT_A4L4 -> PixelFormat.B4G4R4A4_UNorm 
                    {
                        byte * sPtr = (byte*)(pSource);
                        short * dPtr = (short*)(pDestination);

                        for( int ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); ++icount, ocount += 2 )
                        {
                            byte t = *(sPtr++);

                            short t1 = (short)(t & 0x0f);
                            ushort ta = (flags & ScanlineFlags.SetAlpha ) != 0 ?  (ushort)0xf000 : (ushort)((t & 0xf0) << 8);

                            *(dPtr++) = (short)(t1 | (t1 << 4) | (t1 << 8) | ta);
                        }
                    }
                    return true;
#endif
                            // DXGI_1_2_FORMATS

                        case PixelFormat.R8G8B8A8_UNorm:
                            // D3DFMT_A4L4 -> PixelFormat.R8G8B8A8_UNorm
                            {
                                byte* sPtr = (byte*) (pSource);
                                var dPtr = (uint*) (pDestination);

                                for (int ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); ++icount, ocount += 4)
                                {
                                    byte t = *(sPtr++);

                                    uint t1 = (uint)(((t & 0x0f) << 4) | (t & 0x0f));
                                    uint ta = ((flags & ScanlineFlags.SetAlpha) != 0 ? 0xff000000 : (uint) (((t & 0xf0) << 24) | ((t & 0xf0) << 20)));

                                    *(dPtr++) = (t1 | (t1 << 8) | (t1 << 16) | ta);
                                }
                            }
                            return true;
                    }
                    break;

#if !DIRECTX11_1
                case TEXP_LEGACY_FORMAT.B4G4R4A4:
                    if (outFormat != PixelFormat.R8G8B8A8_UNorm)
                        return false;

                    // D3DFMT_A4R4G4B4 -> PixelFormat.R8G8B8A8_UNorm
                    {
                        short* sPtr = (short*) (pSource);
                        var dPtr = (uint*) (pDestination);

                        for (int ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4)
                        {
                            short t = *(sPtr++);

                            uint t1 = (uint)(((t & 0x0f00) >> 4) | ((t & 0x0f00) >> 8));
                            uint t2 = (uint)(((t & 0x00f0) << 8) | ((t & 0x00f0) << 4));
                            uint t3 = (uint)(((t & 0x000f) << 20) | ((t & 0x000f) << 16));
                            uint ta = ((flags & ScanlineFlags.SetAlpha) != 0 ? 0xff000000 : (uint) (((t & 0xf000) << 16) | ((t & 0xf000) << 12)));

                            *(dPtr++) = (t1 | t2 | t3 | ta);
                        }
                    }
                    return true;
#endif
            }
            return false;
        }
Example #5
0
        /// <summary>
        /// Swizzles (RGB &lt;-&gt; BGR) an image row with optional clearing of alpha value to 1.0.
        /// </summary>
        /// <param name="pDestination">The destination buffer.</param>
        /// <param name="outSize">The destination size.</param>
        /// <param name="pSource">The source buffer.</param>
        /// <param name="inSize">The source size.</param>
        /// <param name="format">The <see cref="Format"/> of the source scanline.</param>
        /// <param name="flags">Scanline flags used when copying the scanline.</param>
        /// <remarks>
        /// This method can be used in place as well, otherwise copies the image row unmodified.
        /// </remarks>
        internal static unsafe void SwizzleScanline(IntPtr pDestination, int outSize, IntPtr pSource, int inSize, PixelFormat format, ScanlineFlags flags)
        {
            switch (format)
            {
                //---------------------------------------------------------------------------------
                case PixelFormat.R10G10B10A2_Typeless:
                case PixelFormat.R10G10B10A2_UNorm:
                case PixelFormat.R10G10B10A2_UInt:
                case PixelFormat.R10G10B10_Xr_Bias_A2_UNorm:
                    if ((flags & ScanlineFlags.Legacy) != 0)
                    {
                        // Swap Red (R) and Blue (B) channel (used for D3DFMT_A2R10G10B10 legacy sources)
                        if (pDestination == pSource)
                        {
                            var dPtr = (uint*)(pDestination);
                            for (int count = 0; count < outSize; count += 4)
                            {
                                uint t = *dPtr;

                                uint t1 = (t & 0x3ff00000) >> 20;
                                uint t2 = (t & 0x000003ff) << 20;
                                uint t3 = (t & 0x000ffc00);
                                uint ta = (flags & ScanlineFlags.SetAlpha) != 0 ? 0xC0000000 : (t & 0xC0000000);

                                *(dPtr++) = t1 | t2 | t3 | ta;
                            }
                        }
                        else
                        {
                            var sPtr = (uint*)(pSource);
                            var dPtr = (uint*)(pDestination);
                            int size = Math.Min(outSize, inSize);
                            for (int count = 0; count < size; count += 4)
                            {
                                uint t = *(sPtr++);

                                uint t1 = (t & 0x3ff00000) >> 20;
                                uint t2 = (t & 0x000003ff) << 20;
                                uint t3 = (t & 0x000ffc00);
                                uint ta = (flags & ScanlineFlags.SetAlpha) != 0 ? 0xC0000000 : (t & 0xC0000000);

                                *(dPtr++) = t1 | t2 | t3 | ta;
                            }
                        }
                        return;
                    }
                    break;

                //---------------------------------------------------------------------------------
                case PixelFormat.R8G8B8A8_Typeless:
                case PixelFormat.R8G8B8A8_UNorm:
                case PixelFormat.R8G8B8A8_UNorm_SRgb:
                case PixelFormat.B8G8R8A8_UNorm:
                case PixelFormat.B8G8R8X8_UNorm:
                case PixelFormat.B8G8R8A8_Typeless:
                case PixelFormat.B8G8R8A8_UNorm_SRgb:
                case PixelFormat.B8G8R8X8_Typeless:
                case PixelFormat.B8G8R8X8_UNorm_SRgb:
                    // Swap Red (R) and Blue (B) channels (used to convert from DXGI 1.1 BGR formats to DXGI 1.0 RGB)
                    if (pDestination == pSource)
                    {
                        var dPtr = (uint*)(pDestination);
                        for (int count = 0; count < outSize; count += 4)
                        {
                            uint t = *dPtr;

                            uint t1 = (t & 0x00ff0000) >> 16;
                            uint t2 = (t & 0x000000ff) << 16;
                            uint t3 = (t & 0x0000ff00);
                            uint ta = (flags & ScanlineFlags.SetAlpha) != 0 ? 0xff000000 : (t & 0xFF000000);

                            *(dPtr++) = t1 | t2 | t3 | ta;
                        }
                    }
                    else
                    {
                        var sPtr = (uint*)(pSource);
                        var dPtr = (uint*)(pDestination);
                        int size = Math.Min(outSize, inSize);
                        for (int count = 0; count < size; count += 4)
                        {
                            uint t = *(sPtr++);

                            uint t1 = (t & 0x00ff0000) >> 16;
                            uint t2 = (t & 0x000000ff) << 16;
                            uint t3 = (t & 0x0000ff00);
                            uint ta = (flags & ScanlineFlags.SetAlpha) != 0 ? 0xff000000 : (t & 0xFF000000);

                            *(dPtr++) = t1 | t2 | t3 | ta;
                        }
                    }
                    return;
            }

            // Fall-through case is to just use memcpy (assuming this is not an in-place operation)
            if (pDestination == pSource)
                return;

            Utilities.CopyMemory(pDestination, pSource, Math.Min(outSize, inSize));
        }
Example #6
0
        /// <summary>
        /// Copies an image row with optional clearing of alpha value to 1.0.
        /// </summary>
        /// <remarks>
        /// This method can be used in place as well, otherwise copies the image row unmodified.
        /// </remarks>
        /// <param name="pDestination">The destination buffer.</param>
        /// <param name="outSize">The destination size.</param>
        /// <param name="pSource">The source buffer.</param>
        /// <param name="inSize">The source size.</param>
        /// <param name="format">The <see cref="Format"/> of the source scanline.</param>
        /// <param name="flags">Scanline flags used when copying the scanline.</param>
        internal static unsafe void CopyScanline(IntPtr pDestination, int outSize, IntPtr pSource, int inSize, PixelFormat format, ScanlineFlags flags)
        {
            if ((flags & ScanlineFlags.SetAlpha) != 0)
            {
                switch (format)
                {
                    //-----------------------------------------------------------------------------
                    case PixelFormat.R32G32B32A32_Typeless:
                    case PixelFormat.R32G32B32A32_Float:
                    case PixelFormat.R32G32B32A32_UInt:
                    case PixelFormat.R32G32B32A32_SInt:
                        {
                            uint alpha;
                            if (format == PixelFormat.R32G32B32A32_Float)
                                alpha = 0x3f800000;
                            else if (format == PixelFormat.R32G32B32A32_SInt)
                                alpha = 0x7fffffff;
                            else
                                alpha = 0xffffffff;

                            if (pDestination == pSource)
                            {
                                var dPtr = (uint*)(pDestination);
                                for (int count = 0; count < outSize; count += 16)
                                {
                                    dPtr += 3;
                                    *(dPtr++) = alpha;
                                }
                            }
                            else
                            {
                                var sPtr = (uint*)(pSource);
                                var dPtr = (uint*)(pDestination);
                                int size = Math.Min(outSize, inSize);
                                for (int count = 0; count < size; count += 16)
                                {
                                    *(dPtr++) = *(sPtr++);
                                    *(dPtr++) = *(sPtr++);
                                    *(dPtr++) = *(sPtr++);
                                    *(dPtr++) = alpha;
                                    sPtr++;
                                }
                            }
                        }
                        return;

                    //-----------------------------------------------------------------------------
                    case PixelFormat.R16G16B16A16_Typeless:
                    case PixelFormat.R16G16B16A16_Float:
                    case PixelFormat.R16G16B16A16_UNorm:
                    case PixelFormat.R16G16B16A16_UInt:
                    case PixelFormat.R16G16B16A16_SNorm:
                    case PixelFormat.R16G16B16A16_SInt:
                        {
                            ushort alpha;
                            if (format == PixelFormat.R16G16B16A16_Float)
                                alpha = 0x3c00;
                            else if (format == PixelFormat.R16G16B16A16_SNorm || format == PixelFormat.R16G16B16A16_SInt)
                                alpha = 0x7fff;
                            else
                                alpha = 0xffff;

                            if (pDestination == pSource)
                            {
                                var dPtr = (ushort*)(pDestination);
                                for (int count = 0; count < outSize; count += 8)
                                {
                                    dPtr += 3;
                                    *(dPtr++) = alpha;
                                }
                            }
                            else
                            {
                                var sPtr = (ushort*)(pSource);
                                var dPtr = (ushort*)(pDestination);
                                int size = Math.Min(outSize, inSize);
                                for (int count = 0; count < size; count += 8)
                                {
                                    *(dPtr++) = *(sPtr++);
                                    *(dPtr++) = *(sPtr++);
                                    *(dPtr++) = *(sPtr++);
                                    *(dPtr++) = alpha;
                                    sPtr++;
                                }
                            }
                        }
                        return;

                    //-----------------------------------------------------------------------------
                    case PixelFormat.R10G10B10A2_Typeless:
                    case PixelFormat.R10G10B10A2_UNorm:
                    case PixelFormat.R10G10B10A2_UInt:
                    case PixelFormat.R10G10B10_Xr_Bias_A2_UNorm:
                        {
                            if (pDestination == pSource)
                            {
                                var dPtr = (uint*)(pDestination);
                                for (int count = 0; count < outSize; count += 4)
                                {
                                    *dPtr |= 0xC0000000;
                                    ++dPtr;
                                }
                            }
                            else
                            {
                                var sPtr = (uint*)(pSource);
                                var dPtr = (uint*)(pDestination);
                                int size = Math.Min(outSize, inSize);
                                for (int count = 0; count < size; count += 4)
                                {
                                    *(dPtr++) = *(sPtr++) | 0xC0000000;
                                }
                            }
                        }
                        return;

                    //-----------------------------------------------------------------------------
                    case PixelFormat.R8G8B8A8_Typeless:
                    case PixelFormat.R8G8B8A8_UNorm:
                    case PixelFormat.R8G8B8A8_UNorm_SRgb:
                    case PixelFormat.R8G8B8A8_UInt:
                    case PixelFormat.R8G8B8A8_SNorm:
                    case PixelFormat.R8G8B8A8_SInt:
                    case PixelFormat.B8G8R8A8_UNorm:
                    case PixelFormat.B8G8R8A8_Typeless:
                    case PixelFormat.B8G8R8A8_UNorm_SRgb:
                        {
                            uint alpha = (format == PixelFormat.R8G8B8A8_SNorm || format == PixelFormat.R8G8B8A8_SInt) ? 0x7f000000 : 0xff000000;

                            if (pDestination == pSource)
                            {
                                var dPtr = (uint*)(pDestination);
                                for (int count = 0; count < outSize; count += 4)
                                {
                                    uint t = *dPtr & 0xFFFFFF;
                                    t |= alpha;
                                    *(dPtr++) = t;
                                }
                            }
                            else
                            {
                                var sPtr = (uint*)(pSource);
                                var dPtr = (uint*)(pDestination);
                                int size = Math.Min(outSize, inSize);
                                for (int count = 0; count < size; count += 4)
                                {
                                    uint t = *(sPtr++) & 0xFFFFFF;
                                    t |= alpha;
                                    *(dPtr++) = t;
                                }
                            }
                        }
                        return;

                    //-----------------------------------------------------------------------------
                    case PixelFormat.B5G5R5A1_UNorm:
                        {
                            if (pDestination == pSource)
                            {
                                var dPtr = (ushort*)(pDestination);
                                for (int count = 0; count < outSize; count += 2)
                                {
                                    *(dPtr++) |= 0x8000;
                                }
                            }
                            else
                            {
                                var sPtr = (ushort*)(pSource);
                                var dPtr = (ushort*)(pDestination);
                                int size = Math.Min(outSize, inSize);
                                for (int count = 0; count < size; count += 2)
                                {
                                    *(dPtr++) = (ushort)(*(sPtr++) | 0x8000);
                                }
                            }
                        }
                        return;

                    //-----------------------------------------------------------------------------
                    case PixelFormat.A8_UNorm:
                        Utilities.ClearMemory(pDestination, 0xff, outSize);
                        return;

#if DIRECTX11_1
                    //-----------------------------------------------------------------------------
                    case PixelFormat.B4G4R4A4_UNorm:
                        {
                            if (pDestination == pSource)
                            {
                                var dPtr = (ushort*) (pDestination);
                                for (int count = 0; count < outSize; count += 2)
                                {
                                    *(dPtr++) |= 0xF000;
                                }
                            }
                            else
                            {
                                var sPtr = (ushort*) (pSource);
                                var dPtr = (ushort*) (pDestination);
                                int size = Math.Min(outSize, inSize);
                                for (int count = 0; count < size; count += 2)
                                {
                                    *(dPtr++) = (ushort) (*(sPtr++) | 0xF000);
                                }
                            }
                        }
                        return;
#endif
                    // DXGI_1_2_FORMATS
                }
            }

            // Fall-through case is to just use memcpy (assuming this is not an in-place operation)
            if (pDestination == pSource)
                return;

            Utilities.CopyMemory(pDestination, pSource, Math.Min(outSize, inSize));
        }
Example #7
0
        /// <summary>
        /// Converts an image row with optional clearing of alpha value to 1.0
        /// </summary>
        /// <param name="pDestination"></param>
        /// <param name="outSize"></param>
        /// <param name="pSource"></param>
        /// <param name="inSize"></param>
        /// <param name="inFormat"></param>
        /// <param name="flags"></param>
        private unsafe static void ExpandScanline(IntPtr pDestination, int outSize, IntPtr pSource, int inSize, PixelFormat inFormat, ScanlineFlags flags)
        {
            switch (inFormat)
            {
                case PixelFormat.B5G6R5_UNorm:
                    // PixelFormat.B5G6R5_UNorm -> PixelFormat.R8G8B8A8_UNorm
                    {
                        var sPtr = (ushort*) (pSource);
                        var dPtr = (uint*) (pDestination);

                        for (uint ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4)
                        {
                            ushort t = *(sPtr++);

                            uint t1 = (uint) (((t & 0xf800) >> 8) | ((t & 0xe000) >> 13));
                            uint t2 = (uint) (((t & 0x07e0) << 5) | ((t & 0x0600) >> 5));
                            uint t3 = (uint) (((t & 0x001f) << 19) | ((t & 0x001c) << 14));

                            *(dPtr++) = t1 | t2 | t3 | 0xff000000;
                        }
                    }
                    break;

                case PixelFormat.B5G5R5A1_UNorm:
                    // PixelFormat.B5G5R5A1_UNorm -> PixelFormat.R8G8B8A8_UNorm
                    {
                        var sPtr = (ushort*) (pSource);
                        var dPtr = (uint*) (pDestination);

                        for (uint ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4)
                        {
                            ushort t = *(sPtr++);

                            uint t1 = (uint) (((t & 0x7c00) >> 7) | ((t & 0x7000) >> 12));
                            uint t2 = (uint) (((t & 0x03e0) << 6) | ((t & 0x0380) << 1));
                            uint t3 = (uint) (((t & 0x001f) << 19) | ((t & 0x001c) << 14));
                            uint ta = (uint) ((flags & ScanlineFlags.SetAlpha) != 0 ? 0xff000000 : (((t & 0x8000) != 0 ? 0xff000000 : 0)));

                            *(dPtr++) = t1 | t2 | t3 | ta;
                        }
                    }
                    break;

#if DIRECTX11_1
                case PixelFormat.B4G4R4A4_UNorm:
                    // PixelFormat.B4G4R4A4_UNorm -> PixelFormat.R8G8B8A8_UNorm
                    {
                        var sPtr = (ushort*) (pSource);
                        var dPtr = (uint*) (pDestination);

                        for (uint ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4)
                        {
                            ushort t = *(sPtr++);

                            uint t1 = (uint) (((t & 0x0f00) >> 4) | ((t & 0x0f00) >> 8));
                            uint t2 = (uint) (((t & 0x00f0) << 8) | ((t & 0x00f0) << 4));
                            uint t3 = (uint) (((t & 0x000f) << 20) | ((t & 0x000f) << 16));
                            uint ta = (flags & ScanlineFlags.SetAlpha) != 0 ? 0xff000000 : (uint) ((((t & 0xf000) << 16) | ((t & 0xf000) << 12)));

                            *(dPtr++) = t1 | t2 | t3 | ta;
                        }
                    }
                    break;
#endif
// DXGI_1_2_FORMATS
            }
        }
Example #8
0
        private static bool LegacyExpandScanline(BinaryReader reader, int inSize, LegacyFormat inFormat, BinaryWriter writer, int outSize, DataFormat outFormat, uint[] pal8, ScanlineFlags flags)
        {
            Debug.Assert(reader != null && inSize > 0);
              Debug.Assert(writer != null && outSize > 0);
              Debug.Assert(TextureHelper.IsValidDds(outFormat) && !TextureHelper.IsPlanar(outFormat) && !TextureHelper.IsPalettized(outFormat));

              switch (inFormat)
              {
            case LegacyFormat.R8G8B8:
              if (outFormat != DataFormat.R8G8B8A8_UNORM)
            return false;

              // D3DFMT_R8G8B8 -> DXGI_FORMAT_R8G8B8A8_UNORM
              if (inSize >= 3 && outSize >= 4)
              {
            for (int ocount = 0, icount = 0; ((icount < (inSize - 2)) && (ocount < (outSize - 3))); icount += 3, ocount += 4)
            {
              // 24bpp Direct3D 9 files are actually BGR, so need to swizzle as well
              uint t1 = (uint)(reader.ReadByte() << 16);
              uint t2 = (uint)(reader.ReadByte() << 8);
              uint t3 = reader.ReadByte();

              writer.Write((int)(t1 | t2 | t3 | 0xff000000));
            }
            return true;
              }
              return false;

            case LegacyFormat.R3G3B2:
              switch (outFormat)
              {
            case DataFormat.R8G8B8A8_UNORM:
              // D3DFMT_R3G3B2 -> DXGI_FORMAT_R8G8B8A8_UNORM
              if (inSize >= 1 && outSize >= 4)
              {
                for (int ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 3))); ++icount, ocount += 4)
                {
                  byte t = reader.ReadByte();

                  uint t1 = (uint)((t & 0xe0) | ((t & 0xe0) >> 3) | ((t & 0xc0) >> 6));
                  uint t2 = (uint)(((t & 0x1c) << 11) | ((t & 0x1c) << 8) | ((t & 0x18) << 5));
                  uint t3 = (uint)(((t & 0x03) << 22) | ((t & 0x03) << 20) | ((t & 0x03) << 18) | ((t & 0x03) << 16));

                  writer.Write((int)(t1 | t2 | t3 | 0xff000000));
                }
                return true;
              }
              return false;

            case DataFormat.B5G6R5_UNORM:
              // D3DFMT_R3G3B2 -> DXGI_FORMAT_B5G6R5_UNORM
              if (inSize >= 1 && outSize >= 2)
              {
                for (int ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 1))); ++icount, ocount += 2)
                {
                  byte t = reader.ReadByte();

                  int t1 = ((t & 0xe0) << 8) | ((t & 0xc0) << 5);
                  int t2 = ((t & 0x1c) << 6) | ((t & 0x1c) << 3);
                  int t3 = ((t & 0x03) << 3) | ((t & 0x03) << 1) | ((t & 0x02) >> 1);

                  writer.Write((short)(t1 | t2 | t3));
                }
                return true;
              }
              return false;
              }
              break;

            case LegacyFormat.A8R3G3B2:
              if (outFormat != DataFormat.R8G8B8A8_UNORM)
            return false;

              // D3DFMT_A8R3G3B2 -> DXGI_FORMAT_R8G8B8A8_UNORM
              if (inSize >= 2 && outSize >= 4)
              {
            for (int ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4)
            {
              short t = reader.ReadInt16();

              uint t1 = (uint)((t & 0x00e0) | ((t & 0x00e0) >> 3) | ((t & 0x00c0) >> 6));
              uint t2 = (uint)(((t & 0x001c) << 11) | ((t & 0x001c) << 8) | ((t & 0x0018) << 5));
              uint t3 = (uint)(((t & 0x0003) << 22) | ((t & 0x0003) << 20) | ((t & 0x0003) << 18) | ((t & 0x0003) << 16));
              uint ta = ((flags & ScanlineFlags.SetAlpha) != 0 ? 0xff000000 : (uint)((t & 0xff00) << 16));

              writer.Write((uint)(t1 | t2 | t3 | ta));
            }
            return true;
              }
              return false;

            case LegacyFormat.P8:
              if ((outFormat != DataFormat.R8G8B8A8_UNORM) || pal8 == null)
            return false;

              // D3DFMT_P8 -> DXGI_FORMAT_R8G8B8A8_UNORM
              if (inSize >= 1 && outSize >= 4)
              {
            for (int ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 3))); ++icount, ocount += 4)
            {
              byte t = reader.ReadByte();
              writer.Write(pal8[t]);
            }
            return true;
              }
              return false;

            case LegacyFormat.A8P8:
              if ((outFormat != DataFormat.R8G8B8A8_UNORM) || pal8 == null)
            return false;

              // D3DFMT_A8P8 -> DXGI_FORMAT_R8G8B8A8_UNORM
              if (inSize >= 2 && outSize >= 4)
              {
            for (int ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4)
            {
              short t = reader.ReadInt16();

              uint t1 = pal8[t & 0xff];
              uint ta = ((flags & ScanlineFlags.SetAlpha) != 0 ? 0xff000000 : (uint)((t & 0xff00) << 16));

              writer.Write((int)(t1 | ta));
            }
            return true;
              }
              return false;

            case LegacyFormat.A4L4:
              switch (outFormat)
              {
            //#if DIRECTX11_1
            case DataFormat.B4G4R4A4_UNORM:
              // D3DFMT_A4L4 -> DXGI_FORMAT_B4G4R4A4_UNORM
              if (inSize >= 1 && outSize >= 2)
              {
                for (int ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 1))); ++icount, ocount += 2)
                {
                  byte t = reader.ReadByte();

                  ushort t1 = (ushort)(t & 0x0f);
                  ushort ta = (flags & ScanlineFlags.SetAlpha) != 0 ? (ushort)0xf000 : (ushort)((t & 0xf0) << 8);

                  writer.Write((ushort)(t1 | (t1 << 4) | (t1 << 8) | ta));
                }
                return true;
              }
              return false;
            //#endif

            case DataFormat.R8G8B8A8_UNORM:
              // D3DFMT_A4L4 -> DXGI_FORMAT_R8G8B8A8_UNORM
              if (inSize >= 1 && outSize >= 4)
              {
                for (int ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 3))); ++icount, ocount += 4)
                {
                  byte t = reader.ReadByte();

                  uint t1 = (uint)(((t & 0x0f) << 4) | (t & 0x0f));
                  uint ta = ((flags & ScanlineFlags.SetAlpha) != 0 ? 0xff000000 : (uint)(((t & 0xf0) << 24) | ((t & 0xf0) << 20)));

                  writer.Write((uint)(t1 | (t1 << 8) | (t1 << 16) | ta));
                }
                return true;
              }
              return false;
              }
              break;

            //#if !DIRECTX11_1
            case LegacyFormat.B4G4R4A4:
              if (outFormat != DataFormat.R8G8B8A8_UNORM)
            return false;

              // D3DFMT_A4R4G4B4 -> DXGI_FORMAT_R8G8B8A8_UNORM
              if (inSize >= 2 && outSize >= 4)
              {
            for (int ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4)
            {
              ushort t = reader.ReadUInt16();

              uint t1 = (uint)(((t & 0x0f00) >> 4) | ((t & 0x0f00) >> 8));
              uint t2 = (uint)(((t & 0x00f0) << 8) | ((t & 0x00f0) << 4));
              uint t3 = (uint)(((t & 0x000f) << 20) | ((t & 0x000f) << 16));
              uint ta = ((flags & ScanlineFlags.SetAlpha) != 0 ? 0xff000000 : (uint)(((t & 0xf000) << 16) | ((t & 0xf000) << 12)));

              writer.Write((uint)(t1 | t2 | t3 | ta));
            }
            return true;
              }
              return false;
            //#endif

            case LegacyFormat.L8:
              if (outFormat != DataFormat.R8G8B8A8_UNORM)
            return false;

              // D3DFMT_L8 -> DXGI_FORMAT_R8G8B8A8_UNORM
              if (inSize >= 1 && outSize >= 4)
              {
            for (int ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 3))); ++icount, ocount += 4)
            {
              uint t1 = reader.ReadByte();
              uint t2 = (t1 << 8);
              uint t3 = (t1 << 16);

              writer.Write((uint)(t1 | t2 | t3 | 0xff000000));
            }
            return true;
              }
              return false;

            case LegacyFormat.L16:
              if (outFormat != DataFormat.R16G16B16A16_UNORM)
            return false;

              // D3DFMT_L16 -> DXGI_FORMAT_R16G16B16A16_UNORM
              if (inSize >= 2 && outSize >= 8)
              {
            for (int ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 7))); icount += 2, ocount += 8)
            {
              ushort t = reader.ReadUInt16();

              ulong t1 = t;
              ulong t2 = (t1 << 16);
              ulong t3 = (t1 << 32);

              writer.Write((ulong)(t1 | t2 | t3 | 0xffff000000000000));
            }
            return true;
              }
              return false;

            case LegacyFormat.A8L8:
              if (outFormat != DataFormat.R8G8B8A8_UNORM)
            return false;

              // D3DFMT_A8L8 -> DXGI_FORMAT_R8G8B8A8_UNORM
              if (inSize >= 2 && outSize >= 4)
              {
            for (int ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4)
            {
              ushort t = reader.ReadUInt16();

              uint t1 = (uint)(t & 0xff);
              uint t2 = (t1 << 8);
              uint t3 = (t1 << 16);
              uint ta = (flags & ScanlineFlags.SetAlpha) != 0 ? 0xff000000 : (uint)((t & 0xff00) << 16);

              writer.Write((int)(t1 | t2 | t3 | ta));
            }
            return true;
              }
              return false;
              }

              return false;
        }