コード例 #1
0
        internal static void WriteUncompressed(byte[] source, byte[] destination, int destStart, DDS_Header.DDS_PIXELFORMAT dest_ddspf, ImageFormats.ImageEngineFormatDetails sourceFormatDetails, ImageFormats.ImageEngineFormatDetails 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 == ImageEngineFormat.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 (ImageEngine.EnableThreading)
            {
                Parallel.For(0, source.Length / sourceIncrement, new ParallelOptions {
                    MaxDegreeOfParallelism = ImageEngine.NumThreads
                }, (ind, loopState) =>
                {
                    if (ImageEngine.IsCancellationRequested)
                    {
                        loopState.Stop();
                    }

                    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)
                {
                    if (ImageEngine.IsCancellationRequested)
                    {
                        break;
                    }

                    WriteUncompressedPixel(source, i, sourceInds, sourceFormatDetails, masks, destination, destStart, destInds, destFormatDetails, oneChannel, twoChannel, requiresSignedAdjust);
                }
            }
        }
コード例 #2
0
 static void WriteUncompressedMipMap(byte[] destination, int mipOffset, MipMap mipmap, ImageFormats.ImageEngineFormatDetails destFormatDetails, DDS_Header.DDS_PIXELFORMAT ddspf)
 {
     DDS_Encoders.WriteUncompressed(mipmap.Pixels, destination, mipOffset, ddspf, mipmap.LoadedFormatDetails, destFormatDetails);
 }
コード例 #3
0
        internal static void ReadUncompressed(byte[] source, int sourceStart, byte[] destination, int pixelCount, DDS_Header.DDS_PIXELFORMAT ddspf, ImageFormats.ImageEngineFormatDetails 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
        private static MipMap ReadUncompressedMipMap(MemoryStream stream, int mipOffset, int mipWidth, int mipHeight, DDS_Header.DDS_PIXELFORMAT ddspf, ImageFormats.ImageEngineFormatDetails 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, formatDetails));
        }