SHARE
TWEET

BMPLoader

Bunny83 Feb 5th, 2017 (edited) 1,099 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #region License and Information
  2. /*****
  3. *
  4. * BMPLoader.cs
  5. *
  6. * This is a simple implementation of a BMP file loader for Unity3D.
  7. * Formats it should support are:
  8. *  - 1 bit monochrome indexed
  9. *  - 2-8 bit indexed
  10. *  - 16 / 24 / 32 bit color (including "BI_BITFIELDS")
  11. *  - RLE-4 and RLE-8 support has been added.
  12. *
  13. * Unless the type is "BI_ALPHABITFIELDS" the loader does not interpret alpha
  14. * values by default, however you can set the "ReadPaletteAlpha" setting to
  15. * true to interpret the 4th (usually "00") value as alpha for indexed images.
  16. * You can also set "ForceAlphaReadWhenPossible" to true so it will interpret
  17. * the "left over" bits as alpha if there are any. It will also force to read
  18. * alpha from a palette if it's an indexed image, just like "ReadPaletteAlpha".
  19. *
  20. * It's not tested well to the bone, so there might be some errors somewhere.
  21. * However I tested it with 4 different images created with MS Paint
  22. * (1bit, 4bit, 8bit, 24bit) as those are the only formats supported.
  23. *
  24. * 2017.02.05 - first version
  25. * 2017.03.06 - Added RLE4 / RLE8 support
  26. *
  27. * Copyright (c) 2017 Markus Göbel (Bunny83)
  28. *
  29. * Permission is hereby granted, free of charge, to any person obtaining a copy
  30. * of this software and associated documentation files (the "Software"), to
  31. * deal in the Software without restriction, including without limitation the
  32. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  33. * sell copies of the Software, and to permit persons to whom the Software is
  34. * furnished to do so, subject to the following conditions:
  35. *
  36. * The above copyright notice and this permission notice shall be included in
  37. * all copies or substantial portions of the Software.
  38. *
  39. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  40. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  41. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  42. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  43. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  44. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  45. * IN THE SOFTWARE.
  46. *
  47. *****/
  48. #endregion License and Information
  49. using UnityEngine;
  50. using System.Collections;
  51. using System.Collections.Generic;
  52. using System.IO;
  53. using System;
  54.  
  55. namespace B83.Image.BMP
  56. {
  57.     public enum BMPComressionMode : int
  58.     {
  59.         BI_RGB = 0x00,
  60.         BI_RLE8 = 0x01,
  61.         BI_RLE4 = 0x02,
  62.         BI_BITFIELDS = 0x03,
  63.         BI_JPEG = 0x04,
  64.         BI_PNG = 0x05,
  65.         BI_ALPHABITFIELDS = 0x06,
  66.  
  67.         BI_CMYK = 0x0B,
  68.         BI_CMYKRLE8 = 0x0C,
  69.         BI_CMYKRLE4 = 0x0D,
  70.  
  71.     }
  72.     public struct BMPFileHeader
  73.     {
  74.         public ushort magic; // "BM"
  75.         public uint filesize;
  76.         public uint reserved;
  77.         public uint offset;
  78.     }
  79.     public struct BitmapInfoHeader
  80.     {
  81.         public uint size;
  82.         public int width;
  83.         public int height;
  84.         public ushort nColorPlanes; // always 1
  85.         public ushort nBitsPerPixel; // [1,4,8,16,24,32]
  86.         public BMPComressionMode compressionMethod;
  87.         public uint rawImageSize; // can be "0"
  88.         public int xPPM;
  89.         public int yPPM;
  90.         public uint nPaletteColors;
  91.         public uint nImportantColors;
  92.  
  93.         public int absWidth { get { return Mathf.Abs(width); } }
  94.         public int absHeight { get { return Mathf.Abs(height); } }
  95.  
  96.     }
  97.  
  98.     public class BMPImage
  99.     {
  100.         public BMPFileHeader header;
  101.         public BitmapInfoHeader info;
  102.         public uint rMask = 0x00FF0000;
  103.         public uint gMask = 0x0000FF00;
  104.         public uint bMask = 0x000000FF;
  105.         public uint aMask = 0x00000000;
  106.         public List<Color32> palette;
  107.         public Color32[] imageData;
  108.         public Texture2D ToTexture2D()
  109.         {
  110.             var tex = new Texture2D(info.absWidth, info.absHeight);
  111.             tex.SetPixels32(imageData);
  112.             tex.Apply();
  113.             return tex;
  114.         }
  115.     }
  116.  
  117.  
  118.     public class BMPLoader
  119.     {
  120.         const ushort MAGIC = 0x4D42; // "BM" little endian
  121.         public bool ReadPaletteAlpha = false;
  122.         public bool ForceAlphaReadWhenPossible = false;
  123.  
  124.         public BMPImage LoadBMP(string aFileName)
  125.         {
  126.             using (var file = File.OpenRead(aFileName))
  127.                 return LoadBMP(file);
  128.         }
  129.         public BMPImage LoadBMP(byte[] aData)
  130.         {
  131.             using (var stream = new MemoryStream(aData))
  132.                 return LoadBMP(stream);
  133.         }
  134.  
  135.         public BMPImage LoadBMP(Stream aData)
  136.         {
  137.             using (var reader = new BinaryReader(aData))
  138.                 return LoadBMP(reader);
  139.  
  140.         }
  141.         public BMPImage LoadBMP(BinaryReader aReader)
  142.         {
  143.             BMPImage bmp = new BMPImage();
  144.             if (!ReadFileHeader(aReader, ref bmp.header))
  145.             {
  146.                 Debug.LogError("Not a BMP file");
  147.                 return null;
  148.             }
  149.             if (!ReadInfoHeader(aReader, ref bmp.info))
  150.             {
  151.                 Debug.LogError("Unsupported header format");
  152.                 return null;
  153.             }
  154.             if (   bmp.info.compressionMethod != BMPComressionMode.BI_RGB
  155.                 && bmp.info.compressionMethod != BMPComressionMode.BI_BITFIELDS
  156.                 && bmp.info.compressionMethod != BMPComressionMode.BI_ALPHABITFIELDS
  157.                 && bmp.info.compressionMethod != BMPComressionMode.BI_RLE4
  158.                 && bmp.info.compressionMethod != BMPComressionMode.BI_RLE8
  159.                 )
  160.             {
  161.                 Debug.LogError("Unsupported image format: "+ bmp.info.compressionMethod);
  162.                 return null;
  163.             }
  164.             long offset = 14 + bmp.info.size;
  165.             aReader.BaseStream.Seek(offset, SeekOrigin.Begin);
  166.             if (bmp.info.nBitsPerPixel < 24)
  167.             {
  168.                 bmp.rMask = 0x00007C00;
  169.                 bmp.gMask = 0x000003E0;
  170.                 bmp.bMask = 0x0000001F;
  171.             }
  172.  
  173.             if (bmp.info.compressionMethod == BMPComressionMode.BI_BITFIELDS || bmp.info.compressionMethod == BMPComressionMode.BI_ALPHABITFIELDS)
  174.             {
  175.                 bmp.rMask = aReader.ReadUInt32();
  176.                 bmp.gMask = aReader.ReadUInt32();
  177.                 bmp.bMask = aReader.ReadUInt32();
  178.             }
  179.             if (ForceAlphaReadWhenPossible)
  180.                 bmp.aMask = GetMask(bmp.info.nBitsPerPixel) ^ (bmp.rMask | bmp.gMask | bmp.bMask);
  181.  
  182.             if (bmp.info.compressionMethod == BMPComressionMode.BI_ALPHABITFIELDS)
  183.                 bmp.aMask = aReader.ReadUInt32();
  184.  
  185.             if (bmp.info.nPaletteColors > 0 || bmp.info.nBitsPerPixel <= 8)
  186.                 bmp.palette = ReadPalette(aReader, bmp, ReadPaletteAlpha || ForceAlphaReadWhenPossible);
  187.  
  188.  
  189.             aReader.BaseStream.Seek(bmp.header.offset, SeekOrigin.Begin);
  190.             bool uncompressed = bmp.info.compressionMethod == BMPComressionMode.BI_RGB ||
  191.                 bmp.info.compressionMethod == BMPComressionMode.BI_BITFIELDS ||
  192.                 bmp.info.compressionMethod == BMPComressionMode.BI_ALPHABITFIELDS;
  193.             if (bmp.info.nBitsPerPixel == 32 && uncompressed)
  194.                 Read32BitImage(aReader, bmp);
  195.             else if (bmp.info.nBitsPerPixel == 24 && uncompressed)
  196.                 Read24BitImage(aReader, bmp);
  197.             else if (bmp.info.nBitsPerPixel == 16 && uncompressed)
  198.                 Read16BitImage(aReader, bmp);
  199.             else if (bmp.info.compressionMethod == BMPComressionMode.BI_RLE4 && bmp.info.nBitsPerPixel == 4 && bmp.palette != null)
  200.                 ReadIndexedImageRLE4(aReader, bmp);
  201.             else if (bmp.info.compressionMethod == BMPComressionMode.BI_RLE8 && bmp.info.nBitsPerPixel == 8 && bmp.palette != null)
  202.                 ReadIndexedImageRLE8(aReader, bmp);
  203.             else if (uncompressed && bmp.info.nBitsPerPixel <= 8 && bmp.palette != null)
  204.                 ReadIndexedImage(aReader, bmp);
  205.             else
  206.             {
  207.                 Debug.LogError("Unsupported file format: " + bmp.info.compressionMethod + " BPP: " + bmp.info.nBitsPerPixel);
  208.                 return null;
  209.             }
  210.             return bmp;
  211.         }
  212.  
  213.  
  214.         private static void Read32BitImage(BinaryReader aReader, BMPImage bmp)
  215.         {
  216.             int w = Mathf.Abs(bmp.info.width);
  217.             int h = Mathf.Abs(bmp.info.height);
  218.             Color32[] data = bmp.imageData = new Color32[w * h];
  219.             if (aReader.BaseStream.Position + w*h*4 > aReader.BaseStream.Length)
  220.             {
  221.                 Debug.LogError("Unexpected end of file.");
  222.                 return;
  223.             }
  224.             int shiftR = GetShiftCount(bmp.rMask);
  225.             int shiftG = GetShiftCount(bmp.gMask);
  226.             int shiftB = GetShiftCount(bmp.bMask);
  227.             int shiftA = GetShiftCount(bmp.aMask);
  228.             byte a = 255;
  229.             for (int i = 0; i < data.Length; i++)
  230.             {
  231.                 uint v = aReader.ReadUInt32();
  232.                 byte r = (byte)((v & bmp.rMask) >> shiftR);
  233.                 byte g = (byte)((v & bmp.gMask) >> shiftG);
  234.                 byte b = (byte)((v & bmp.bMask) >> shiftB);
  235.                 if (bmp.bMask != 0)
  236.                     a = (byte)((v & bmp.aMask) >> shiftA);
  237.                 data[i] = new Color32(r,g,b,a);
  238.             }
  239.         }
  240.  
  241.  
  242.         private static void Read24BitImage(BinaryReader aReader, BMPImage bmp)
  243.         {
  244.             int w = Mathf.Abs(bmp.info.width);
  245.             int h = Mathf.Abs(bmp.info.height);
  246.             int rowLength = ((24 * w + 31) / 32) * 4;
  247.             int count = rowLength * h;
  248.             int pad = rowLength - w * 3;
  249.             Color32[] data = bmp.imageData = new Color32[w * h];
  250.             if (aReader.BaseStream.Position + count > aReader.BaseStream.Length)
  251.             {
  252.                 Debug.LogError("Unexpected end of file. (Have "+ (aReader.BaseStream.Position + count)+" bytes, expected " + aReader.BaseStream.Length+" bytes)");
  253.                 return;
  254.             }
  255.             int shiftR = GetShiftCount(bmp.rMask);
  256.             int shiftG = GetShiftCount(bmp.gMask);
  257.             int shiftB = GetShiftCount(bmp.bMask);
  258.             for (int y = 0; y < h; y++)
  259.             {
  260.                 for(int x = 0; x < w; x++)
  261.                 {
  262.                     uint v = aReader.ReadByte() | ((uint)aReader.ReadByte()<<8) | ((uint)aReader.ReadByte()<<16);
  263.                     byte r = (byte)((v & bmp.rMask) >> shiftR);
  264.                     byte g = (byte)((v & bmp.gMask) >> shiftG);
  265.                     byte b = (byte)((v & bmp.bMask) >> shiftB);
  266.                     data[x+y*w] = new Color32(r, g, b, 255);
  267.                 }
  268.                 for (int i = 0; i < pad; i++)
  269.                     aReader.ReadByte();
  270.             }
  271.         }
  272.  
  273.         private static void Read16BitImage(BinaryReader aReader, BMPImage bmp)
  274.         {
  275.             int w = Mathf.Abs(bmp.info.width);
  276.             int h = Mathf.Abs(bmp.info.height);
  277.             int rowLength = ((16 * w + 31) / 32) * 4;
  278.             int count = rowLength * h;
  279.             int pad = rowLength - w * 2;
  280.             Color32[] data = bmp.imageData = new Color32[w * h];
  281.             if (aReader.BaseStream.Position + count > aReader.BaseStream.Length)
  282.             {
  283.                 Debug.LogError("Unexpected end of file. (Have " + (aReader.BaseStream.Position + count) + " bytes, expected " + aReader.BaseStream.Length + " bytes)");
  284.                 return;
  285.             }
  286.             int shiftR = GetShiftCount(bmp.rMask);
  287.             int shiftG = GetShiftCount(bmp.gMask);
  288.             int shiftB = GetShiftCount(bmp.bMask);
  289.             int shiftA = GetShiftCount(bmp.aMask);
  290.             byte a = 255;
  291.             for (int y = 0; y < h; y++)
  292.             {
  293.                 for (int x = 0; x < w; x++)
  294.                 {
  295.                     uint v = aReader.ReadByte() | ((uint)aReader.ReadByte() << 8);
  296.                     byte r = (byte)((v & bmp.rMask) >> shiftR);
  297.                     byte g = (byte)((v & bmp.gMask) >> shiftG);
  298.                     byte b = (byte)((v & bmp.bMask) >> shiftB);
  299.                     if (bmp.aMask != 0)
  300.                         a = (byte)((v & bmp.aMask) >> shiftA);
  301.                     data[x + y * w] = new Color32(r, g, b, a);
  302.                 }
  303.                 for (int i = 0; i < pad; i++)
  304.                     aReader.ReadByte();
  305.             }
  306.         }
  307.  
  308.         private static void ReadIndexedImage(BinaryReader aReader, BMPImage bmp)
  309.         {
  310.             int w = Mathf.Abs(bmp.info.width);
  311.             int h = Mathf.Abs(bmp.info.height);
  312.             int bitCount = bmp.info.nBitsPerPixel;
  313.             int rowLength = ((bitCount * w + 31) / 32) * 4;
  314.             int count = rowLength * h;
  315.             int pad = rowLength - (w * bitCount + 7)/8;
  316.             Color32[] data = bmp.imageData = new Color32[w * h];
  317.             if (aReader.BaseStream.Position + count > aReader.BaseStream.Length)
  318.             {
  319.                 Debug.LogError("Unexpected end of file. (Have " + (aReader.BaseStream.Position + count) + " bytes, expected " + aReader.BaseStream.Length + " bytes)");
  320.                 return;
  321.             }
  322.             BitStreamReader bitReader = new BitStreamReader(aReader);
  323.             for (int y = 0; y < h; y++)
  324.             {
  325.                 for (int x = 0; x < w; x++)
  326.                 {
  327.                     int v = (int)bitReader.ReadBits(bitCount);
  328.                     if (v >= bmp.palette.Count)
  329.                     {
  330.                         Debug.LogError("Indexed bitmap has indices greater than it's color palette");
  331.                         return;
  332.                     }
  333.                     data[x + y * w] = bmp.palette[v];
  334.                 }
  335.                 bitReader.Flush();
  336.                 for (int i = 0; i < pad; i++)
  337.                     aReader.ReadByte();
  338.             }
  339.         }
  340.         private static void ReadIndexedImageRLE4(BinaryReader aReader, BMPImage bmp)
  341.         {
  342.             int w = Mathf.Abs(bmp.info.width);
  343.             int h = Mathf.Abs(bmp.info.height);
  344.             Color32[] data = bmp.imageData = new Color32[w * h];
  345.             int x = 0;
  346.             int y = 0;
  347.             int yOffset = 0;
  348.             while (aReader.BaseStream.Position < aReader.BaseStream.Length-1)
  349.             {
  350.                 int count = (int)aReader.ReadByte();
  351.                 byte d = aReader.ReadByte();
  352.                 if (count > 0)
  353.                 {  
  354.                     for (int i = (count/2); i > 0; i--)
  355.                     {
  356.                         data[x++ + yOffset] = bmp.palette[(d>>4)&0x0F];
  357.                         data[x++ + yOffset] = bmp.palette[d & 0x0F];
  358.                     }
  359.                     if ((count & 0x01) > 0)
  360.                     {
  361.                         data[x++ + yOffset] = bmp.palette[(d >> 4) & 0x0F];
  362.                     }
  363.                 }
  364.                 else
  365.                 {
  366.                     if (d == 0)
  367.                     {
  368.                         x = 0;
  369.                         y += 1;
  370.                         yOffset = y * w;
  371.                     }
  372.                     else if (d == 1)
  373.                     {
  374.                         break;
  375.                     }
  376.                     else if (d == 2)
  377.                     {
  378.                         x += aReader.ReadByte();
  379.                         y += aReader.ReadByte();
  380.                         yOffset = y * w;
  381.                     }
  382.                     else
  383.                     {
  384.                         for(int i = (d / 2); i > 0; i--)
  385.                         {
  386.                             byte d2 = aReader.ReadByte();
  387.                             data[x++ + yOffset] = bmp.palette[(d2 >> 4) & 0x0F];
  388.                             data[x++ + yOffset] = bmp.palette[d2 & 0x0F];
  389.                         }
  390.                         if ((d & 0x01) > 0)
  391.                         {
  392.                             data[x++ + yOffset] = bmp.palette[(aReader.ReadByte() >> 4) & 0x0F];
  393.                         }
  394.                         if ((((d - 1) / 2) & 1) == 0)
  395.                         {
  396.                             aReader.ReadByte(); // padding (word alignment)
  397.                         }
  398.                     }
  399.                 }
  400.             }
  401.         }
  402.         private static void ReadIndexedImageRLE8(BinaryReader aReader, BMPImage bmp)
  403.         {
  404.             int w = Mathf.Abs(bmp.info.width);
  405.             int h = Mathf.Abs(bmp.info.height);
  406.             Color32[] data = bmp.imageData = new Color32[w * h];
  407.             int x = 0;
  408.             int y = 0;
  409.             int yOffset = 0;
  410.             while (aReader.BaseStream.Position < aReader.BaseStream.Length - 1)
  411.             {
  412.                 int count = (int)aReader.ReadByte();
  413.                 byte d = aReader.ReadByte();
  414.                 if (count > 0)
  415.                 {
  416.                     for (int i = count; i > 0; i--)
  417.                     {
  418.                         data[x++ + yOffset] = bmp.palette[d ];
  419.                     }
  420.                 }
  421.                 else
  422.                 {
  423.                     if (d == 0)
  424.                     {
  425.                         x = 0;
  426.                         y += 1;
  427.                         yOffset = y * w;
  428.                     }
  429.                     else if (d == 1)
  430.                     {
  431.                         break;
  432.                     }
  433.                     else if (d == 2)
  434.                     {
  435.                         x += aReader.ReadByte();
  436.                         y += aReader.ReadByte();
  437.                         yOffset = y * w;
  438.                     }
  439.                     else
  440.                     {
  441.                         for (int i = d; i > 0; i--)
  442.                         {
  443.                             data[x++ + yOffset] = bmp.palette[aReader.ReadByte()];
  444.                         }
  445.                         if ((d & 0x01) > 0)
  446.                         {
  447.                             aReader.ReadByte(); // padding (word alignment)
  448.                         }
  449.                     }
  450.                 }
  451.             }
  452.         }
  453.         private static int GetShiftCount(uint mask)
  454.         {
  455.             for(int i = 0; i < 32; i++)
  456.             {
  457.                 if ((mask & 0x01) > 0)
  458.                     return i;
  459.                 mask >>= 1;
  460.             }
  461.             return -1;
  462.         }
  463.         private static uint GetMask(int bitCount)
  464.         {
  465.             uint mask = 0;
  466.             for(int i = 0; i < bitCount; i++)
  467.             {
  468.                 mask <<= 1;
  469.                 mask |= 0x01;
  470.             }
  471.             return mask;
  472.         }
  473.         private static bool ReadFileHeader(BinaryReader aReader, ref BMPFileHeader aFileHeader)
  474.         {
  475.             aFileHeader.magic = aReader.ReadUInt16();
  476.             if (aFileHeader.magic != MAGIC)
  477.                 return false;
  478.             aFileHeader.filesize = aReader.ReadUInt32();
  479.             aFileHeader.reserved = aReader.ReadUInt32();
  480.             aFileHeader.offset = aReader.ReadUInt32();
  481.             return true;
  482.         }
  483.         private static bool ReadInfoHeader(BinaryReader aReader, ref BitmapInfoHeader aHeader)
  484.         {
  485.             aHeader.size = aReader.ReadUInt32();
  486.             if (aHeader.size < 40)
  487.                 return false;
  488.             aHeader.width = aReader.ReadInt32();
  489.             aHeader.height = aReader.ReadInt32();
  490.             aHeader.nColorPlanes = aReader.ReadUInt16();
  491.             aHeader.nBitsPerPixel = aReader.ReadUInt16();
  492.             aHeader.compressionMethod = (BMPComressionMode)aReader.ReadInt32();
  493.             aHeader.rawImageSize = aReader.ReadUInt32();
  494.             aHeader.xPPM = aReader.ReadInt32();
  495.             aHeader.yPPM = aReader.ReadInt32();
  496.             aHeader.nPaletteColors = aReader.ReadUInt32();
  497.             aHeader.nImportantColors = aReader.ReadUInt32();
  498.             int pad = (int)aHeader.size - 40;
  499.             if (pad > 0)
  500.                 aReader.ReadBytes(pad);
  501.             return true;
  502.         }
  503.         public static List<Color32> ReadPalette(BinaryReader aReader, BMPImage aBmp, bool aReadAlpha)
  504.         {
  505.             uint count = aBmp.info.nPaletteColors;
  506.             if (count == 0u)
  507.                 count = 1u << aBmp.info.nBitsPerPixel;
  508.             var palette = new List<Color32>((int)count);
  509.             for(int i = 0; i < count; i++)
  510.             {
  511.                 byte b = aReader.ReadByte();
  512.                 byte g = aReader.ReadByte();
  513.                 byte r = aReader.ReadByte();
  514.                 byte a = aReader.ReadByte();
  515.                 if (!aReadAlpha)
  516.                     a = 255;
  517.                 palette.Add(new Color32(r,g,b,a));
  518.             }
  519.             return palette;
  520.         }
  521.  
  522.     }
  523.     public class BitStreamReader
  524.     {
  525.         BinaryReader m_Reader;
  526.         byte m_Data = 0;
  527.         int m_Bits = 0;
  528.        
  529.         public BitStreamReader(BinaryReader aReader)
  530.         {
  531.             m_Reader = aReader;
  532.         }
  533.         public BitStreamReader(Stream aStream) : this(new BinaryReader(aStream)) { }
  534.  
  535.         public byte ReadBit()
  536.         {
  537.             if (m_Bits <= 0)
  538.             {
  539.                 m_Data = m_Reader.ReadByte();
  540.                 m_Bits = 8;
  541.             }
  542.             return (byte)((m_Data >> --m_Bits) & 1);
  543.         }
  544.  
  545.         public ulong ReadBits(int aCount)
  546.         {
  547.             ulong val = 0UL;
  548.             if (aCount <= 0 || aCount > 32)
  549.                 throw new System.ArgumentOutOfRangeException("aCount", "aCount must be between 1 and 32 inclusive");
  550.             for (int i = aCount-1; i>=0; i--)
  551.                 val |= ((ulong)ReadBit() << i);
  552.             return val;
  553.         }
  554.         public void Flush()
  555.         {
  556.             m_Data = 0;
  557.             m_Bits = 0;
  558.         }
  559.     }
  560. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top