예제 #1
0
파일: Program.cs 프로젝트: tsvx/Image2Raw
        static string SaveBitmap(string origName, RawFormat format, Size size, byte[] data)
        {
            string rawName = Path.ChangeExtension(origName, $"{format}-{size.Width}x{size.Height}.raw");

            File.WriteAllBytes(rawName, data);
            return(rawName);
        }
예제 #2
0
파일: Image.cs 프로젝트: nhbcyz/corefx
        public void Save(string filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
        {
            if (filename == null)
            {
                throw new ArgumentNullException("filename");
            }
            if (encoder == null)
            {
                throw new ArgumentNullException("encoder");
            }

            IntPtr encoderParamsMemory = IntPtr.Zero;

            if (encoderParams != null)
            {
                _rawData            = null;
                encoderParamsMemory = encoderParams.ConvertToMemory();
            }
            int status = SafeNativeMethods.Gdip.Ok;

            try
            {
                Guid g     = encoder.Clsid;
                bool saved = false;

                if (_rawData != null)
                {
                    ImageCodecInfo rawEncoder = RawFormat.FindEncoder();
                    if (rawEncoder != null && rawEncoder.Clsid == g)
                    {
                        using (FileStream fs = File.OpenWrite(filename))
                        {
                            fs.Write(_rawData, 0, _rawData.Length);
                            saved = true;
                        }
                    }
                }

                if (!saved)
                {
                    status = SafeNativeMethods.Gdip.GdipSaveImageToFile(new HandleRef(this, nativeImage),
                                                                        filename,
                                                                        ref g,
                                                                        new HandleRef(encoderParams, encoderParamsMemory));
                }
            }
            finally
            {
                if (encoderParamsMemory != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(encoderParamsMemory);
                }
            }

            if (status != SafeNativeMethods.Gdip.Ok)
            {
                throw SafeNativeMethods.Gdip.StatusException(status);
            }
        }
예제 #3
0
        /// <summary>
        /// Saves this <see cref='Image'/> to the specified file in the specified format and with the specified encoder parameters.
        /// </summary>
        public void Save(string filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
        {
            if (filename == null)
            {
                throw new ArgumentNullException(nameof(filename));
            }
            if (encoder == null)
            {
                throw new ArgumentNullException(nameof(encoder));
            }
            if (!Directory.Exists(Path.GetDirectoryName(filename)))
            {
                throw new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, filename));
            }

            IntPtr encoderParamsMemory = IntPtr.Zero;

            if (encoderParams != null)
            {
                _rawData            = null;
                encoderParamsMemory = encoderParams.ConvertToMemory();
            }

            try
            {
                Guid g     = encoder.Clsid;
                bool saved = false;

                if (_rawData != null)
                {
                    ImageCodecInfo rawEncoder = RawFormat.FindEncoder();
                    if (rawEncoder != null && rawEncoder.Clsid == g)
                    {
                        using (FileStream fs = File.OpenWrite(filename))
                        {
                            fs.Write(_rawData, 0, _rawData.Length);
                            saved = true;
                        }
                    }
                }

                if (!saved)
                {
                    Gdip.CheckStatus(Gdip.GdipSaveImageToFile(
                                         new HandleRef(this, nativeImage),
                                         filename,
                                         ref g,
                                         new HandleRef(encoderParams, encoderParamsMemory)));
                }
            }
            finally
            {
                if (encoderParamsMemory != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(encoderParamsMemory);
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Saves this <see cref='Image'/> to the specified stream in the specified format.
        /// </summary>
        public void Save(Stream stream, ImageCodecInfo encoder, EncoderParameters?encoderParams)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }
            if (encoder == null)
            {
                throw new ArgumentNullException(nameof(encoder));
            }

            IntPtr encoderParamsMemory = IntPtr.Zero;

            if (encoderParams != null)
            {
                _rawData            = null;
                encoderParamsMemory = encoderParams.ConvertToMemory();
            }

            try
            {
                Guid g     = encoder.Clsid;
                bool saved = false;

                if (_rawData != null)
                {
                    ImageCodecInfo?rawEncoder = RawFormat.FindEncoder();
                    if (rawEncoder != null && rawEncoder.Clsid == g)
                    {
                        stream.Write(_rawData, 0, _rawData.Length);
                        saved = true;
                    }
                }

                if (!saved)
                {
                    using DrawingCom.IStreamWrapper streamWrapper = DrawingCom.GetComWrapper(new GPStream(stream, makeSeekable: false));
                    unsafe
                    {
                        Gdip.CheckStatus(Gdip.GdipSaveImageToStream(
                                             new HandleRef(this, nativeImage),
                                             streamWrapper.Ptr,
                                             &g,
                                             new HandleRef(encoderParams, encoderParamsMemory)));
                    }
                }
            }
            finally
            {
                if (encoderParamsMemory != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(encoderParamsMemory);
                }
            }
        }
예제 #5
0
        /// <include file='doc\Image.uex' path='docs/doc[@for="Image.Save4"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Saves this <see cref='System.Drawing.Image'/> to the specified stream in the specified
        ///       format.
        ///    </para>
        /// </devdoc>
        public void Save(Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (encoder == null)
            {
                throw new ArgumentNullException("encoder");
            }

            IntPtr encoderParamsMemory = IntPtr.Zero;

            if (encoderParams != null)
            {
                rawData             = null;
                encoderParamsMemory = encoderParams.ConvertToMemory();
            }
            int status = SafeNativeMethods.Ok;

            try {
                Guid g     = encoder.Clsid;
                bool saved = false;

                if (rawData != null)
                {
                    ImageCodecInfo rawEncoder = RawFormat.FindEncoder();
                    if (rawEncoder.Clsid == g)
                    {
                        stream.Write(rawData, 0, rawData.Length);
                        saved = true;
                    }
                }

                if (!saved)
                {
                    status = SafeNativeMethods.GdipSaveImageToStream(new HandleRef(this, nativeImage),
                                                                     new UnsafeNativeMethods.ComStreamFromDataStream(stream),
                                                                     ref g,
                                                                     new HandleRef(encoderParams, encoderParamsMemory));
                }
            }
            finally {
                if (encoderParamsMemory != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(encoderParamsMemory);
                }
            }

            if (status != SafeNativeMethods.Ok)
            {
                throw SafeNativeMethods.StatusException(status);
            }
        }
예제 #6
0
        /// <summary>
        /// NEW!!  So far alright?
        /// </summary>
        public void SegwitTestNet()
        {
            //The faucet: https://testnet.manu.backend.hamburg/faucet
            //https://bitcoin.stackexchange.com/questions/59231/how-to-sign-a-segwit-transaction-via-nbitcoin
            var           net      = NBitcoin.Network.TestNet;
            BlockExplorer explorer = new BlockExplorer("https://testnet.blockexplorer.com/");
            HDWallet      wallet   = new HDWallet("seed12345678ryan12345678", net);
            uint          path     = 0;
            var           extkey   = wallet.GetPrivateKey(path);
            Key           k        = extkey.PrivateKey;

            //This gives you a Bech32 address (currently not really interoperable in wallets, so you need to convert it into P2SH)
            var address = k.PubKey.WitHash.GetAddress(net);

            var p2sh = address.GetScriptAddress();
            //p2sh is now an interoperable P2SH segwit address

            //SENT TO: 2NGSoYM3yLi9SXvZc5yYcSwHWyCWzgBrP9X
            //TXID 1397a4cc480879eae604ce871c47a4d690c6ea6a6dcfd7e38d95f31b81593556

            var response = explorer.GetUnspent(p2sh.ToString());
            List <ExplorerUnspent> unspent      = response.Convert <List <ExplorerUnspent> >();
            List <Transaction>     transactions = new List <Transaction>();

            foreach (var item in unspent)
            {
                string           txcontent  = "{\"txid\":\"6636b3fedb57be81232f92f80fa8d3df9a0f07305af2c7f705a7f353e516b1d7\",\"version\":1,\"locktime\":0,\"vin\":[{\"txid\":\"50b7d9a5fa1281e7020fa8a152835756e0d57d6b4d634b4251ab500e8630bc3e\",\"vout\":1,\"scriptSig\":{\"asm\":\"0014a16f4ba22e84c364ec4f8fe19d8a48762156b41e\",\"hex\":\"160014a16f4ba22e84c364ec4f8fe19d8a48762156b41e\"},\"sequence\":4294967295,\"n\":0,\"addr\":\"2N9viNVJ5MsAM8MXdUuATDwKeMjMLQkaXyR\",\"valueSat\":193987962850,\"value\":1939.8796285,\"doubleSpentTxID\":null}],\"vout\":[{\"value\":\"2.00000000\",\"n\":0,\"scriptPubKey\":{\"hex\":\"a9142f672b3ea4af55d9da43e507e3c060d2e34521ba87\",\"asm\":\"OP_HASH160 2f672b3ea4af55d9da43e507e3c060d2e34521ba OP_EQUAL\",\"addresses\":[\"2MwZsLbuB328gxHRfr1VDrfDrK6aWicQcAW\"],\"type\":\"scripthash\"},\"spentTxId\":null,\"spentIndex\":null,\"spentHeight\":null},{\"value\":\"1937.87862850\",\"n\":1,\"scriptPubKey\":{\"hex\":\"a914859695c2cb37ee30bf6a18943c8c27a3ac0e6faa87\",\"asm\":\"OP_HASH160 859695c2cb37ee30bf6a18943c8c27a3ac0e6faa OP_EQUAL\",\"addresses\":[\"2N5RaFdK3rgsNayXnkTQaSLKVBB3brW7G4m\"],\"type\":\"scripthash\"},\"spentTxId\":\"892e6facc4fc596852d41af367dd41f7a7ec1b11a319a202bc0d4c5b8f792f2f\",\"spentIndex\":0,\"spentHeight\":1255964}],\"blockhash\":\"000000000007dbc3ffd03559f2192b299bc0c20aa0aea8e1939f2731e01103e8\",\"blockheight\":1255946,\"confirmations\":123,\"time\":1514228293,\"blocktime\":1514228293,\"valueOut\":1939.8786285,\"size\":138,\"valueIn\":1939.8796285,\"fees\":0.001}";
                ExplorerResponse txResponse = explorer.GetTransaction(item.txid);
                RawFormat        format     = RawFormat.Satoshi;
                var tx = Transaction.Parse(txResponse.data, format, net);
                transactions.Add(tx);
            }
            //For spending, it works the same as a a normal P2SH
            //You need to get the ScriptCoin, the RedeemScript of you script coin should be k.PubKey.WitHash.ScriptPubKey.            var redeemScript = k.PubKey.WitHash.ScriptPubKey;
            var         redeemScript = k.PubKey.WitHash.ScriptPubKey;
            Transaction received     = transactions[0];
            ScriptCoin  coin         = received.Outputs.AsCoins().First().ToScriptCoin(redeemScript);
            //1397a4cc480879eae604ce871c47a4d690c6ea6a6dcfd7e38d95f31b81593556

            BitcoinAddress     destination = BitcoinAddress.Create("2N8hwP1WmJrFF5QWABn38y63uYLhnJYJYTF"); //the faucet return address
            TransactionBuilder builder     = new TransactionBuilder();

            builder.AddCoins(coin);
            builder.AddKeys(k);
            builder.Send(destination, Money.Coins(1.99m));
            builder.SendFees(Money.Coins(0.001m));
            builder.SetChange(p2sh);
            var signedTx = builder.BuildTransaction(true);

            Console.WriteLine(signedTx.ToHex());
            string x = ";;";
            //Assert.True(builder.Verify(signedTx));
        }
 void ISerializable.GetObjectData(SerializationInfo si, StreamingContext context)
 {
     using (MemoryStream ms = new MemoryStream()) {
         // Icon is a decoder-only codec
         if (RawFormat.Equals(ImageFormat.Icon))
         {
             Save(ms, ImageFormat.Png);
         }
         else
         {
             Save(ms, RawFormat);
         }
         si.AddValue("Data", ms.ToArray());
     }
 }
예제 #8
0
        static private RawFormatter GetFormatter(RawFormat rawFormat, Network network)
        {
            RawFormatter formatter = null;

            switch (rawFormat)
            {
            case RawFormat.Satoshi:
                formatter = new SatoshiFormatter();
                break;

            case RawFormat.BlockExplorer:
                formatter = new BlockExplorerFormatter();
                break;

            default:
                throw new NotSupportedException(rawFormat.ToString());
            }
            formatter.Network = network ?? formatter.Network;
            return(formatter);
        }
예제 #9
0
        public string ToString(RawFormat rawFormat, Network network = null)
        {
            var formatter = GetFormatter(rawFormat, network);

            return(ToString(formatter));
        }
예제 #10
0
 public static Transaction Parse(string tx, RawFormat format, Network network = null)
 {
     return(GetFormatter(format, network).ParseJson(tx));
 }
예제 #11
0
 private static RawFormatter GetFormatter(RawFormat rawFormat, Network network)
 {
     RawFormatter formatter = null;
     switch(rawFormat)
     {
         case RawFormat.Satoshi:
             formatter = new SatoshiFormatter();
             break;
         case RawFormat.BlockExplorer:
             formatter = new BlockExplorerFormatter();
             break;
         default:
             throw new NotSupportedException(rawFormat.ToString());
     }
     formatter.Network = network ?? formatter.Network;
     return formatter;
 }
예제 #12
0
 public static Transaction Parse(string tx, RawFormat format, Network network = null)
 {
     return GetFormatter(format, network).Parse(tx);
 }
예제 #13
0
        public void CreateBasicSwap(uint path, params string[] seed)
        {
            List <ExtKey> keys   = new List <ExtKey>();
            Segwit        segwit = new Segwit(NBitcoin.Network.TestNet);

            for (int i = 0; i < seed.Length; i++)
            {
                var key     = GetKey(path, seed[i]);
                var address = segwit.GetP2SHAddress(key);
                keys.Add(key);
                //Console.WriteLine(address.ToString());
            }

            MultiSig multi = new MultiSig(NBitcoin.Network.TestNet);
            var      p2sh  = multi.GetP2SHAddress(2, keys.ToArray());

            Console.WriteLine(p2sh.ToString());
            //multi: b2366808fa2396a5a32120a27f55571055491d6ff8e6bd1e31e52bdd14b91dfb

            REST.BlockExplorer explorer = new REST.BlockExplorer("https://testnet.blockexplorer.com/");

            //var tx = explorer.GetTransaction("b2366808fa2396a5a32120a27f55571055491d6ff8e6bd1e31e52bdd14b91dfb");

            var response = explorer.GetUnspent(p2sh.ToString());
            List <ExplorerUnspent> unspent      = response.Convert <List <ExplorerUnspent> >();
            List <Transaction>     transactions = new List <Transaction>();

            foreach (var item in unspent)
            {
                ExplorerResponse txResponse = explorer.GetTransaction(item.txid);
                RawFormat        format     = RawFormat.Satoshi;
                var tx = Transaction.Parse(txResponse.data, format, Network.TestNet);
                transactions.Add(tx);
            }
            //Create send transaction.

            //get redeem script
            var         redeemScript = multi.GetRedeemScript(2, keys.ToArray());
            Transaction received     = transactions[0];
            ScriptCoin  coin         = received.Outputs.AsCoins().First().ToScriptCoin(redeemScript);

            //create transaction:

            BitcoinAddress     destination = BitcoinAddress.Create("2N8hwP1WmJrFF5QWABn38y63uYLhnJYJYTF"); //the faucet return address
            TransactionBuilder builder     = new TransactionBuilder();

            builder.AddCoins(coin);
            builder.Send(destination, Money.Coins(1.299m));
            builder.SendFees(Money.Coins(0.001m));
            builder.SetChange(destination);
            //builder.
            var unsigned = builder.BuildTransaction(sign: false);

            var         signedA = builder.AddCoins(coin).AddKeys(keys[0].PrivateKey).SignTransaction(unsigned);
            Transaction signedB = builder.AddCoins(coin).AddKeys(keys[1].PrivateKey).SignTransaction(signedA);

            Transaction fullySigned = builder.AddCoins(coin).CombineSignatures(signedA, signedB);

            Console.WriteLine(fullySigned.ToHex());
            Console.ReadLine();
        }
예제 #14
0
        public void NewCreateBasicSwap(uint path, params string[] seed)
        {
            List <ExtKey> keys   = new List <ExtKey>();
            Segwit        segwit = new Segwit(NBitcoin.Network.TestNet);

            for (int i = 0; i < seed.Length; i++)
            {
                var key = GetKey(path, seed[i]);
                //var address = segwit.GetP2SHAddress(key);
                keys.Add(key);
                //Console.WriteLine(address.ToString());
            }
            NBitcoin.Network _Network = NBitcoin.Network.TestNet;

            MultiSig      multi   = new MultiSig(NBitcoin.Network.TestNet);
            List <PubKey> pubKeys = new List <PubKey>();

            for (int i = 0; i < keys.Count; i++)
            {
                pubKeys.Add(keys[i].PrivateKey.PubKey);
            }
            Script pubKeyScript = PayToMultiSigTemplate.Instance.GenerateScriptPubKey(2, pubKeys.ToArray());

            BitcoinAddress       address = pubKeyScript.WitHash.GetAddress(_Network);
            BitcoinScriptAddress p2sh    = address.GetScriptAddress();

            Console.WriteLine("Send money here: " + p2sh.ToString());
            REST.BlockExplorer explorer = new REST.BlockExplorer("https://testnet.blockexplorer.com/");
            var response = explorer.GetUnspent(p2sh.ToString());
            List <ExplorerUnspent> unspent      = response.Convert <List <ExplorerUnspent> >();
            List <Transaction>     transactions = new List <Transaction>();

            foreach (var item in unspent)
            {
                ExplorerResponse txResponse = explorer.GetTransaction(item.txid);
                RawFormat        format     = RawFormat.Satoshi;
                var tx = Transaction.Parse(txResponse.data, format, Network.TestNet);
                transactions.Add(tx);
            }
            //Create send transaction.

            //get redeem script
            //var redeemScript = PayToMultiSigTemplate.Instance.GenerateScriptPubKey(2, pubKeys.ToArray());// multi.GetRedeemScript(2, keys.ToArray());

            Transaction received = transactions[0];
            ScriptCoin  coin     = received.Outputs.AsCoins().First().ToScriptCoin(pubKeyScript.WitHash.ScriptPubKey.Hash.ScriptPubKey);
            //create transaction:
            BitcoinAddress     destination = BitcoinAddress.Create("2N8hwP1WmJrFF5QWABn38y63uYLhnJYJYTF"); //the faucet return address
            TransactionBuilder builder     = new TransactionBuilder();

            builder.AddCoins(coin);
            builder.Send(destination, Money.Coins(1.299m));
            builder.SendFees(Money.Coins(0.001m));
            builder.SetChange(destination);
            //builder.
            var unsigned = builder.BuildTransaction(sign: false);

            var         signedA = builder.AddCoins(coin).AddKeys(keys[0].PrivateKey).SignTransaction(unsigned);
            Transaction signedB = builder.AddCoins(coin).AddKeys(keys[1].PrivateKey).SignTransaction(signedA);

            Transaction fullySigned = builder.AddCoins(coin).CombineSignatures(signedA, signedB);

            Console.WriteLine(fullySigned.ToHex());
            Console.ReadLine();
        }
예제 #15
0
        public static string ToJsonString(this Transaction transaction, RawFormat rawFormat, Network network = null)
        {
            var formatter = network.GetFormatter(rawFormat);

            return(ToJsonString(transaction, formatter));
        }
예제 #16
0
        /// <summary>
        /// Saves the currently loaded image to a uncompressed or paletted Blp file.
        /// </summary>
        /// <param name="filename">The path to the output file.</param>
        /// <param name="format">Raw format. See <see cref="RawFormat"/></param>
        /// <param name="resizeMethod">Method for possibly required resizing. See <see cref="FixSize"/></param>
        /// <param name="hasMipmaps">Specifies whether mipmaps are generated or not.</param>
        /// <param name="samplingFactor">(Optional) Sampling factor 1-30. Lower values stand for higher quality to the disadvantage of speed. Does not apply to Raw3 encoding.</param>
        /// <param name="samplingFactor">(Optional) Specifies whether or not to use dithering. Does not apply to Raw3 encoding.</param>
        public void Save(string filename, RawFormat format, ResizeMethod resizeMethod, bool hasMipmaps, byte samplingFactor = 10, bool dither = false)
        {
            if (bmp != null)
            {
                FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Write);

                using (BinaryWriter bw = new BinaryWriter(fs)) {
                    Blp2Header header = new Blp2Header(DataType.Uncompressed_DirectX, 0, AlphaDepth.Alpha8Bit, AlphaEncoding.RAW8BIT, (byte)(hasMipmaps ? 1 : 0), 0, 0);

                    List <Bitmap> bmps = new List <Bitmap>();
                    // Add resized image to the output
                    bmps.Add(FixSize(resizeMethod));

                    header.width  = (uint)bmps[0].Width;
                    header.height = (uint)bmps[0].Height;

                    // Add mipmaps
                    if (hasMipmaps)
                    {
                        bmps.AddRange(GenerateMipmaps(bmps[0]));
                    }

                    byte[] compImgData  = { };
                    byte[] colorPalette = new byte[256 * 4];

                    if (format == RawFormat.Raw1)
                    {
                        // Uncompressed paletted image
                        if (samplingFactor < 1 || samplingFactor > 30)
                        {
                            throw new ArgumentException("Sampling factor must be between 1 and 30.");
                        }
                        header.encoding = Encoding.RAW1;

                        // Quantize colors to a 256 color palette
                        NeuQuant quant = new NeuQuant(bmps[0]);
                        quant.Quantize();

                        // Set color palette
                        int j = 0;
                        foreach (Color c in quant.Palette)
                        {
                            colorPalette[j]     = c.R;
                            colorPalette[j + 1] = c.G;
                            colorPalette[j + 2] = c.B;
                            colorPalette[j + 3] = 0;
                            j += 4;
                        }

                        for (int i = 0; i < bmps.Count; i++)
                        {
                            // Copy raw image data to byte array
                            BitmapData bmpData = bmps[i].LockBits(new Rectangle(0, 0, bmps[i].Width, bmps[i].Height), ImageLockMode.ReadOnly, bmps[i].PixelFormat);
                            byte[]     imgData = new byte[bmpData.Stride * bmps[i].Height];
                            Marshal.Copy(bmpData.Scan0, imgData, 0, bmpData.Stride * bmps[i].Height);
                            bmps[i].UnlockBits(bmpData);

                            byte[] alphaData = new byte[imgData.Length / 4];

                            // Index image colors
                            int curOffset = compImgData.Length;
                            Array.Resize(ref compImgData, compImgData.Length + imgData.Length / 4);

                            for (j = 0; j < imgData.Length; j += 4)
                            {
                                Color c = Color.FromArgb(imgData[j], imgData[j + 1], imgData[j + 2]);
                                compImgData[curOffset + j / 4] = (byte)quant.GetPaletteIndex(c);

                                // Floyd-Steinberg dithering
                                if (dither)
                                {
                                    // Quantization error
                                    int diffErrR = c.R - quant.Palette[compImgData[curOffset + j / 4]].R;
                                    int diffErrG = c.G - quant.Palette[compImgData[curOffset + j / 4]].G;
                                    int diffErrB = c.B - quant.Palette[compImgData[curOffset + j / 4]].B;

                                    // Diffuse error, distribute  to neighbour bytes as follows:
                                    //  X      P     7/16
                                    // 3/16   5/16   1/16
                                    if (bmpData.Stride - (j % bmpData.Stride) >= 8)
                                    {
                                        imgData[j + 4] = truncateByte(imgData[j + 4], (diffErrR * 7) >> 4);
                                        imgData[j + 5] = truncateByte(imgData[j + 5], (diffErrG * 7) >> 4);
                                        imgData[j + 6] = truncateByte(imgData[j + 6], (diffErrB * 7) >> 4);
                                    }
                                    else if (j + bmpData.Stride < imgData.Length)
                                    {
                                        imgData[j + bmpData.Stride]     = truncateByte(imgData[j + bmpData.Stride], (diffErrR * 5) >> 4);
                                        imgData[j + bmpData.Stride + 1] = truncateByte(imgData[j + bmpData.Stride + 1], (diffErrG * 5) >> 4);
                                        imgData[j + bmpData.Stride + 2] = truncateByte(imgData[j + bmpData.Stride + 2], (diffErrB * 5) >> 4);

                                        if (bmpData.Stride - (j % bmpData.Stride) >= 8)
                                        {
                                            imgData[j + bmpData.Stride + 4] = truncateByte(imgData[j + bmpData.Stride + 4], (diffErrR * 1) >> 4);
                                            imgData[j + bmpData.Stride + 5] = truncateByte(imgData[j + bmpData.Stride + 5], (diffErrG * 1) >> 4);
                                            imgData[j + bmpData.Stride + 6] = truncateByte(imgData[j + bmpData.Stride + 6], (diffErrB * 1) >> 4);
                                        }
                                        else if (j % bmpData.Stride >= 4)
                                        {
                                            imgData[j + bmpData.Stride - 4] = truncateByte(imgData[j + bmpData.Stride - 4], (diffErrR * 3) >> 4);
                                            imgData[j + bmpData.Stride - 3] = truncateByte(imgData[j + bmpData.Stride - 3], (diffErrG * 3) >> 4);
                                            imgData[j + bmpData.Stride - 2] = truncateByte(imgData[j + bmpData.Stride - 2], (diffErrB * 3) >> 4);
                                        }
                                    }
                                }

                                // Fill alpha array (8 bit)
                                alphaData[j / 4] = imgData[j + 3];
                            }

                            // Append alpha channels
                            Array.Resize(ref compImgData, compImgData.Length + alphaData.Length);
                            alphaData.CopyTo(compImgData, compImgData.Length - alphaData.Length);

                            // Image data locations
                            header.offsets[i] = (uint)(curOffset + Marshal.SizeOf(typeof(Blp2Header)) + colorPalette.Length);
                            header.lengths[i] = (uint)(compImgData.Length - ((i > 0) ? header.offsets[i - 1] : 0));
                        }
                    }
                    else if (format == RawFormat.Raw3)
                    {
                        // Uncompressed 32bpp image
                        header.encoding = Encoding.RAW3;

                        for (int i = 0; i < bmps.Count; i++)
                        {
                            // Copy raw image data to byte array
                            BitmapData bmpData = bmps[i].LockBits(new Rectangle(0, 0, bmps[i].Width, bmps[i].Height), ImageLockMode.ReadOnly, bmps[i].PixelFormat);
                            byte[]     imgData = new byte[bmpData.Stride * bmps[i].Height];
                            Marshal.Copy(bmpData.Scan0, imgData, 0, bmpData.Stride * bmps[i].Height);
                            bmps[i].UnlockBits(bmpData);

                            Array.Resize(ref compImgData, compImgData.Length + imgData.Length);
                            imgData.CopyTo(compImgData, compImgData.Length - imgData.Length);

                            // Image data locations
                            header.offsets[i] = (i > 0) ? header.offsets[i - 1] + header.lengths[i - 1] : (uint)(Marshal.SizeOf(typeof(Blp2Header)) + colorPalette.Length);
                            header.lengths[i] = (uint)imgData.Length;
                        }
                    }

                    bw.Write(header.GetBytes());
                    bw.Write(colorPalette);
                    bw.Write(compImgData);
                }
            }
            else
            {
                throw new BlpConversionException("No image data to convert.");
            }
        }
예제 #17
0
 public string ToString(RawFormat rawFormat, Network network = null)
 {
     var formatter = GetFormatter(rawFormat, network);
     return ToString(formatter);
 }
예제 #18
0
파일: Blp2.cs 프로젝트: osler/WorldEditor
        /// <summary>
        /// Saves the currently loaded image to a uncompressed or paletted Blp file.
        /// </summary>
        /// <param name="filename">The path to the output file.</param>
        /// <param name="format">Raw format. See <see cref="RawFormat"/></param>
        /// <param name="resizeMethod">Method for possibly required resizing. See <see cref="FixSize"/></param>
        /// <param name="hasMipmaps">Specifies whether mipmaps are generated or not.</param>
        /// <param name="samplingFactor">(Optional) Sampling factor 1-30. Lower values stand for higher quality to the disadvantage of speed. Does not apply to Raw3 encoding.</param>
        /// <param name="samplingFactor">(Optional) Specifies whether or not to use dithering. Does not apply to Raw3 encoding.</param>
        public void Save(string filename, RawFormat format, ResizeMethod resizeMethod, bool hasMipmaps, byte samplingFactor = 10, bool dither = false)
        {
            if (bmp != null) {

                FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Write);

                using (BinaryWriter bw = new BinaryWriter(fs)) {

                    Blp2Header header = new Blp2Header(DataType.Uncompressed_DirectX, 0, AlphaDepth.Alpha8Bit, AlphaEncoding.RAW8BIT, (byte)(hasMipmaps ? 1 : 0), 0, 0);

                    List<Bitmap> bmps = new List<Bitmap>();
                    // Add resized image to the output
                    bmps.Add(FixSize(resizeMethod));

                    header.width = (uint)bmps[0].Width;
                    header.height = (uint)bmps[0].Height;

                    // Add mipmaps
                    if (hasMipmaps) bmps.AddRange(GenerateMipmaps(bmps[0]));

                    byte[] compImgData = { };
                    byte[] colorPalette = new byte[256 * 4];

                    if (format == RawFormat.Raw1) {
                        // Uncompressed paletted image
                        if (samplingFactor < 1 || samplingFactor > 30) throw new ArgumentException("Sampling factor must be between 1 and 30.");
                        header.encoding = Encoding.RAW1;

                        // Quantize colors to a 256 color palette
                        NeuQuant quant = new NeuQuant(bmps[0]);
                        quant.Quantize();

                        // Set color palette
                        int j = 0;
                        foreach (Color c in quant.Palette) {
                            colorPalette[j] = c.R;
                            colorPalette[j + 1] = c.G;
                            colorPalette[j + 2] = c.B;
                            colorPalette[j + 3] = 0;
                            j += 4;
                        }

                        for (int i = 0; i < bmps.Count; i++) {
                            // Copy raw image data to byte array
                            BitmapData bmpData = bmps[i].LockBits(new Rectangle(0, 0, bmps[i].Width, bmps[i].Height), ImageLockMode.ReadOnly, bmps[i].PixelFormat);
                            byte[] imgData = new byte[bmpData.Stride * bmps[i].Height];
                            Marshal.Copy(bmpData.Scan0, imgData, 0, bmpData.Stride * bmps[i].Height);
                            bmps[i].UnlockBits(bmpData);

                            byte[] alphaData = new byte[imgData.Length / 4];

                            // Index image colors
                            int curOffset = compImgData.Length;
                            Array.Resize(ref compImgData, compImgData.Length + imgData.Length / 4);

                            for (j = 0; j < imgData.Length; j += 4) {
                                Color c = Color.FromArgb(imgData[j], imgData[j + 1], imgData[j + 2]);
                                compImgData[curOffset + j / 4] = (byte)quant.GetPaletteIndex(c);

                                // Floyd-Steinberg dithering
                                if (dither) {
                                    // Quantization error
                                    int diffErrR = c.R - quant.Palette[compImgData[curOffset + j / 4]].R;
                                    int diffErrG = c.G - quant.Palette[compImgData[curOffset + j / 4]].G;
                                    int diffErrB = c.B - quant.Palette[compImgData[curOffset + j / 4]].B;

                                    // Diffuse error, distribute  to neighbour bytes as follows:
                                    //  X      P     7/16
                                    // 3/16   5/16   1/16
                                    if (bmpData.Stride - (j % bmpData.Stride) >= 8) {
                                        imgData[j + 4] = truncateByte(imgData[j + 4], (diffErrR * 7) >> 4);
                                        imgData[j + 5] = truncateByte(imgData[j + 5], (diffErrG * 7) >> 4);
                                        imgData[j + 6] = truncateByte(imgData[j + 6], (diffErrB * 7) >> 4);
                                    } else if (j + bmpData.Stride < imgData.Length) {
                                        imgData[j + bmpData.Stride] = truncateByte(imgData[j + bmpData.Stride], (diffErrR * 5) >> 4);
                                        imgData[j + bmpData.Stride + 1] = truncateByte(imgData[j + bmpData.Stride + 1], (diffErrG * 5) >> 4);
                                        imgData[j + bmpData.Stride + 2] = truncateByte(imgData[j + bmpData.Stride + 2], (diffErrB * 5) >> 4);

                                        if (bmpData.Stride - (j % bmpData.Stride) >= 8) {
                                            imgData[j + bmpData.Stride + 4] = truncateByte(imgData[j + bmpData.Stride + 4], (diffErrR * 1) >> 4);
                                            imgData[j + bmpData.Stride + 5] = truncateByte(imgData[j + bmpData.Stride + 5], (diffErrG * 1) >> 4);
                                            imgData[j + bmpData.Stride + 6] = truncateByte(imgData[j + bmpData.Stride + 6], (diffErrB * 1) >> 4);
                                        } else if (j % bmpData.Stride >= 4) {
                                            imgData[j + bmpData.Stride - 4] = truncateByte(imgData[j + bmpData.Stride - 4], (diffErrR * 3) >> 4);
                                            imgData[j + bmpData.Stride - 3] = truncateByte(imgData[j + bmpData.Stride - 3], (diffErrG * 3) >> 4);
                                            imgData[j + bmpData.Stride - 2] = truncateByte(imgData[j + bmpData.Stride - 2], (diffErrB * 3) >> 4);
                                        }
                                    }
                                }

                                // Fill alpha array (8 bit)
                                alphaData[j / 4] = imgData[j + 3];
                            }

                            // Append alpha channels
                            Array.Resize(ref compImgData, compImgData.Length + alphaData.Length);
                            alphaData.CopyTo(compImgData, compImgData.Length - alphaData.Length);

                            // Image data locations
                            header.offsets[i] = (uint)(curOffset + Marshal.SizeOf(typeof(Blp2Header)) + colorPalette.Length);
                            header.lengths[i] = (uint)(compImgData.Length - ((i > 0) ? header.offsets[i - 1] : 0));
                        }

                    } else if (format == RawFormat.Raw3) {

                        // Uncompressed 32bpp image
                        header.encoding = Encoding.RAW3;

                        for (int i = 0; i < bmps.Count; i++) {
                            // Copy raw image data to byte array
                            BitmapData bmpData = bmps[i].LockBits(new Rectangle(0, 0, bmps[i].Width, bmps[i].Height), ImageLockMode.ReadOnly, bmps[i].PixelFormat);
                            byte[] imgData = new byte[bmpData.Stride * bmps[i].Height];
                            Marshal.Copy(bmpData.Scan0, imgData, 0, bmpData.Stride * bmps[i].Height);
                            bmps[i].UnlockBits(bmpData);

                            Array.Resize(ref compImgData, compImgData.Length + imgData.Length);
                            imgData.CopyTo(compImgData, compImgData.Length - imgData.Length);

                            // Image data locations
                            header.offsets[i] = (i > 0) ? header.offsets[i - 1] + header.lengths[i - 1] : (uint)(Marshal.SizeOf(typeof(Blp2Header)) + colorPalette.Length);
                            header.lengths[i] = (uint)imgData.Length;
                        }

                    }

                    bw.Write(header.GetBytes());
                    bw.Write(colorPalette);
                    bw.Write(compImgData);

                }

            } else {
                throw new BlpConversionException("No image data to convert.");
            }
        }