예제 #1
0
        static private byte[] convertToFormat(PixelFormat srcFormat, byte[] src, int w, int h, PixelFormat dstFormat, bool dxt1HasAlpha = false, byte dxt1Threshold = 128)
        {
            byte[] tempData;

            switch (dstFormat)
            {
            case PixelFormat.DXT1:
            case PixelFormat.DXT3:
            case PixelFormat.DXT5:
            case PixelFormat.ATI2:
                tempData = convertRawToARGB(src, w, h, srcFormat);
                if (dstFormat == PixelFormat.ATI2 && (w < 4 || h < 4))
                {
                    tempData = new byte[MipMap.getBufferSize(w, h, dstFormat)];
                }
                else if (w < 4 || h < 4)
                {
                    if (w < 4)
                    {
                        w = 4;
                    }
                    if (h < 4)
                    {
                        h = 4;
                    }
                    tempData = new byte[MipMap.getBufferSize(w, h, dstFormat)];
                }
                else
                {
                    tempData = compressMipmap(dstFormat, tempData, w, h, dxt1HasAlpha, dxt1Threshold);
                }
                break;

            case PixelFormat.ARGB:
                tempData = convertRawToARGB(src, w, h, srcFormat);
                break;

            case PixelFormat.RGB:
                tempData = convertRawToRGB(src, w, h, srcFormat);
                break;

            case PixelFormat.V8U8:
                tempData = convertRawToARGB(src, w, h, srcFormat);
                tempData = ARGBtoV8U8(tempData, w, h);
                break;

            case PixelFormat.G8:
                tempData = convertRawToARGB(src, w, h, srcFormat);
                tempData = ARGBtoG8(tempData, w, h);
                break;

            default:
                throw new Exception("not supported format");
            }

            return(tempData);
        }
예제 #2
0
        private void LoadImage(MemoryStream stream, ImageFormat format)
        {
            mipMaps = new List <MipMap>();
            switch (format)
            {
            case ImageFormat.DDS:
            {
                LoadImageDDS(stream);
                break;
            }

            case ImageFormat.TGA:
            {
                LoadImageTGA(stream);
                break;
            }

            case ImageFormat.BMP:
            {
                LoadImageBMP(stream);
                break;
            }

            case ImageFormat.PNG:
            case ImageFormat.JPEG:
            {
                BitmapSource frame = format == ImageFormat.PNG
                            ? new PngBitmapDecoder(stream, BitmapCreateOptions.None, BitmapCacheOption.Default).Frames[0]
                            : new JpegBitmapDecoder(stream, BitmapCreateOptions.None, BitmapCacheOption.Default).Frames[0];

                if (!IsPowerOfTwo(frame.PixelWidth) || !IsPowerOfTwo(frame.PixelHeight))
                {
                    throw new TextureSizeNotPowerOf2Exception();
                }

                FormatConvertedBitmap srcBitmap = new FormatConvertedBitmap();
                srcBitmap.BeginInit();
                srcBitmap.Source            = frame;
                srcBitmap.DestinationFormat = PixelFormats.Bgra32;
                srcBitmap.EndInit();

                var pixels = new byte[srcBitmap.PixelWidth * srcBitmap.PixelHeight * 4];
                frame.CopyPixels(pixels, srcBitmap.PixelWidth * 4, 0);

                pixelFormat = PixelFormat.ARGB;
                MipMap mipmap = new MipMap(pixels, srcBitmap.PixelWidth, srcBitmap.PixelHeight, PixelFormat.ARGB);
                mipMaps.Add(mipmap);
                break;
            }

            default:
                throw new Exception();
            }
        }
예제 #3
0
        public Image convertToRGB()
        {
            for (int i = 0; i < mipMaps.Count; i++)
            {
                mipMaps[i] = new MipMap(convertRawToRGB(mipMaps[i].data, mipMaps[i].width, mipMaps[i].height, pixelFormat),
                                        mipMaps[i].width, mipMaps[i].height, PixelFormat.RGB);
            }
            pixelFormat = PixelFormat.RGB;

            return(this);
        }
예제 #4
0
        public void StoreImageToDDS(Stream stream, PixelFormat format = PixelFormat.Unknown)
        {
            stream.WriteUInt32(DDS_TAG);
            stream.WriteInt32(DDS_HEADER_dwSize);
            stream.WriteUInt32(DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE);
            stream.WriteInt32(mipMaps[0].height);
            stream.WriteInt32(mipMaps[0].width);

            int dataSize = 0;

            for (int i = 0; i < mipMaps.Count; i++)
            {
                dataSize += MipMap.getBufferSize(mipMaps[i].width, mipMaps[i].height, format == PixelFormat.Unknown ? pixelFormat : format);
            }

            stream.WriteInt32(dataSize);

            stream.WriteUInt32(0); // dwDepth
            stream.WriteInt32(mipMaps.Count);
            stream.WriteZeros(44); // dwReserved1

            stream.WriteInt32(DDS_PIXELFORMAT_dwSize);
            DDS_PF pixfmt = getDDSPixelFormat(format == PixelFormat.Unknown ? pixelFormat : format);

            stream.WriteUInt32(pixfmt.flags);
            stream.WriteUInt32(pixfmt.fourCC);
            stream.WriteUInt32(pixfmt.bits);
            stream.WriteUInt32(pixfmt.Rmask);
            stream.WriteUInt32(pixfmt.Gmask);
            stream.WriteUInt32(pixfmt.Bmask);
            stream.WriteUInt32(pixfmt.Amask);

            stream.WriteInt32(DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE);
            stream.WriteUInt32(0); // dwCaps2
            stream.WriteUInt32(0); // dwCaps3
            stream.WriteUInt32(0); // dwCaps4
            stream.WriteUInt32(0); // dwReserved2
            for (int i = 0; i < mipMaps.Count; i++)
            {
                stream.WriteFromBuffer(mipMaps[i].data);
            }
        }
예제 #5
0
        private void LoadImageBMP(MemoryStream stream)
        {
            ushort tag = stream.ReadUInt16();

            if (tag != BMP_TAG)
            {
                throw new Exception("not BMP header");
            }

            stream.Skip(8);

            uint offsetData = stream.ReadUInt32();
            int  headerSize = stream.ReadInt32();

            int  imageWidth  = stream.ReadInt32();
            int  imageHeight = stream.ReadInt32();
            bool downToTop   = true;

            if (imageHeight < 0)
            {
                imageHeight = -imageHeight;
                downToTop   = false;
            }
            if (!IsPowerOfTwo(imageWidth) || !IsPowerOfTwo(imageHeight))
            {
                throw new TextureSizeNotPowerOf2Exception();
            }

            stream.Skip(2);

            int bits = stream.ReadUInt16();

            if (bits != 32 && bits != 24)
            {
                throw new Exception("only 24 and 32 bits BMP supported!");
            }

            bool hasAlphaMask = false;
            uint Rmask = 0xFF0000, Gmask = 0xFF00, Bmask = 0xFF, Amask = 0xFF000000;

            if (headerSize >= 40)
            {
                int compression = stream.ReadInt32();
                if (compression == 1 || compression == 2)
                {
                    throw new Exception("compression not supported in BMP!");
                }

                if (compression == 3)
                {
                    stream.Skip(20);
                    Rmask = stream.ReadUInt32();
                    Gmask = stream.ReadUInt32();
                    Bmask = stream.ReadUInt32();
                    if (headerSize >= 56)
                    {
                        Amask        = stream.ReadUInt32();
                        hasAlphaMask = true;
                    }
                }

                stream.JumpTo(headerSize + 14);
            }

            int Rshift = getShiftFromMask(Rmask);
            int Gshift = getShiftFromMask(Gmask);
            int Bshift = getShiftFromMask(Bmask);
            int Ashift = getShiftFromMask(Amask);

            byte[] buffer = new byte[imageWidth * imageHeight * 4];
            int    pos    = downToTop ? imageWidth * (imageHeight - 1) * 4 : 0;
            int    delta  = downToTop ? -imageWidth * 4 * 2 : 0;

            for (int h = 0; h < imageHeight; h++)
            {
                for (int i = 0; i < imageWidth; i++)
                {
                    if (bits == 24)
                    {
                        buffer[pos++] = (byte)stream.ReadByte();
                        buffer[pos++] = (byte)stream.ReadByte();
                        buffer[pos++] = (byte)stream.ReadByte();
                        buffer[pos++] = 255;
                    }
                    else if (bits == 32)
                    {
                        uint p1    = (uint)stream.ReadByte();
                        uint p2    = (uint)stream.ReadByte();
                        uint p3    = (uint)stream.ReadByte();
                        uint p4    = (uint)stream.ReadByte();
                        uint pixel = p4 << 24 | p3 << 16 | p2 << 8 | p1;
                        buffer[pos++] = (byte)((pixel & Bmask) >> Bshift);
                        buffer[pos++] = (byte)((pixel & Gmask) >> Gshift);
                        buffer[pos++] = (byte)((pixel & Rmask) >> Rshift);
                        buffer[pos++] = (byte)((pixel & Amask) >> Ashift);
                    }
                }
                if (imageWidth % 4 != 0)
                {
                    stream.Skip(4 - (imageWidth % 4));
                }
                pos += delta;
            }

            if (bits == 32 && !hasAlphaMask)
            {
                bool hasAlpha = false;
                for (int i = 0; i < imageWidth * imageHeight; i++)
                {
                    if (buffer[4 * i + 3] != 0)
                    {
                        hasAlpha = true;
                        break;
                    }
                }

                if (!hasAlpha)
                {
                    for (int i = 0; i < imageWidth * imageHeight; i++)
                    {
                        buffer[4 * i + 3] = 255;
                    }
                }
            }

            pixelFormat = PixelFormat.ARGB;
            MipMap mipmap = new MipMap(buffer, imageWidth, imageHeight, PixelFormat.ARGB);

            mipMaps.Add(mipmap);
        }
예제 #6
0
        private void LoadImageDDS(MemoryStream stream)
        {
            if (stream.ReadUInt32() != DDS_TAG)
            {
                throw new Exception("not DDS tag");
            }

            if (stream.ReadInt32() != DDS_HEADER_dwSize)
            {
                throw new Exception("wrong DDS header dwSize");
            }

            DDSflags = stream.ReadUInt32();

            int dwHeight = stream.ReadInt32();
            int dwWidth  = stream.ReadInt32();

            if (!IsPowerOfTwo(dwWidth) ||
                !IsPowerOfTwo(dwHeight))
            {
                throw new TextureSizeNotPowerOf2Exception();
            }

            stream.Skip(8); // dwPitchOrLinearSize, dwDepth

            int dwMipMapCount = stream.ReadInt32();

            if (dwMipMapCount == 0)
            {
                dwMipMapCount = 1;
            }

            stream.Skip(11 * 4); // dwReserved1
            stream.SkipInt32();  // ppf.dwSize

            ddsPixelFormat.flags  = stream.ReadUInt32();
            ddsPixelFormat.fourCC = stream.ReadUInt32();
            if ((ddsPixelFormat.flags & DDPF_FOURCC) != 0 && ddsPixelFormat.fourCC == FOURCC_DX10_TAG)
            {
                throw new Exception("DX10 DDS format not supported");
            }

            ddsPixelFormat.bits  = stream.ReadUInt32();
            ddsPixelFormat.Rmask = stream.ReadUInt32();
            ddsPixelFormat.Gmask = stream.ReadUInt32();
            ddsPixelFormat.Bmask = stream.ReadUInt32();
            ddsPixelFormat.Amask = stream.ReadUInt32();

            switch (ddsPixelFormat.fourCC)
            {
            case 0:
                if (ddsPixelFormat.bits == 32 &&
                    (ddsPixelFormat.flags & DDPF_ALPHAPIXELS) != 0 &&
                    ddsPixelFormat.Rmask == 0xFF0000 &&
                    ddsPixelFormat.Gmask == 0xFF00 &&
                    ddsPixelFormat.Bmask == 0xFF &&
                    ddsPixelFormat.Amask == 0xFF000000)
                {
                    pixelFormat = PixelFormat.ARGB;
                    break;
                }
                if (ddsPixelFormat.bits == 24 &&
                    ddsPixelFormat.Rmask == 0xFF0000 &&
                    ddsPixelFormat.Gmask == 0xFF00 &&
                    ddsPixelFormat.Bmask == 0xFF)
                {
                    pixelFormat = PixelFormat.RGB;
                    break;
                }
                if (ddsPixelFormat.bits == 16 &&
                    ddsPixelFormat.Rmask == 0xFF &&
                    ddsPixelFormat.Gmask == 0xFF00 &&
                    ddsPixelFormat.Bmask == 0x00)
                {
                    pixelFormat = PixelFormat.V8U8;
                    break;
                }
                if (ddsPixelFormat.bits == 8 &&
                    ddsPixelFormat.Rmask == 0xFF &&
                    ddsPixelFormat.Gmask == 0x00 &&
                    ddsPixelFormat.Bmask == 0x00)
                {
                    pixelFormat = PixelFormat.G8;
                    break;
                }
                throw new Exception("Not supported DDS format");

            case 21:
                pixelFormat = PixelFormat.ARGB;
                break;

            case 20:
                pixelFormat = PixelFormat.RGB;
                break;

            case 60:
                pixelFormat = PixelFormat.V8U8;
                break;

            case 50:
                pixelFormat = PixelFormat.G8;
                break;

            case FOURCC_DXT1_TAG:
                pixelFormat = PixelFormat.DXT1;
                break;

            case FOURCC_DXT3_TAG:
                pixelFormat = PixelFormat.DXT3;
                break;

            case FOURCC_DXT5_TAG:
                pixelFormat = PixelFormat.DXT5;
                break;

            case FOURCC_ATI2_TAG:
                pixelFormat = PixelFormat.ATI2;
                break;

            default:
                throw new Exception("Not supported DDS format");
            }
            stream.Skip(5 * 4); // dwCaps, dwCaps2, dwCaps3, dwCaps4, dwReserved2

            for (int i = 0; i < dwMipMapCount; i++)
            {
                int w     = dwWidth >> i;
                int h     = dwHeight >> i;
                int origW = w;
                int origH = h;
                if (origW == 0 && origH != 0)
                {
                    origW = 1;
                }
                if (origH == 0 && origW != 0)
                {
                    origH = 1;
                }
                w = origW;
                h = origH;

                if (pixelFormat == PixelFormat.DXT1 ||
                    pixelFormat == PixelFormat.DXT3 ||
                    pixelFormat == PixelFormat.DXT5)
                {
                    if (w < 4)
                    {
                        w = 4;
                    }
                    if (h < 4)
                    {
                        h = 4;
                    }
                }

                byte[] tempData;
                try
                {
                    tempData = stream.ReadToBuffer(MipMap.getBufferSize(w, h, pixelFormat));
                }
                catch
                {
                    throw new Exception("not enough data in stream");
                }

                mipMaps.Add(new MipMap(tempData, origW, origH, pixelFormat));
            }
        }
예제 #7
0
        private void LoadImageTGA(MemoryStream stream)
        {
            int idLength = stream.ReadByte();

            int colorMapType = stream.ReadByte();

            if (colorMapType != 0)
            {
                throw new Exception("indexed TGA not supported!");
            }

            int imageType = stream.ReadByte();

            if (imageType != 2 && imageType != 10)
            {
                throw new Exception("only RGB TGA supported!");
            }

            bool compressed = imageType == 10;

            stream.SkipInt16(); // color map first entry index
            stream.SkipInt16(); // color map length
            stream.Skip(1);     // color map entry size
            stream.SkipInt16(); // x origin
            stream.SkipInt16(); // y origin

            int imageWidth  = stream.ReadInt16();
            int imageHeight = stream.ReadInt16();

            if (!IsPowerOfTwo(imageWidth) || !IsPowerOfTwo(imageHeight))
            {
                throw new TextureSizeNotPowerOf2Exception();
            }

            int imageDepth = stream.ReadByte();

            if (imageDepth != 32 && imageDepth != 24)
            {
                throw new Exception("only 24 and 32 bits TGA supported!");
            }

            int imageDesc = stream.ReadByte();

            if ((imageDesc & 0x10) != 0)
            {
                throw new Exception("origin right not supported in TGA!");
            }

            bool downToTop = (imageDesc & 0x20) == 0;

            stream.Skip(idLength);

            byte[] buffer = new byte[imageWidth * imageHeight * 4];
            int    pos    = downToTop ? imageWidth * (imageHeight - 1) * 4 : 0;
            int    delta  = downToTop ? -imageWidth * 4 * 2 : 0;

            if (compressed)
            {
                int count = 0, repeat = 0, w = 0, h = 0;
                for (; ;)
                {
                    if (count == 0 && repeat == 0)
                    {
                        byte code = (byte)stream.ReadByte();
                        if ((code & 0x80) != 0)
                        {
                            repeat = (code & 0x7F) + 1;
                        }
                        else
                        {
                            count = code + 1;
                        }
                    }
                    else
                    {
                        if (repeat != 0)
                        {
                            byte pixelR = (byte)stream.ReadByte();
                            byte pixelG = (byte)stream.ReadByte();
                            byte pixelB = (byte)stream.ReadByte();
                            byte pixelA;
                            if (imageDepth == 32)
                            {
                                pixelA = (byte)stream.ReadByte();
                            }
                            else
                            {
                                pixelA = 0xFF;
                            }
                            for (; w < imageWidth && repeat > 0; w++, repeat--)
                            {
                                buffer[pos++] = pixelR;
                                buffer[pos++] = pixelG;
                                buffer[pos++] = pixelB;
                                buffer[pos++] = pixelA;
                            }
                        }
                        else
                        {
                            for (; w < imageWidth && count > 0; w++, count--)
                            {
                                buffer[pos++] = (byte)stream.ReadByte();
                                buffer[pos++] = (byte)stream.ReadByte();
                                buffer[pos++] = (byte)stream.ReadByte();
                                if (imageDepth == 32)
                                {
                                    buffer[pos++] = (byte)stream.ReadByte();
                                }
                                else
                                {
                                    buffer[pos++] = 0xFF;
                                }
                            }
                        }
                    }

                    if (w == imageWidth)
                    {
                        w    = 0;
                        pos += delta;
                        if (++h == imageHeight)
                        {
                            break;
                        }
                    }
                }
            }
            else
            {
                for (int h = 0; h < imageHeight; h++, pos += delta)
                {
                    for (int w = 0; w < imageWidth; w++)
                    {
                        buffer[pos++] = (byte)stream.ReadByte();
                        buffer[pos++] = (byte)stream.ReadByte();
                        buffer[pos++] = (byte)stream.ReadByte();
                        if (imageDepth == 32)
                        {
                            buffer[pos++] = (byte)stream.ReadByte();
                        }
                        else
                        {
                            buffer[pos++] = 0xFF;
                        }
                    }
                }
            }

            pixelFormat = PixelFormat.ARGB;
            MipMap mipmap = new MipMap(buffer, imageWidth, imageHeight, PixelFormat.ARGB);

            mipMaps.Add(mipmap);
        }