Beispiel #1
0
        private static unsafe MipGeneratorFn _Get(MipFormat format)
        {
            switch (format)
            {
            case MipFormat.RGBA:
            case MipFormat.pRGBA:
                return(_Color);

            // FIXME: Is this right? I think maybe it needs to be different
            case MipFormat.RGBA | MipFormat.sRGB:
            case MipFormat.pRGBA | MipFormat.sRGB:
                return(_sRGBColor);

            case MipFormat.Gray1:
                return(_Gray);

            case MipFormat.pGray4:
                return(_PAGray);

            case MipFormat.pGray4 | MipFormat.sRGB:
                return(_sRGBPAGray);

            default:
                return(null);
            }
        }
Beispiel #2
0
            public unsafe MipGeneratorFn Get(MipFormat format)
            {
                switch (format)
                {
                case MipFormat.pGray4:
                    return(PAGray);

                default:
                    throw new ArgumentOutOfRangeException("format");
                }
            }
Beispiel #3
0
        public static unsafe MipGeneratorFn Get(
            MipFormat format,
            stbir_filter filter_horizontal = stbir_filter.DEFAULT,
            stbir_filter filter_vertical   = stbir_filter.DEFAULT,
            stbir_edge edge_horizontal     = stbir_edge.CLAMP,
            stbir_edge edge_vertical       = stbir_edge.CLAMP
            )
        {
            var masked   = (format & ~MipFormat.sRGB);
            var datatype = (masked == MipFormat.Vector4) ||
                           (masked == MipFormat.pVector4) ||
                           (masked == MipFormat.Single)
                ? stbir_datatype.FLOAT
                : stbir_datatype.UINT8;
            var colorspace = (format & MipFormat.sRGB) == MipFormat.sRGB
                ? stbir_colorspace.SRGB
                : stbir_colorspace.LINEAR;
            var channels = masked == MipFormat.Gray1 ? 1 : 4;
            var flags    = (masked == MipFormat.pRGBA) ||
                           (masked == MipFormat.pGray4) ||
                           (masked == MipFormat.pVector4)
                ? stbir_flags.ALPHA_PREMULTIPLIED
                : default;
            var alpha_channel = (masked == MipFormat.Gray1) ? -1 : 3;

            unsafe void Implementation(
                void *src, int srcWidth, int srcHeight, int srcStrideBytes,
                void *dest, int destWidth, int destHeight, int destStrideBytes
                )
            {
                var result = API.stbir_resize(
                    src, srcWidth, srcHeight, srcStrideBytes,
                    dest, destWidth, destHeight, destStrideBytes,
                    datatype, channels, alpha_channel, (int)flags,
                    edge_horizontal, edge_vertical,
                    filter_horizontal, filter_vertical,
                    colorspace, null
                    );

                if (result != 1)
                {
                    throw new Exception("An error occurred in stb_image_resize");
                }
            }

            return(Implementation);
        }
    }
Beispiel #4
0
        public static MipGeneratorFn Get(MipFormat format)
        {
            var index = (int)format;

            if ((index < 0) || (index >= Cache.Length))
            {
                throw new ArgumentOutOfRangeException("format");
            }
            var result = Cache[index];

            if (result == null)
            {
                throw new ArgumentOutOfRangeException("format");
            }
            return(result);
        }
Beispiel #5
0
 public static void Set(MipFormat format, MipGeneratorFn implementation)
 {
     Cache[(int)format] = implementation;
 }
Beispiel #6
0
        private unsafe void GenerateMips(bool sRGB)
        {
            void *pPreviousLevelData = null, pLevelData = Data;
            int   levelWidth = Width, levelHeight = Height;
            int   previousLevelWidth = Width, previousLevelHeight = Height;

            // FIXME
            MipChain = new byte[64][];
            var pins = new List <GCHandle>();

            MipFormat format = (MipFormat)(-1);

            if (IsFloatingPoint)
            {
                if (ChannelCount == 4)
                {
                    format = IsPremultiplied ? MipFormat.pVector4 : MipFormat.Vector4;
                }
                else if (ChannelCount == 1)
                {
                    format = MipFormat.Single;
                }
            }
            else if (!Is16Bit)
            {
                if (ChannelCount == 4)
                {
                    format = IsPremultiplied ? MipFormat.pRGBA : MipFormat.RGBA;
                }
                else
                {
                    format = MipFormat.Gray1;
                }
            }

            if (format == (MipFormat)(-1))
            {
                throw new ArgumentOutOfRangeException("Mip generation is not supported for this image format");
            }
            if (sRGB)
            {
                format |= MipFormat.sRGB;
            }

            var mipGenerator = STBMipGenerator.Get(format);

            for (uint level = 0; (levelWidth >= 1) && (levelHeight >= 1); level++)
            {
                if (IsDisposed)
                {
                    throw new ObjectDisposedException("Image");
                }

                if (level > 0)
                {
                    var levelBuf = new byte[levelWidth * levelHeight * SizeofPixel];
                    MipChain[level - 1] = levelBuf;
                    var pin = GCHandle.Alloc(levelBuf, GCHandleType.Pinned);
                    pins.Add(pin);
                    pLevelData = (void *)pin.AddrOfPinnedObject();
                    // FIXME: Do this one step at a time in a list of work items
                    var previousStrideBytes = previousLevelWidth * SizeofPixel;
                    var levelStrideBytes    = levelWidth * SizeofPixel;
                    mipGenerator(
                        pPreviousLevelData, previousLevelWidth, previousLevelHeight, previousStrideBytes,
                        pLevelData, levelWidth, levelHeight, levelStrideBytes
                        );
                }

                previousLevelWidth  = levelWidth;
                previousLevelHeight = levelHeight;
                var newWidth  = levelWidth / 2;
                var newHeight = levelHeight / 2;
                levelWidth         = newWidth;
                levelHeight        = newHeight;
                pPreviousLevelData = pLevelData;
            }

            foreach (var pin in pins)
            {
                pin.Free();
            }
        }