Пример #1
0
        internal static void WriteUncompressed(byte[] source, byte[] destination, int destStart, DDS_Header.DDS_PIXELFORMAT dest_ddspf, DDSFormatDetails sourceFormatDetails, DDSFormatDetails destFormatDetails)
        {
            int  byteCount            = dest_ddspf.dwRGBBitCount / 8;
            bool requiresSignedAdjust = (dest_ddspf.dwFlags & DDS_Header.DDS_PFdwFlags.DDPF_SIGNED) == DDS_Header.DDS_PFdwFlags.DDPF_SIGNED;
            bool oneChannel           = (dest_ddspf.dwFlags & DDS_Header.DDS_PFdwFlags.DDPF_LUMINANCE) == DDS_Header.DDS_PFdwFlags.DDPF_LUMINANCE;
            bool twoChannel           = oneChannel && (dest_ddspf.dwFlags & DDS_Header.DDS_PFdwFlags.DDPF_ALPHAPIXELS) == DDS_Header.DDS_PFdwFlags.DDPF_ALPHAPIXELS;

            uint AMask = dest_ddspf.dwABitMask;
            uint RMask = dest_ddspf.dwRBitMask;
            uint GMask = dest_ddspf.dwGBitMask;
            uint BMask = dest_ddspf.dwBBitMask;

            ///// Figure out channel existance and ordering.
            // Setup array that indicates channel offset from pixel start.
            // e.g. Alpha is usually first, and is given offset 0.
            // NOTE: Ordering array is in ARGB order, and the stored indices change depending on detected channel order.
            // A negative index indicates channel doesn't exist in data and sets channel to 0xFF.

            if (destFormatDetails.Format == DDSFormat.DDS_ARGB_32F)
            {
                AMask = 4;
                BMask = 3;
                GMask = 2;
                RMask = 1;
            }

            List <uint> maskOrder = new List <uint>(4)
            {
                AMask, RMask, GMask, BMask
            };

            maskOrder.Sort();
            maskOrder.RemoveAll(t => t == 0);  // Required, otherwise indicies get all messed up when there's only two channels, but it's not indicated as such.

            // Determine channel ordering
            int destAIndex = AMask == 0 ? -1 : maskOrder.IndexOf(AMask) * destFormatDetails.ComponentSize;
            int destRIndex = RMask == 0 ? -1 : maskOrder.IndexOf(RMask) * destFormatDetails.ComponentSize;
            int destGIndex = GMask == 0 ? -1 : maskOrder.IndexOf(GMask) * destFormatDetails.ComponentSize;
            int destBIndex = BMask == 0 ? -1 : maskOrder.IndexOf(BMask) * destFormatDetails.ComponentSize;

            int sourceAInd = 3 * sourceFormatDetails.ComponentSize;
            int sourceRInd = 2 * sourceFormatDetails.ComponentSize;
            int sourceGInd = 1 * sourceFormatDetails.ComponentSize;
            int sourceBInd = 0;


            var sourceInds = new int[] { sourceBInd, sourceGInd, sourceRInd, sourceAInd };
            var destInds   = new int[] { destBIndex, destGIndex, destRIndex, destAIndex };
            var masks      = new uint[] { BMask, GMask, RMask, AMask };

            int sourceIncrement = 4 * sourceFormatDetails.ComponentSize;

            if (EnableThreading)
            {
                Parallel.For(0, source.Length / sourceIncrement, new ParallelOptions {
                    MaxDegreeOfParallelism = ThreadCount
                }, (ind, loopState) =>
                {
                    WriteUncompressedPixel(source, ind * sourceIncrement, sourceInds, sourceFormatDetails, masks, destination, destStart + ind * byteCount, destInds, destFormatDetails, oneChannel, twoChannel, requiresSignedAdjust);
                });
            }
            else
            {
                for (int i = 0; i < source.Length; i += 4 * sourceFormatDetails.ComponentSize, destStart += byteCount)
                {
                    WriteUncompressedPixel(source, i, sourceInds, sourceFormatDetails, masks, destination, destStart, destInds, destFormatDetails, oneChannel, twoChannel, requiresSignedAdjust);
                }
            }
        }
Пример #2
0
        private static MipMap ReadUncompressedMipMap(MemoryStream stream, int mipOffset, int mipWidth, int mipHeight, DDS_Header.DDS_PIXELFORMAT ddspf, DDSFormatDetails formatDetails)
        {
            byte[] data   = stream.GetBuffer();
            byte[] mipmap = new byte[mipHeight * mipWidth * 4 * formatDetails.ComponentSize];

            // Smaller sizes breaks things, so just exclude them
            if (mipHeight >= 4 && mipWidth >= 4)
            {
                DDS_Decoders.ReadUncompressed(data, mipOffset, mipmap, mipWidth * mipHeight, ddspf, formatDetails);
            }

            return(new MipMap(mipmap, mipWidth, mipHeight));
        }
Пример #3
0
        internal static void ReadUncompressed(byte[] source, int sourceStart, byte[] destination, int pixelCount, DDS_Header.DDS_PIXELFORMAT ddspf, DDSFormatDetails formatDetails)
        {
            bool requiresSignedAdjustment = ((ddspf.dwFlags & DDS_Header.DDS_PFdwFlags.DDPF_SIGNED) == DDS_Header.DDS_PFdwFlags.DDPF_SIGNED);
            int  sourceIncrement          = ddspf.dwRGBBitCount / 8; // /8 for bits to bytes conversion
            bool oneChannel = (ddspf.dwFlags & DDS_Header.DDS_PFdwFlags.DDPF_LUMINANCE) == DDS_Header.DDS_PFdwFlags.DDPF_LUMINANCE;
            bool twoChannel = (ddspf.dwFlags & DDS_Header.DDS_PFdwFlags.DDPF_ALPHAPIXELS) == DDS_Header.DDS_PFdwFlags.DDPF_ALPHAPIXELS && oneChannel;

            uint AMask = ddspf.dwABitMask;
            uint RMask = ddspf.dwRBitMask;
            uint GMask = ddspf.dwGBitMask;
            uint BMask = ddspf.dwBBitMask;


            ///// Figure out channel existance and ordering.
            // Setup array that indicates channel offset from pixel start.
            // e.g. Alpha is usually first, and is given offset 0.
            // NOTE: Ordering array is in ARGB order, and the stored indices change depending on detected channel order.
            // A negative index indicates channel doesn't exist in data and sets channel to 0xFF.
            List <uint> maskOrder = new List <uint>(4)
            {
                AMask, RMask, GMask, BMask
            };

            maskOrder.Sort();
            maskOrder.RemoveAll(t => t == 0);  // Required, otherwise indicies get all messed up when there's only two channels, but it's not indicated as such.

            // TODO: Cubemaps and hardcoded format readers for performance
            int AIndex = 0;
            int RIndex = 0;
            int GIndex = 0;
            int BIndex = 0;

            if (twoChannel)  // Note: V8U8 does not come under this one.
            {
                // Intensity is first byte, then the alpha. Set all RGB to intensity for grayscale.
                // Second mask is always RMask as determined by the DDS Spec.
                AIndex = AMask > RMask ? 1 : 0;
                RIndex = AMask > RMask ? 0 : 1;
                GIndex = AMask > RMask ? 0 : 1;
                BIndex = AMask > RMask ? 0 : 1;
            }
            else if (oneChannel)
            {
                // Decide whether it's alpha or not.
                AIndex = AMask == 0 ? -1 : 0;
                RIndex = AMask == 0 ? 0 : -1;
                GIndex = AMask == 0 ? 0 : -1;
                BIndex = AMask == 0 ? 0 : -1;
            }
            else
            {
                // Set default ordering
                AIndex = AMask == 0 ? -1 : maskOrder.IndexOf(AMask) * formatDetails.ComponentSize;
                RIndex = RMask == 0 ? -1 : maskOrder.IndexOf(RMask) * formatDetails.ComponentSize;
                GIndex = GMask == 0 ? -1 : maskOrder.IndexOf(GMask) * formatDetails.ComponentSize;
                BIndex = BMask == 0 ? -1 : maskOrder.IndexOf(BMask) * formatDetails.ComponentSize;
            }

            // Determine order of things
            int destAInd = 3 * formatDetails.ComponentSize;
            int destRInd = 2 * formatDetails.ComponentSize;
            int destGInd = 1 * formatDetails.ComponentSize;
            int destBInd = 0;

            switch (formatDetails.ComponentSize)
            {
            case 1:
                // Check masks fit properly
                if (maskOrder.Count != sourceIncrement)
                {
                    // Determine mask size
                    var lengths = new int[4];
                    lengths[0] = CountSetBits(BMask);
                    lengths[1] = CountSetBits(GMask);
                    lengths[2] = CountSetBits(RMask);
                    lengths[3] = CountSetBits(AMask);

                    ReadBytesLegacy(source, sourceStart, sourceIncrement, lengths, destination, new int[] { destBInd, destGInd, destRInd, destAInd });
                }
                else
                {
                    ReadBytes(source, sourceStart, sourceIncrement, new int[] { BIndex, GIndex, RIndex, AIndex }, destination, new int[] { destBInd, destGInd, destRInd, destAInd });
                }
                break;

            case 2:
                ReadUShorts(source, sourceStart, sourceIncrement, new int[] { BIndex, GIndex, RIndex, AIndex }, destination, new int[] { destBInd, destGInd, destRInd, destAInd });
                break;

            case 4:
                ReadFloats(source, sourceStart, sourceIncrement, new int[] { BIndex, GIndex, RIndex, AIndex }, destination, new int[] { destBInd, destGInd, destRInd, destAInd });
                break;
            }

            if (requiresSignedAdjustment)
            {
                for (int i = 0; i < destination.Length; i += 4)
                {
                    //destination[i] -= 128;  // Don't adjust blue
                    destination[i + 1] -= 128;
                    destination[i + 2] -= 128;

                    // Alpha not adjusted
                }
            }
        }
Пример #4
0
 static void WriteUncompressedMipMap(byte[] destination, int mipOffset, MipMap mipmap, DDSFormatDetails loadedFormatDetails, DDSFormatDetails destFormatDetails, DDS_Header.DDS_PIXELFORMAT ddspf)
 {
     DDS_Encoders.WriteUncompressed(mipmap.Pixels, destination, mipOffset, ddspf, loadedFormatDetails, destFormatDetails);
 }
Пример #5
0
        /// <summary>
        /// Determines DDS Surface Format given the header.
        /// </summary>
        /// <param name="ddspf">DDS PixelFormat structure.</param>
        /// <returns>Friendly format.</returns>
        public static DDSFormat DetermineDDSSurfaceFormat(DDS_Header.DDS_PIXELFORMAT ddspf)
        {
            DDSFormat format = ParseFourCC(ddspf.dwFourCC);

            if (format == DDSFormat.Unknown)
            {
                // Due to some previous settings, need to check these first.
                if (ddspf.dwABitMask <= 4 && ddspf.dwABitMask != 0 &&
                    ddspf.dwBBitMask <= 4 && ddspf.dwBBitMask != 0 &&
                    ddspf.dwGBitMask <= 4 && ddspf.dwGBitMask != 0 &&
                    ddspf.dwRBitMask <= 4 && ddspf.dwRBitMask != 0)
                {
                    format = DDSFormat.DDS_CUSTOM;
                }


                // KFreon: Apparently all these flags mean it's a V8U8 image...
                else if (ddspf.dwRGBBitCount == 16 &&
                         ddspf.dwRBitMask == 0x00FF &&
                         ddspf.dwGBitMask == 0xFF00 &&
                         ddspf.dwBBitMask == 0x00 &&
                         ddspf.dwABitMask == 0x00 &&
                         (ddspf.dwFlags & DDS_PFdwFlags.DDPF_SIGNED) == DDS_PFdwFlags.DDPF_SIGNED)
                {
                    format = DDSFormat.DDS_V8U8;
                }

                // KFreon: Test for L8/G8
                else if (ddspf.dwABitMask == 0 &&
                         ddspf.dwBBitMask == 0 &&
                         ddspf.dwGBitMask == 0 &&
                         ddspf.dwRBitMask == 0xFF &&
                         ddspf.dwFlags == DDS_PFdwFlags.DDPF_LUMINANCE &&
                         ddspf.dwRGBBitCount == 8)
                {
                    format = DDSFormat.DDS_G8_L8;
                }

                // KFreon: A8L8. This can probably be something else as well, but it seems to work for now
                else if (ddspf.dwRGBBitCount == 16 &&
                         ddspf.dwFlags == (DDS_PFdwFlags.DDPF_ALPHAPIXELS | DDS_PFdwFlags.DDPF_LUMINANCE))
                {
                    format = DDSFormat.DDS_A8L8;
                }

                // KFreon: G_R only.
                else if (((ddspf.dwFlags & DDS_PFdwFlags.DDPF_RGB) == DDS_PFdwFlags.DDPF_RGB && !((ddspf.dwFlags & DDS_PFdwFlags.DDPF_ALPHAPIXELS) == DDS_PFdwFlags.DDPF_ALPHAPIXELS)) &&
                         ddspf.dwABitMask == 0 &&
                         ddspf.dwBBitMask == 0 &&
                         ddspf.dwGBitMask != 0 &&
                         ddspf.dwRBitMask != 0)
                {
                    format = DDSFormat.DDS_G16_R16;
                }

                // KFreon: RGB. RGB channels have something in them, but alpha doesn't.
                else if (((ddspf.dwFlags & DDS_PFdwFlags.DDPF_RGB) == DDS_PFdwFlags.DDPF_RGB && !((ddspf.dwFlags & DDS_PFdwFlags.DDPF_ALPHAPIXELS) == DDS_PFdwFlags.DDPF_ALPHAPIXELS)) &&
                         ddspf.dwABitMask == 0 &&
                         ddspf.dwBBitMask != 0 &&
                         ddspf.dwGBitMask != 0 &&
                         ddspf.dwRBitMask != 0)
                {
                    // TODO more formats?
                    if (ddspf.dwBBitMask == 31)
                    {
                        format = DDSFormat.DDS_R5G6B5;
                    }
                    else
                    {
                        format = DDSFormat.DDS_RGB_8;
                    }
                }

                // KFreon: RGB and A channels are present.
                else if (((ddspf.dwFlags & (DDS_PFdwFlags.DDPF_RGB | DDS_PFdwFlags.DDPF_ALPHAPIXELS)) == (DDS_PFdwFlags.DDPF_RGB | DDS_PFdwFlags.DDPF_ALPHAPIXELS)) ||
                         ddspf.dwABitMask != 0 &&
                         ddspf.dwBBitMask != 0 &&
                         ddspf.dwGBitMask != 0 &&
                         ddspf.dwRBitMask != 0)
                {
                    // TODO: Some more formats here?
                    format = DDSFormat.DDS_ARGB_8;
                }

                // KFreon: If nothing else fits, but there's data in one of the bitmasks, assume it can be read.
                else if (ddspf.dwABitMask != 0 || ddspf.dwRBitMask != 0 || ddspf.dwGBitMask != 0 || ddspf.dwBBitMask != 0)
                {
                    format = DDSFormat.DDS_CUSTOM;
                }
                else
                {
                    throw new FormatException("DDS Format is unknown.");
                }
            }

            return(format);
        }