예제 #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
        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);
            }
        }
예제 #3
0
        public void correctMips(PixelFormat dstFormat, bool dxt1HasAlpha = false, byte dxt1Threshold = 128)
        {
            byte[] tempData;

            if (pixelFormat != PixelFormat.ARGB)
            {
                tempData = convertRawToARGB(mipMaps[0].data, mipMaps[0].width, mipMaps[0].height, pixelFormat);
            }
            else
            {
                tempData = mipMaps[0].data;
            }

            int width  = mipMaps[0].origWidth;
            int height = mipMaps[0].origHeight;

            if (mipMaps.Count > 1)
            {
                mipMaps.RemoveRange(1, mipMaps.Count - 1);
            }

            if (dstFormat != pixelFormat || (dstFormat == PixelFormat.DXT1 && !dxt1HasAlpha))
            {
                byte[] top = convertToFormat(PixelFormat.ARGB, tempData, width, height, dstFormat, dxt1HasAlpha, dxt1Threshold);
                mipMaps.RemoveAt(0);
                mipMaps.Add(new MipMap(top, width, height, dstFormat));
                pixelFormat = dstFormat;
            }

            int prevW, prevH;
            int origW = width;
            int origH = height;

            for (;;)
            {
                prevW   = width;
                prevH   = height;
                origW >>= 1;
                origH >>= 1;
                if (origW == 0 && origH == 0)
                {
                    break;
                }
                if (origW == 0)
                {
                    origW = 1;
                }
                if (origH == 0)
                {
                    origH = 1;
                }
                width  = origW;
                height = origH;

                if (pixelFormat == PixelFormat.ATI2 && (width < 4 || height < 4))
                {
                    tempData = new byte[MipMap.getBufferSize(width, height, dstFormat)];
                    mipMaps.Add(new MipMap(tempData, width, height, pixelFormat));
                    continue;
                }

                if (pixelFormat == PixelFormat.DXT1 ||
                    pixelFormat == PixelFormat.DXT3 ||
                    pixelFormat == PixelFormat.DXT5)
                {
                    if (width < 4 || height < 4)
                    {
                        if (width < 4)
                        {
                            width = 4;
                        }
                        if (height < 4)
                        {
                            height = 4;
                        }
                        tempData = new byte[MipMap.getBufferSize(width, height, dstFormat)];
                        mipMaps.Add(new MipMap(tempData, origW, origH, pixelFormat));
                        continue;
                    }
                }

                tempData = downscaleARGB(tempData, prevW, prevH);
                if (pixelFormat != PixelFormat.ARGB)
                {
                    byte[] converted = convertToFormat(PixelFormat.ARGB, tempData, origW, origH, pixelFormat, dxt1HasAlpha, dxt1Threshold);
                    mipMaps.Add(new MipMap(converted, origW, origH, pixelFormat));
                }
                else
                {
                    mipMaps.Add(new MipMap(tempData, origW, origH, pixelFormat));
                }
            }
        }
예제 #4
0
        private void LoadImageDDS(MemoryStream stream, ImageFormat format)
        {
            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 (!checkPowerOfTwo(dwWidth) ||
                !checkPowerOfTwo(dwHeight))
            {
                throw new Exception("dimensions not power of two");
            }

            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

            byte[] tempData;
            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;
                    }
                }

                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));
            }
        }