A class to convert/copy pixels of the same or different formats
Example #1
0
        private void Unpack(ref ColorEx dst, int x, int y, int z, PixelFormat format, BufferBase src, PixelBox srcbox,
                            int elemsize)
        {
            var data = src + (elemsize * ((x) + (y) * srcbox.RowPitch + (z) * srcbox.SlicePitch));

            dst = PixelConverter.UnpackColor(format, data);
        }
        public static int GetMemorySize(int width, int height, int depth, PixelFormat format)
        {
            if (Compressed(format))
            {
                switch (format)
                {
                // DXT formats work by dividing the image into 4x4 blocks, then encoding each
                // 4x4 block with a certain number of bytes. DXT can only be used on 2D images.
                case PixelFormat.DXT1:
                    Debug.Assert(depth == 1);
                    return(((width + 3) / 4) * ((height + 3) / 4) * 8);

                case PixelFormat.DXT2:
                case PixelFormat.DXT3:
                case PixelFormat.DXT4:
                case PixelFormat.DXT5:
                    Debug.Assert(depth == 1);
                    return(((width + 3) / 4) * ((height + 3) / 4) * 16);

                default:
                    throw new Exception("Invalid compressed pixel format, in PixelBox.GetMemorySize");
                }
            }
            else
            {
                return(width * height * depth * PixelConverter.GetNumElemBytes(format));
            }
        }
Example #3
0
        private void _unpackDXTColor(PixelFormat pf, DXTColorBlock block, ColorEx[] pCol)
        {
            // Note - we assume all values have already been endian swapped

            // Colour lookup table
            var derivedColours = new ColorEx[4];

            using (var src = BufferBase.Wrap(block.colour_0, 1))
            {
                derivedColours[0] = PixelConverter.UnpackColor(PixelFormat.R5G6B5, src);
            }

            using (var src = BufferBase.Wrap(block.colour_1, 1))
            {
                derivedColours[1] = PixelConverter.UnpackColor(PixelFormat.R5G6B5, src);
            }

            if (pf == PixelFormat.DXT1 && block.colour_0 <= block.colour_1)
            {
                // 1-bit alpha

                // one intermediate colour, half way between the other two
                derivedColours[2] = (derivedColours[0] + derivedColours[1]) / 2;
                // transparent colour
                derivedColours[3] = new ColorEx(0, 0, 0, 0);
            }
            else
            {
                // first interpolated colour, 1/3 of the way along
                derivedColours[2] = (derivedColours[0] * 2 + derivedColours[1]) / 3;
                // second interpolated colour, 2/3 of the way along
                derivedColours[3] = (derivedColours[0] + derivedColours[1] * 2) / 3;
            }

            // Process 4x4 block of texels
            for (var row = 0; row < 4; ++row)
            {
                for (var x = 0; x < 4; ++x)
                {
                    // LSB come first
                    var colIdx = (byte)block.indexRow[row] >> (x * 2) & 0x3;
                    if (pf == PixelFormat.DXT1)
                    {
                        // Overwrite entire colour
                        pCol[(row * 4) + x] = derivedColours[colIdx];
                    }
                    else
                    {
                        // alpha has already been read (alpha precedes colour)
                        var col = pCol[(row * 4) + x];
                        col.r = derivedColours[colIdx].r;
                        col.g = derivedColours[colIdx].g;
                        col.b = derivedColours[colIdx].b;
                    }
                }
            }
        }
Example #4
0
        public static bool IsAccessible(PixelFormat format)
        {
            if (format == PixelFormat.Unknown)
            {
                return(false);
            }
            var flags = PixelConverter.GetDescriptionFor(format).flags;

            return(!((flags & PixelFormatFlags.Compressed) > 0 || (flags & PixelFormatFlags.Depth) > 0));
        }
Example #5
0
        public static uint[] GetBitMasks(PixelFormat format)
        {
            var rgba = new uint[4];
            var des  = PixelConverter.GetDescriptionFor(format);

            rgba[0] = des.rmask;
            rgba[1] = des.gmask;
            rgba[2] = des.bmask;
            rgba[3] = des.amask;
            return(rgba);
        }
Example #6
0
        public static int[] GetBitDepths(PixelFormat format)
        {
            var rgba = new int[4];
            var des  = PixelConverter.GetDescriptionFor(format);

            rgba[0] = des.rbits;
            rgba[1] = des.gbits;
            rgba[2] = des.bbits;
            rgba[3] = des.abits;
            return(rgba);
        }
Example #7
0
        public static byte[] GetBitShifts(PixelFormat format)
        {
            var rgba = new byte[4];
            var des  = PixelConverter.GetDescriptionFor(format);

            rgba[0] = des.rshift;
            rgba[1] = des.gshift;
            rgba[2] = des.bshift;
            rgba[3] = des.ashift;

            return(rgba);
        }
        ///*************************************************************************
        ///   Pixel packing/unpacking utilities
        ///*************************************************************************


        //           ///<summary>
        //           ///    Pack a color value to memory
        //           ///</summary>
        //           ///<param name="color">The color</param>
        //           ///<param name="format">Pixel format in which to write the color</param>
        //           ///<param name="dest">Destination memory location</param>
        //          public static void PackColor(System.Drawing.Color color, PixelFormat format,  IntPtr dest) {
        //              PackColor(color.r, color.g, color.b, color.a, format, dest);
        //          }

        ///<summary>
        ///    Pack a color value to memory
        ///</summary>
        ///<param name="r,g,b,a">The four color components, range 0x00 to 0xFF</param>
        ///<param name="format">Pixelformat in which to write the color</param>
        ///<param name="dest">Destination memory location</param>
        unsafe public void PackColor(uint r, uint g, uint b, uint a, PixelFormat format, byte *dest)
        {
            PixelFormatDescription des = PixelConverter.GetDescriptionFor(format);

            if ((des.flags & PixelFormatFlags.NativeEndian) != 0)
            {
                // Shortcut for integer formats packing
                uint value = (((Bitwise.FixedToFixed(r, 8, des.rbits) << des.rshift) & des.rmask) |
                              ((Bitwise.FixedToFixed(g, 8, des.gbits) << des.gshift) & des.gmask) |
                              ((Bitwise.FixedToFixed(b, 8, des.bbits) << des.bshift) & des.bmask) |
                              ((Bitwise.FixedToFixed(a, 8, des.abits) << des.ashift) & des.amask));
                // And write to memory
                Bitwise.IntWrite(dest, des.elemBytes, value);
            }
            else
            {
                // Convert to float
                PackColor((float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, (float)a / 255.0f, format, dest);
            }
        }
        //           /** Unpack a color value from memory
        //              @param color	The color is returned here
        //              @param pf		Pixelformat in which to read the color
        //              @param src		Source memory location
        //           */
        //          protected static void UnpackColor(ref System.Drawing.Color color, PixelFormat pf,  IntPtr src) {
        //              UnpackColor(color.r, color.g, color.b, color.a, pf, src);
        //          }

        /** Unpack a color value from memory
         * @param r,g,b,a	The color is returned here (as byte)
         * @param pf		Pixelformat in which to read the color
         * @param src		Source memory location
         * @remarks     This function returns the color components in 8 bit precision,
         *    this will lose precision when coming from A2R10G10B10 or floating
         *    point formats.
         */
        unsafe public static void UnpackColor(ref byte r, ref byte g, ref byte b, ref byte a,
                                              PixelFormat pf, byte *src)
        {
            PixelFormatDescription des = PixelConverter.GetDescriptionFor(pf);

            if ((des.flags & PixelFormatFlags.NativeEndian) != 0)
            {
                // Shortcut for integer formats unpacking
                uint value = Bitwise.IntRead(src, des.elemBytes);
                if ((des.flags & PixelFormatFlags.Luminance) != 0)
                {
                    // Luminance format -- only rbits used
                    r = g = b = (byte)Bitwise.FixedToFixed((value & des.rmask) >> des.rshift, des.rbits, 8);
                }
                else
                {
                    r = (byte)Bitwise.FixedToFixed((value & des.rmask) >> des.rshift, des.rbits, 8);
                    g = (byte)Bitwise.FixedToFixed((value & des.gmask) >> des.gshift, des.gbits, 8);
                    b = (byte)Bitwise.FixedToFixed((value & des.bmask) >> des.bshift, des.bbits, 8);
                }
                if ((des.flags & PixelFormatFlags.HasAlpha) != 0)
                {
                    a = (byte)Bitwise.FixedToFixed((value & des.amask) >> des.ashift, des.abits, 8);
                }
                else
                {
                    a = 255; // No alpha, default a component to full
                }
            }
            else
            {
                // Do the operation with the more generic floating point
                float rr, gg, bb, aa;
                UnpackColor(out rr, out gg, out bb, out aa, pf, src);
                r = Bitwise.FloatToByteFixed(rr);
                g = Bitwise.FloatToByteFixed(gg);
                b = Bitwise.FloatToByteFixed(bb);
                a = Bitwise.FloatToByteFixed(aa);
            }
        }
        ///<summary>
        ///    Pack a color value to memory
        ///</summary>
        ///<param name="r,g,b,a">
        ///    The four color components, range 0.0f to 1.0f
        ///    (an exception to this case exists for floating point pixel
        ///    formats, which don't clamp to 0.0f..1.0f)
        ///</param>
        ///<param name="format">Pixelformat in which to write the color</param>
        ///<param name="dest">Destination memory location</param>
        unsafe public static void PackColor(float r, float g, float b, float a, PixelFormat format, byte *dest)
        {
            // Catch-it-all here
            PixelFormatDescription des = PixelConverter.GetDescriptionFor(format);

            if ((des.flags & PixelFormatFlags.NativeEndian) != 0)
            {
                // Do the packing
                uint value = ((Bitwise.FloatToFixed(r, des.rbits) << des.rshift) & des.rmask) |
                             ((Bitwise.FloatToFixed(g, des.gbits) << des.gshift) & des.gmask) |
                             ((Bitwise.FloatToFixed(b, des.bbits) << des.bshift) & des.bmask) |
                             ((Bitwise.FloatToFixed(a, des.abits) << des.ashift) & des.amask);
                // And write to memory
                Bitwise.IntWrite(dest, des.elemBytes, value);
            }
            else
            {
                switch (format)
                {
                case PixelFormat.FLOAT32_R:
                    ((float *)dest)[0] = r;
                    break;

                case PixelFormat.FLOAT32_RGB:
                    ((float *)dest)[0] = r;
                    ((float *)dest)[1] = g;
                    ((float *)dest)[2] = b;
                    break;

                case PixelFormat.FLOAT32_RGBA:
                    ((float *)dest)[0] = r;
                    ((float *)dest)[1] = g;
                    ((float *)dest)[2] = b;
                    ((float *)dest)[3] = a;
                    break;

                case PixelFormat.FLOAT16_R:
                    ((ushort *)dest)[0] = Bitwise.FloatToHalf(r);
                    break;

                case PixelFormat.FLOAT16_RGB:
                    ((ushort *)dest)[0] = Bitwise.FloatToHalf(r);
                    ((ushort *)dest)[1] = Bitwise.FloatToHalf(g);
                    ((ushort *)dest)[2] = Bitwise.FloatToHalf(b);
                    break;

                case PixelFormat.FLOAT16_RGBA:
                    ((ushort *)dest)[0] = Bitwise.FloatToHalf(r);
                    ((ushort *)dest)[1] = Bitwise.FloatToHalf(g);
                    ((ushort *)dest)[2] = Bitwise.FloatToHalf(b);
                    ((ushort *)dest)[3] = Bitwise.FloatToHalf(a);
                    break;

                //                  case PixelFormat.SHORT_RGBA:
                //                      ((ushort*)dest)[0] = Bitwise.FloatToFixed(r, 16);
                //                      ((ushort*)dest)[1] = Bitwise.FloatToFixed(g, 16);
                //                      ((ushort*)dest)[2] = Bitwise.FloatToFixed(b, 16);
                //                      ((ushort*)dest)[3] = Bitwise.FloatToFixed(a, 16);
                //                      break;
                //                  case PixelFormat.BYTE_LA:
                //                      ((byte*)dest)[0] = Bitwise.FloatToFixed(r, 8);
                //                      ((byte*)dest)[1] = Bitwise.FloatToFixed(a, 8);
                //                      break;
                default:
                    // Not yet supported
                    throw new Exception("Pack to " + format + " not implemented, in PixelUtil.PackColor");
                }
            }
        }
 public static string GetFormatName(PixelFormat format)
 {
     return(PixelConverter.GetDescriptionFor(format).name);
 }
 public static bool HasAlpha(PixelFormat format)
 {
     return((PixelConverter.GetDescriptionFor(format).flags & PixelFormatFlags.HasAlpha) > 0);
 }
 public static bool IsCompressed(PixelFormat format)
 {
     return((PixelConverter.GetDescriptionFor(format).flags & PixelFormatFlags.Compressed) > 0);
 }
 /// <summary>
 ///    Returns the size in bytes of an element of the given pixel format.
 /// </summary>
 /// <param name="format">Pixel format to test.</param>
 /// <returns>Size in bytes.</returns>
 public static int GetNumElemBytes(PixelFormat format)
 {
     return(PixelConverter.GetDescriptionFor(format).elemBytes);
 }
        unsafe public static void UnpackColor(out float r, out float g, out float b, out float a,
                                              PixelFormat pf, byte *src)
        {
            PixelFormatDescription des = PixelConverter.GetDescriptionFor(pf);

            if ((des.flags & PixelFormatFlags.NativeEndian) != 0)
            {
                // Shortcut for integer formats unpacking
                uint value = Bitwise.IntRead(src, des.elemBytes);
                if ((des.flags & PixelFormatFlags.Luminance) != 0)
                {
                    // Luminance format -- only rbits used
                    r = g = b = Bitwise.FixedToFloat(
                        (value & des.rmask) >> des.rshift, des.rbits);
                }
                else
                {
                    r = Bitwise.FixedToFloat((value & des.rmask) >> des.rshift, des.rbits);
                    g = Bitwise.FixedToFloat((value & des.gmask) >> des.gshift, des.gbits);
                    b = Bitwise.FixedToFloat((value & des.bmask) >> des.bshift, des.bbits);
                }
                if ((des.flags & PixelFormatFlags.HasAlpha) != 0)
                {
                    a = Bitwise.FixedToFloat((value & des.amask) >> des.ashift, des.abits);
                }
                else
                {
                    a = 1.0f; // No alpha, default a component to full
                }
            }
            else
            {
                switch (pf)
                {
                case PixelFormat.FLOAT32_R:
                    r = g = b = ((float *)src)[0];
                    a = 1.0f;
                    break;

                case PixelFormat.FLOAT32_RGB:
                    r = ((float *)src)[0];
                    g = ((float *)src)[1];
                    b = ((float *)src)[2];
                    a = 1.0f;
                    break;

                case PixelFormat.FLOAT32_RGBA:
                    r = ((float *)src)[0];
                    g = ((float *)src)[1];
                    b = ((float *)src)[2];
                    a = ((float *)src)[3];
                    break;

                case PixelFormat.FLOAT16_R:
                    r = g = b = Bitwise.HalfToFloat(((ushort *)src)[0]);
                    a = 1.0f;
                    break;

                case PixelFormat.FLOAT16_RGB:
                    r = Bitwise.HalfToFloat(((ushort *)src)[0]);
                    g = Bitwise.HalfToFloat(((ushort *)src)[1]);
                    b = Bitwise.HalfToFloat(((ushort *)src)[2]);
                    a = 1.0f;
                    break;

                case PixelFormat.FLOAT16_RGBA:
                    r = Bitwise.HalfToFloat(((ushort *)src)[0]);
                    g = Bitwise.HalfToFloat(((ushort *)src)[1]);
                    b = Bitwise.HalfToFloat(((ushort *)src)[2]);
                    a = Bitwise.HalfToFloat(((ushort *)src)[3]);
                    break;

                //                  case PixelFormat.SHORT_RGBA:
                //                      r = Bitwise.FixedToFloat(((ushort*)src)[0], 16);
                //                      g = Bitwise.FixedToFloat(((ushort*)src)[1], 16);
                //                      b = Bitwise.FixedToFloat(((ushort*)src)[2], 16);
                //                      a = Bitwise.FixedToFloat(((ushort*)src)[3], 16);
                //                      break;
                //                  case PixelFormat.BYTE_LA:
                //                      r = g = b = Bitwise.FixedToFloat(((byte*)src)[0], 8);
                //                      a = Bitwise.FixedToFloat(((byte*)src)[1], 8);
                //                      break;
                default:
                    // Not yet supported
                    throw new Exception("Unpack from " + pf + " not implemented, in PixelUtil.UnpackColor");
                }
            }
        }
Example #16
0
        public override Codec.DecodeResult Decode(Stream input)
        {
            using (var br = new BinaryReader(input))
            {
                // Read 4 character code
                var fileType = br.ReadInt32();
                using (var wrap = BufferBase.Wrap(fileType, 2))
                {
                    _flipEndian(wrap, sizeof(uint), 1);
                }

                if (FOURCC('D', 'D', 'S', ' ') != fileType)
                {
                    throw new AxiomException("This is not a DDS file!");
                }

                // Read header in full
                var header = DDSHeader.Read(br);

                // Endian flip if required, all 32-bit values
                using (var wrap = BufferBase.Wrap(header, Memory.SizeOf(typeof(DDSHeader))))
                {
                    _flipEndian(wrap, 4, Memory.SizeOf(typeof(DDSHeader)) / 4);
                }

                // Check some sizes
                if (header.size != DDS_HEADER_SIZE)
                {
                    throw new AxiomException("DDS header size mismatch!");
                }

                if (header.pixelFormat.size != DDS_PIXELFORMAT_SIZE)
                {
                    throw new AxiomException("DDS header size mismatch!");
                }

                var imgData = new ImageData();

                imgData.depth  = 1; // (deal with volume later)
                imgData.width  = header.width;
                imgData.height = header.height;
                var numFaces = 1; // assume one face until we know otherwise

                if ((header.caps.caps1 & DDSCAPS_MIPMAP) != 0)
                {
                    imgData.numMipMaps = header.mipMapCount - 1;
                }
                else
                {
                    imgData.numMipMaps = 0;
                }

                imgData.flags = 0;

                var decompressDXT = false;
                // Figure out basic image type
                if ((header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0)
                {
                    imgData.flags |= ImageFlags.CubeMap;
                    numFaces       = 6;
                }
                else if ((header.caps.caps2 & DDSCAPS2_VOLUME) != 0)
                {
                    imgData.flags |= ImageFlags.Volume;
                    imgData.depth  = header.depth;
                }
                // Pixel format
                var sourceFormat = PixelFormat.Unknown;

                if ((header.pixelFormat.flags & DDPF_FOURCC) != 0)
                {
                    sourceFormat = _convertFourCCFormat(header.pixelFormat.fourCC);
                }
                else
                {
                    sourceFormat = _convertPixelFormat(header.pixelFormat.rgbBits, header.pixelFormat.redMask,
                                                       header.pixelFormat.greenMask, header.pixelFormat.blueMask,
                                                       (header.pixelFormat.flags & DDPF_ALPHAPIXELS) != 0
                                                            ? header.pixelFormat.alphaMask
                                                            : 0);
                }

                if (PixelUtil.IsCompressed(sourceFormat))
                {
                    if (!Root.Instance.RenderSystem.Capabilities.HasCapability(Capabilities.TextureCompressionDXT))
                    {
                        // We'll need to decompress
                        decompressDXT = true;
                        // Convert format
                        switch (sourceFormat)
                        {
                        case PixelFormat.DXT1:
                            // source can be either 565 or 5551 depending on whether alpha present
                            // unfortunately you have to read a block to figure out which
                            // Note that we upgrade to 32-bit pixel formats here, even
                            // though the source is 16-bit; this is because the interpolated
                            // values will benefit from the 32-bit results, and the source
                            // from which the 16-bit samples are calculated may have been
                            // 32-bit so can benefit from this.
                            var block = DXTColorBlock.Read(br);
                            using (var wrap = BufferBase.Wrap(block.colour_0, sizeof(ushort)))
                            {
                                _flipEndian(wrap, sizeof(ushort), 1);
                            }

                            using (var wrap = BufferBase.Wrap(block.colour_1, sizeof(ushort)))
                            {
                                _flipEndian(wrap, sizeof(ushort), 1);
                            }
                            // skip back since we'll need to read this again
                            br.BaseStream.Seek(0 - (long)Memory.SizeOf(typeof(DXTColorBlock)), SeekOrigin.Current);
                            // colour_0 <= colour_1 means transparency in DXT1
                            if (block.colour_0 <= block.colour_1)
                            {
                                imgData.format = PixelFormat.BYTE_RGBA;
                            }
                            else
                            {
                                imgData.format = PixelFormat.BYTE_RGB;
                            }
                            break;

                        case PixelFormat.DXT2:
                        case PixelFormat.DXT3:
                        case PixelFormat.DXT4:
                        case PixelFormat.DXT5:
                            // full alpha present, formats vary only in encoding
                            imgData.format = PixelFormat.BYTE_RGBA;
                            break;

                        default:
                            // all other cases need no special format handling
                            break;
                        }
                    }
                    else
                    {
                        // Use original format
                        imgData.format = sourceFormat;
                        // Keep DXT data compressed
                        imgData.flags |= ImageFlags.Compressed;
                    }
                }
                else // not compressed
                {
                    // Don't test against DDPF_RGB since greyscale DDS doesn't set this
                    // just derive any other kind of format
                    imgData.format = sourceFormat;
                }

                // Calculate total size from number of mipmaps, faces and size
                imgData.size = Image.CalculateSize(imgData.numMipMaps, numFaces, imgData.width, imgData.height, imgData.depth, imgData.format);

                // Now deal with the data
                var dest       = new byte[imgData.size];
                var destBuffer = BufferBase.Wrap(dest);

                // all mips for a face, then each face
                for (var i = 0; i < numFaces; ++i)
                {
                    var width  = imgData.width;
                    var height = imgData.height;
                    var depth  = imgData.depth;

                    for (var mip = 0; mip <= imgData.numMipMaps; ++mip)
                    {
                        var dstPitch = width * PixelUtil.GetNumElemBytes(imgData.format);

                        if (PixelUtil.IsCompressed(sourceFormat))
                        {
                            // Compressed data
                            if (decompressDXT)
                            {
                                DXTColorBlock             col;
                                DXTInterpolatedAlphaBlock iAlpha;
                                DXTExplicitAlphaBlock     eAlpha;
                                // 4x4 block of decompressed colour
                                var tempColours     = new ColorEx[16];
                                var destBpp         = PixelUtil.GetNumElemBytes(imgData.format);
                                var sx              = Utility.Min(width, 4);
                                var sy              = Utility.Min(height, 4);
                                var destPitchMinus4 = dstPitch - destBpp * sx;
                                // slices are done individually
                                for (var z = 0; z < depth; ++z)
                                {
                                    // 4x4 blocks in x/y
                                    for (var y = 0; y < height; y += 4)
                                    {
                                        for (var x = 0; x < width; x += 4)
                                        {
                                            if (sourceFormat == PixelFormat.DXT2 || sourceFormat == PixelFormat.DXT3)
                                            {
                                                // explicit alpha
                                                eAlpha = DXTExplicitAlphaBlock.Read(br);
                                                using (var wrap = BufferBase.Wrap(eAlpha.alphaRow, eAlpha.alphaRow.Length * sizeof(ushort)))
                                                {
                                                    _flipEndian(wrap, sizeof(ushort), 4);
                                                }
                                                _unpackDXTAlpha(eAlpha, tempColours);
                                            }
                                            else if (sourceFormat == PixelFormat.DXT4 || sourceFormat == PixelFormat.DXT5)
                                            {
                                                // interpolated alpha
                                                iAlpha = DXTInterpolatedAlphaBlock.Read(br);
                                                using (var wrap = BufferBase.Wrap(iAlpha.alpha_0, 1))
                                                {
                                                    _flipEndian(wrap, sizeof(ushort), 1);
                                                }

                                                using (var wrap = BufferBase.Wrap(iAlpha.alpha_1, 1))
                                                {
                                                    _flipEndian(wrap, sizeof(ushort), 1);
                                                }
                                                _unpackDXTAlpha(iAlpha, tempColours);
                                            }
                                            // always read colour
                                            col = DXTColorBlock.Read(br);

                                            using (var wrap = BufferBase.Wrap(col.colour_0, sizeof(ushort)))
                                            {
                                                _flipEndian(wrap, sizeof(ushort), 1);
                                            }

                                            using (var wrap = BufferBase.Wrap(col.colour_1, sizeof(ushort)))
                                            {
                                                _flipEndian(wrap, sizeof(ushort), 1);
                                            }
                                            _unpackDXTColor(sourceFormat, col, tempColours);

                                            // write 4x4 block to uncompressed version
                                            for (var by = 0; by < sy; ++by)
                                            {
                                                for (var bx = 0; bx < sx; ++bx)
                                                {
                                                    PixelConverter.PackColor(tempColours[by * 4 + bx], imgData.format, destBuffer);
                                                    destBuffer += destBpp;
                                                }
                                                // advance to next row
                                                destBuffer += destPitchMinus4;
                                            }
                                            // next block. Our dest pointer is 4 lines down
                                            // from where it started
                                            if (x + 4 >= width)
                                            {
                                                // Jump back to the start of the line
                                                destBuffer += -destPitchMinus4;
                                            }
                                            else
                                            {
                                                // Jump back up 4 rows and 4 pixels to the
                                                // right to be at the next block to the right
                                                destBuffer += -(dstPitch * sy + destBpp * sx);
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                // load directly
                                // DDS format lies! sizeOrPitch is not always set for DXT!!
                                var dxtSize = PixelUtil.GetMemorySize(width, height, depth, imgData.format);
                                using (var src = BufferBase.Wrap(br.ReadBytes(dxtSize)))
                                {
                                    Memory.Copy(src, destBuffer, dxtSize);
                                }
                                destBuffer += dxtSize;
                            }
                        }
                        else
                        {
                            // Final data - trim incoming pitch
                            int srcPitch;
                            if ((header.flags & DDSD_PITCH) != 0)
                            {
                                srcPitch = header.sizeOrPitch / Utility.Max(1, mip * 2);
                            }
                            else
                            {
                                // assume same as final pitch
                                srcPitch = dstPitch;
                            }
                            Contract.Requires(dstPitch <= srcPitch);
                            var srcAdvance = (long)(srcPitch - dstPitch);

                            for (var z = 0; z < imgData.depth; ++z)
                            {
                                for (var y = 0; y < imgData.height; ++y)
                                {
                                    using (var src = BufferBase.Wrap(br.ReadBytes(dstPitch)))
                                    {
                                        Memory.Copy(src, destBuffer, dstPitch);
                                    }

                                    if (srcAdvance > 0)
                                    {
                                        br.BaseStream.Seek(srcAdvance, SeekOrigin.Current);
                                    }

                                    destBuffer += dstPitch;
                                }
                            }
                        }

                        // Next mip
                        if (width != 1)
                        {
                            width /= 2;
                        }

                        if (height != 1)
                        {
                            height /= 2;
                        }

                        if (depth != 1)
                        {
                            depth /= 2;
                        }
                    }
                }

                destBuffer.Dispose();
                return(new DecodeResult(new MemoryStream(dest), imgData));
            }
        }
Example #17
0
        /// <summary>
        /// </summary>
        /// <param name="src"> </param>
        /// <param name="dst"> </param>
        public void Scale(PixelBox src, PixelBox dst)
        {
            var srcelemsize = PixelUtil.GetNumElemBytes(src.Format);
            var dstelemsize = PixelUtil.GetNumElemBytes(dst.Format);

            var dstOffset = 0;

            // sx_48,sy_48,sz_48 represent current position in source
            // using 16/48-bit fixed precision, incremented by steps
            var stepx = ((UInt64)src.Width << 48) / (UInt64)dst.Width;
            var stepy = ((UInt64)src.Height << 48) / (UInt64)dst.Height;
            var stepz = ((UInt64)src.Depth << 48) / (UInt64)dst.Depth;
            // temp is 16/16 bit fixed precision, used to adjust a source
            // coordinate (x, y, or z) backwards by half a pixel so that the
            // integer bits represent the first sample (eg, sx1) and the
            // fractional bits are the blend weight of the second sample
            uint temp;
            // note: ((stepz>>1) - 1) is an extra half-step increment to adjust
            // for the center of the destination pixel, not the top-left corner
            var sz_48 = (stepz >> 1) - 1;

            for (var z = dst.Front; z < dst.Back; z++, sz_48 += stepz)
            {
                temp = (uint)(sz_48 >> 32);
                temp = (temp > 0x8000) ? temp - 0x8000 : 0;
                var sz1 = (int)(temp >> 16);
                var sz2 = System.Math.Min(sz1 + 1, src.Depth - 1);
                var szf = (temp & 0xFFFF) / 65536f;

                var sy_48 = (stepy >> 1) - 1;
                for (var y = dst.Top; y < dst.Bottom; y++, sy_48 += stepy)
                {
                    temp = (uint)(sy_48 >> 32);
                    temp = (temp > 0x8000) ? temp - 0x8000 : 0;
                    var sy1 = (int)(temp >> 16);                        // src x #1
                    var sy2 = System.Math.Min(sy1 + 1, src.Height - 1); // src x #2
                    var syf = (temp & 0xFFFF) / 65536f;                 // weight of #2

                    var sx_48 = (stepx >> 1) - 1;
                    for (var x = dst.Left; x < dst.Right; x++, sx_48 += stepx)
                    {
                        temp = (uint)(sy_48 >> 32);
                        temp = (temp > 0x8000) ? temp - 0x8000 : 0;
                        var     sx1 = (int)(temp >> 16);                       // src x #1
                        var     sx2 = System.Math.Min(sx1 + 1, src.Width - 1); // src x #2
                        var     sxf = (temp & 0xFFFF) / 65536f;                // weight of #2
                        ColorEx x1y1z1 = ColorEx.White, x2y1z1 = ColorEx.White, x1y2z1 = ColorEx.White, x2y2z1 = ColorEx.White;
                        ColorEx x1y1z2 = ColorEx.White, x2y1z2 = ColorEx.White, x1y2z2 = ColorEx.White, x2y2z2 = ColorEx.White;
                        Unpack(ref x1y1z1, sx1, sy1, sz1, src.Format, src.Data, src, srcelemsize);
                        Unpack(ref x2y1z1, sx2, sy1, sz1, src.Format, src.Data, src, srcelemsize);
                        Unpack(ref x1y2z1, sx1, sy2, sz1, src.Format, src.Data, src, srcelemsize);
                        Unpack(ref x2y2z1, sx2, sy2, sz1, src.Format, src.Data, src, srcelemsize);
                        Unpack(ref x1y1z2, sx1, sy1, sz2, src.Format, src.Data, src, srcelemsize);
                        Unpack(ref x2y1z2, sx2, sy1, sz2, src.Format, src.Data, src, srcelemsize);
                        Unpack(ref x1y2z2, sx1, sy2, sz2, src.Format, src.Data, src, srcelemsize);
                        Unpack(ref x2y2z2, sx2, sy2, sz2, src.Format, src.Data, src, srcelemsize);

                        var accum = x1y1z1 * ((1.0f - sxf) * (1.0f - syf) * (1.0f - szf)) + x2y1z1 * (sxf * (1.0f - syf) * (1.0f - szf)) +
                                    x1y2z1 * ((1.0f - sxf) * syf * (1.0f - szf)) + x2y2z1 * (sxf * syf * (1.0f - szf)) +
                                    x1y1z2 * ((1.0f - sxf) * (1.0f - syf) * szf) + x2y1z2 * (sxf * (1.0f - syf) * szf) +
                                    x1y2z2 * ((1.0f - sxf) * syf * szf) + x2y2z2 * (sxf * syf * szf);

                        PixelConverter.PackColor(accum, dst.Format, dst.Data + dstOffset);
                        dstOffset += dstelemsize;
                    }
                    dstOffset += dstelemsize * dst.RowSkip;
                }
                dstOffset += dstelemsize * dst.SliceSkip;
            }
        }
Example #18
0
 public static PixelComponentType GetComponentType(PixelFormat format)
 {
     return(PixelConverter.GetDescriptionFor(format).componentType);
 }
Example #19
0
 public static bool IsNativeEndian(PixelFormat format)
 {
     return((PixelConverter.GetDescriptionFor(format).flags & PixelFormatFlags.NativeEndian) > 0);
 }
Example #20
0
 public static bool IsLuminance(PixelFormat format)
 {
     return((PixelConverter.GetDescriptionFor(format).flags & PixelFormatFlags.Luminance) > 0);
 }
Example #21
0
 public static bool IsFloatingPoint(PixelFormat format)
 {
     return((PixelConverter.GetDescriptionFor(format).flags & PixelFormatFlags.Float) > 0);
 }