Ejemplo n.º 1
0
 /// <summary>Prepares the resource for writing and updates <see cref="Resource.RawData"/></summary>
 public override void EncodeResource()
 {
     System.Diagnostics.Debug.WriteLine("bit width: " + _bitsPerScanLine + ", height: " + _height + "num glyphs: " + _glyphs.Length);
     byte[] raw = new byte[12 + (_bitsPerScanLine / 8 * _height + 1) * _glyphs.Length];
     ArrayFunctions.WriteToArray(_startingChar, raw, 0);
     ArrayFunctions.WriteToArray((short)_glyphs.Length, raw, 2);
     ArrayFunctions.WriteToArray(_bitsPerScanLine, raw, 4);
     ArrayFunctions.WriteToArray(_height, raw, 6);
     ArrayFunctions.WriteToArray(BaseLine, raw, 8);
     for (int i = 0; i < _glyphs.Length; i++)
     {
         raw[12 + i] = (byte)_glyphs[i].Width;
     }
     for (int i = 0, offset = 12 + _glyphs.Length; i < _glyphs.Length; i++)
     {
         BitmapData bd1  = GraphicsFunctions.GetBitmapData(_glyphs[i]);
         byte[]     pix1 = new byte[bd1.Stride * bd1.Height];
         GraphicsFunctions.CopyImageToBytes(bd1, pix1);
         // BitmapData.Stride rounds up to 4, so we have to trim off the excess bytes
         byte[] trimmed = new byte[_height * _bitsPerScanLine / 8];
         for (int y = 0; y < _height; y++)
         {
             for (int x = 0; x < (_bitsPerScanLine / 8); x++)
             {
                 trimmed[x + y * (_bitsPerScanLine / 8)] = pix1[x + y * bd1.Stride];
             }
         }
         System.Diagnostics.Debug.WriteLine("pix1.Length: " + pix1.Length + ", trimmed.Length: " + trimmed.Length + ", offset: " + offset);
         ArrayFunctions.WriteToArray(trimmed, raw, ref offset);
         _glyphs[i].UnlockBits(bd1);
     }
     _rawData = raw;
 }
Ejemplo n.º 2
0
        /// <summary>Processes raw data to populate the resource</summary>
        /// <param name="raw">Raw byte data</param>
        /// <param name="containsHeader">Whether or not <i>raw</i> contains the resource Header information</param>
        /// <exception cref="ArgumentException">Header-defined <see cref="Type"/> is not <see cref="Resource.ResourceType.Font"/></exception>
        public override void DecodeResource(byte[] raw, bool containsHeader)
        {
            _decodeResource(raw, containsHeader);
            if (_type != ResourceType.Font)
            {
                throw new ArgumentException("Raw header is not for a Font resource");
            }
            int offset = 0;

            _startingChar    = BitConverter.ToInt16(_rawData, offset);
            _glyphs          = new Bitmap[BitConverter.ToInt16(_rawData, offset + 2)];
            _bitsPerScanLine = BitConverter.ToInt16(_rawData, offset + 4);
            _height          = BitConverter.ToInt16(_rawData, offset + 6);
            _baseLine        = BitConverter.ToInt16(_rawData, offset + 8);
            offset          += 12;
            for (int i = 0; i < _glyphs.Length; i++)
            {
                _glyphs[i] = new Bitmap(_rawData[offset++], _height, PixelFormat.Format1bppIndexed);
            }
            for (int i = 0; i < _glyphs.Length; i++)
            {
                BitmapData bd1  = GraphicsFunctions.GetBitmapData(_glyphs[i]);
                byte[]     pix1 = new byte[bd1.Stride * bd1.Height];
                for (int y = 0; y < _height; y++)
                {
                    for (int s = 0; s < (_bitsPerScanLine / 8); s++)
                    {
                        pix1[y * bd1.Stride + s] = _rawData[offset++];
                    }
                }
                GraphicsFunctions.CopyBytesToImage(pix1, bd1);
                _glyphs[i].UnlockBits(bd1);
            }
            _glyphIndexer = new GlyphIndexer(this);
        }
Ejemplo n.º 3
0
        /// <summary>Sets the transparency mask</summary>
        /// <param name="image">New image mask. Converts to <see cref="PixelFormat.Format1bppIndexed"/>, must be <b>640x480</b> or smaller</param>
        /// <param name="transparentColor">The Color to be used as transparent</param>
        /// <exception cref="ArgumentException"><i>image</i> contains a consecutive length of 256 or 512 pixels not located at the end of the image</exception>
        /// <exception cref="Idmr.Common.BoundaryException"><i>image</i> exceeds maximum allowable dimensions</exception>
        /// <remarks>The MASK format cannot handle the 256 or 512px lengths in the middle of the image. It can however do that at the end of the image, via "throw away" pixels.<br/>
        /// Maximum size is defined by <see cref="Panl.MaximumWidth"/> and <see cref="Panl.MaximumHeight"/></remarks>
        public void SetMask(Bitmap image, Color transparentColor)
        {
            string message = "Image contains line length of 256 or 512 pixels";

            if (image.Width > Panl.MaximumWidth || image.Height > Panl.MaximumHeight)
            {
                throw new Common.BoundaryException("image.Size", Panl.MaximumWidth + "x" + Panl.MaximumHeight);
            }
            Bitmap temp = _image;

            try
            {
                // due to special length checks, can't use Common.Functions.ConvertTo1bpp
                image  = new Bitmap(image);                     // force to 32bbpRGB
                _image = new Bitmap(image.Width, image.Height, PixelFormat.Format1bppIndexed);
                // import image data
                BitmapData bd32  = GraphicsFunctions.GetBitmapData(image);
                byte[]     pix32 = new byte[bd32.Stride * bd32.Height];
                GraphicsFunctions.CopyImageToBytes(bd32, pix32);
                BitmapData bd1  = GraphicsFunctions.GetBitmapData(_image);
                byte[]     pix1 = new byte[bd1.Stride * bd1.Height];
                for (int y = 0; y < image.Height; y++)
                {
                    for (int x = 0, numBlack = 0, numWhite = 0, pos32 = y * bd32.Stride, pos1 = y * bd1.Stride; x < bd32.Width; x++)
                    {
                        if (pix32[pos32 + x * 4] != transparentColor.B || pix32[pos32 + x * 4 + 1] != transparentColor.G || pix32[pos32 + x * 4 + 2] != transparentColor.R)
                        {                               // white
                            pix1[pos1 + x / 8] |= (byte)(0x80 >> (x & 7));
                            // throw if 256px detected, and not end of row (which format can handle)
                            if ((numBlack % 256) == 0 && x != image.Width - 1)
                            {
                                throw new ArgumentException(message, "image");
                            }
                            numBlack = 0;
                            numWhite++;
                        }
                        else
                        {                               // black
                            if ((numWhite % 256) == 0 && x != image.Width - 1)
                            {
                                throw new ArgumentException(message, "image");
                            }
                            numBlack++;
                            numWhite = 0;
                        }
                    }
                }
                GraphicsFunctions.CopyBytesToImage(pix1, bd1);
                image.UnlockBits(bd32);
                _image.UnlockBits(bd1);
                Width      = (short)_image.Width;
                Height     = (short)_image.Height;
                _isModifed = true;
            }
            catch (Exception x) { _image = temp; throw x; }
        }
Ejemplo n.º 4
0
 /// <summary>Preparess the resource for writing and updates <see cref="Resource.RawData"/></summary>
 public override void EncodeResource()
 {
     //TODO: test Panl.Write()
     byte[] raw = null;
     for (int i = 0; i < _images.Length; i++)
     {
         BitmapData bd      = GraphicsFunctions.GetBitmapData(_images[i]);
         byte[]     pixels  = new byte[bd.Stride * bd.Height];
         byte[]     tempRaw = new byte[pixels.Length];
         int        offset  = 0;
         GraphicsFunctions.CopyImageToBytes(bd, pixels);                 // from 0,0, index values
         int k;
         for (int y = 0; y < _images[i].Height; y++)
         {
             for (int x = 0, pos = y * bd.Stride; x < _images[i].Width;)
             {
                 for (k = x + 1; k < _images[i].Width; k++)
                 {
                     if (pixels[pos + x] != pixels[pos + k])
                     {
                         break;                                                                  // determine length of single color = k
                     }
                 }
                 if ((k - x) < 5 && pixels[pos + x] < 0x3F)
                 {
                     // TYPE_3 : 1-4 px, can't use 3F since shift goes to FC-FF
                     byte b = (byte)(pixels[pos + x] << 2 + (k - x - 1));
                     tempRaw[offset++] = b;
                 }
                 else
                 {
                     // TYPE_1 : only going to use FD, since I see no reason to use FC at all
                     tempRaw[offset++] = 0xFD;
                     tempRaw[offset++] = (byte)(k - x - 1);
                     tempRaw[offset++] = pixels[pos + x];
                 }
                 x = k;
             }
             tempRaw[offset++] = 0xFE;
         }
         tempRaw[offset++] = 0xFF;
         _images[i].UnlockBits(bd);
         byte[] temp = raw;
         raw = new byte[(temp == null ? 0 : temp.Length) + offset];
         if (temp != null)
         {
             ArrayFunctions.WriteToArray(temp, raw, 0);
         }
         Buffer.BlockCopy(tempRaw, 0, raw, raw.Length - offset, offset);
     }
     _rawData = raw;
 }
Ejemplo n.º 5
0
        /// <summary>Take the original image from the craft image strip and adds the RGB values from the craft IFF</summary>
        /// <param name="craftImage">The greyscale craft image</param>
        /// <param name="iff">An array containing the RGB values as per the craft IFF</param>
        /// <returns>Colorized craft image according to IFF</returns>
        Bitmap mask(Bitmap craftImage, byte[] iff)
        {
            // craftImage comes in as 32bppRGB, but we force the image into 24bppRGB with LockBits
            BitmapData bmData = GraphicsFunctions.GetBitmapData(craftImage, PixelFormat.Format24bppRgb);

            byte[] pix = new byte[bmData.Stride * bmData.Height];
            GraphicsFunctions.CopyImageToBytes(bmData, pix);
            for (int y = 0; y < craftImage.Height; y++)
            {
                for (int x = 0, pos = bmData.Stride * y; x < craftImage.Width; x++)
                {
                    // stupid thing returns BGR instead of RGB
                    pix[pos + x * 3]     = (byte)(pix[pos + x * 3] * iff[2] / 255);                     // get intensity, apply to IFF mask
                    pix[pos + x * 3 + 1] = (byte)(pix[pos + x * 3 + 1] * iff[1] / 255);
                    pix[pos + x * 3 + 2] = (byte)(pix[pos + x * 3 + 2] * iff[0] / 255);
                }
            }
            GraphicsFunctions.CopyBytesToImage(pix, bmData);
            craftImage.UnlockBits(bmData);
            craftImage.MakeTransparent(Color.Black);
            return(craftImage);
        }
Ejemplo n.º 6
0
        /// <summary>Converts image to compressed DELT data</summary>
        /// <param name="image">Bitmap to be encoded</param>
        /// <param name="left"><see cref="Delt.Left">Delt.Left</see> or <see cref="Anim.Frame.Left">Anim.Frame.Left</see></param>
        /// <param name="top"><see cref="Delt.Top">Delt.Top</see> or <see cref="Anim.Frame.Top">Anim.Frame.Top</see></param>
        /// <exception cref="ArgumentException"><i>image</i> is not <see cref="PixelFormat.Format8bppIndexed"/></exception>
        /// <returns>Encoded byte array of raw data ready to be written to file</returns>
        /// <remarks><i>image</i> must be <see cref="PixelFormat.Format8bppIndexed"/></remarks>
        public static byte[] EncodeImage(Bitmap image, short left, short top)
        {
            if (image.PixelFormat != PixelFormat.Format8bppIndexed)
            {
                throw new ArgumentException("image must be 8bppIndexed");
            }
            BitmapData bd = GraphicsFunctions.GetBitmapData(image);

            byte[] pix = new byte[bd.Stride * bd.Height];
            GraphicsFunctions.CopyImageToBytes(bd, pix);
            image.UnlockBits(bd);               // don't actually need image anymore other than .Width
            byte[] tempRaw = new byte[312960];  // max length; no repeats, 640x480 (6 read operations req'ed for 640px plus type/left/top per row [640+6 + 3*2], times 480 rows)
            int    w = bd.Stride;
            int    k, t = 0, pos = 0;

            for (int y = 0; y < image.Height; y++)
            {
                // okay, so BlockCopy lines; explicit short conversions into GetBytes returns byte[2], which BlockCopy uses as src to copy over into tempRaw[]
                ArrayFunctions.WriteToArray((short)((image.Width << 1) + 1), tempRaw, pos); // full-width row, compressed data
                pos += 2;
                ArrayFunctions.WriteToArray(left, tempRaw, pos);                            // row LEFT
                pos += 2;
                ArrayFunctions.WriteToArray((short)(y + top), tempRaw, pos);                // row TOP
                pos += 2;
                t    = y * w;
                for (int x = 0; x < image.Width;)
                {
                    for (k = x + 1; k < image.Width; k++)
                    {
                        if (pix[t + x] != pix[t + k])
                        {
                            break;                                                      // find next pixel that doesn't match current
                        }
                        if ((k - x) == 127)
                        {
                            break;                                              // max repeat, 127<<1+1 == 255
                        }
                    }
                    if ((k - x) >= 3)                                // need 3+ for REPEAT to be effective
                    {
                        tempRaw[pos++] = (byte)(((k - x) << 1) + 1); // odd OP_CODE
                        tempRaw[pos++] = pix[t + x];                 // pixel to be repeated
                    }
                    else
                    {
                        for (k = x + 1; k < image.Width; k++)                   // determine length of straight read
                        {
                            if ((k - x) == 127)
                            {
                                break;
                            }
                            try { if (pix[t + k] != pix[t + k + 1])
                                  {
                                      continue;
                                  }
                            }                                                                           // throws on end of row at k+1
                            catch { k++; break; }
                            // at this point, we're at two-in-a-row
                            try { if (pix[t + k + 1] != pix[t + k + 2])
                                  {
                                      continue;
                                  }
                            }                                                                           // throws on end of row at k+2
                            catch { k += 2; break; }
                            // three-in-a-row, cut it off!
                            break;
                        }
                        tempRaw[pos++] = (byte)((k - x) << 1);                                  // even OP_CODE
                        Buffer.BlockCopy(pix, t + x, tempRaw, pos, k - x); pos += (k - x);
                    }
                    x = k;
                }
            }
            pos += 2;                                  // EOI short = 0, pos now equals the used length of tempRaw
            byte[] raw = new byte[pos];
            ArrayFunctions.TrimArray(tempRaw, 0, raw); // copy all of the used data into the final, correctly-sized array
            return(raw);
        }
Ejemplo n.º 7
0
 /// <summary>Reads raw Delt-encoded image data and converts to a 256-color Bitmap</summary>
 /// <param name="left"><see cref="Delt.Left">Delt.Left</see> or <see cref="Anim.Frame.Left">Anim.Frame.Left</see></param>
 /// <param name="top"><see cref="Delt.Top">Delt.Top</see> or <see cref="Anim.Frame.Top">Anim.Frame.Top</see></param>
 /// <param name="width"><see cref="Delt.Width">Delt.Width</see> or <see cref="Anim.Frame.Width">Anim.Frame.Width</see></param>
 /// <param name="height"><see cref="Delt.Height">Delt.Height</see> or <see cref="Anim.Frame.Height">Anim.Frame.Height</see></param>
 /// <param name="rawData">Encoded pixel data from the LFD</param>
 /// <returns>256-color indexed Bitmap with default palette, <see cref="ErrorImage"/> on error</returns>
 public static Bitmap DecodeImage(short left, short top, short width, short height, byte[] rawData)
 {
     //System.Diagnostics.Debug.WriteLine("Image LTWH: " + left + ", " + top + ", " + width + ", " + height);
     try
     {
         int    w      = (width % 4 == 0 ? width : width + (4 - width % 4));             // w has to be a multiple of 4, round up
         byte[] pixels = new byte[w * height];
         for (int y = 0, pos = 0; y < height - 1;)
         {
             int  l          = BitConverter.ToInt16(rawData, pos); pos += 2; // row data value
             bool compressed = Convert.ToBoolean(l % 2);                     // get storage type
             l >>= 1;                                                        // number of pixels in row
             if (l == 0)
             {
                 l++; continue;
             }                                                            // if we wind up at the end, try next row
             int x = BitConverter.ToInt16(rawData, pos) - left; pos += 2; // row starting column
             y = BitConverter.ToInt16(rawData, pos) - top; pos += 2;      // starting row
             if (y < 0 || y >= height)
             {
                 System.Diagnostics.Debug.WriteLine("r " + y.ToString());
             }
             if (x < 0 || x >= width)
             {
                 System.Diagnostics.Debug.WriteLine("c " + x.ToString());
             }
             int startCol = x;
             for (; x < l + startCol;)
             {
                 byte b = rawData[pos++];
                 if (((b % 2) == 1) && compressed)               // odd OP_CODE odd LENGTH = Repeat
                 {
                     b >>= 1;                                    // number of repeats
                     byte p = rawData[pos++];
                     for (int k = 0; k < b; k++, x++)
                     {
                         pixels[y * w + x] = p;
                     }
                 }
                 else if (!compressed)                   // even LENGTH = Straight Read
                 {
                     pos--;                              // not actually an OP_CODE, need to read again
                     for (int k = 0; k < l; k++, x++)
                     {
                         pixels[y * w + x] = rawData[pos++];
                     }
                 }
                 else                            // even OP_CODE = Read
                 {
                     b >>= 1;
                     for (int k = 0; k < b; k++, x++)
                     {
                         pixels[y * w + x] = rawData[pos++];
                     }
                 }
             }
         }
         Bitmap     image  = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
         BitmapData bmdata = GraphicsFunctions.GetBitmapData(image);
         GraphicsFunctions.CopyBytesToImage(pixels, bmdata);
         image.UnlockBits(bmdata);
         return(image);
     }
     catch { return(Delt.ErrorImage); }
 }
Ejemplo n.º 8
0
        panlInfo decodeImage(byte[] rawData, int imageIndex)
        {
            panlInfo pi;
            short    width = 0, height = 0;

            for (int i = 0;;)
            {
                if (rawData[i] == 0xFE || rawData[i] == 0xFF)
                {
                    break;
                }
                else if (rawData[i] == 0xFD)
                {
                    width += (short)(rawData[i + 1] + 1);
                    i     += 3;
                }
                else if (rawData[i] == 0xFC)
                {
                    width += (short)(rawData[i + 2] + 1);
                    i     += 3;
                }
                else
                {
                    width += (short)((rawData[i] & 3) + 1);
                    i++;
                }
            }
            // ...and the mask height
            int pos = 0, x, y;

            pi.RawLength = 0;
            for (height = 0; pos < _rawData.Length; height++)
            {
                if (rawData[pos] == 0xFF)
                {
                    pi.RawLength = (short)(pos + 1); break;
                }
                if (rawData[pos] == 0xFE)
                {
                    pos++; height--; continue;
                }
                for (x = 0; x < width; pos++)
                {
                    if (rawData[pos] == 0xFD)
                    {
                        x   += rawData[pos + 1] + 1;
                        pos += 2;
                    }
                    else if (rawData[pos] == 0xFC)
                    {
                        x   += rawData[pos + 2] + 1;
                        pos += 2;
                    }
                    else
                    {
                        x += (rawData[pos] & 3) + 1;
                    }
                }
            }
            // start ze image!
            pi.PixelData = new byte[(width % 4 == 0 ? width : width + 4 - width % 4) * height];                 // Scan width is 4
            int px = 0;

            for (y = 0, pos = 0; y < height; y++)
            {
                for (; (px % 4) != 0;)
                {
                    px++;
                }
                if (rawData[pos] == 0xFE)
                {
                    pos++;
                }
                for (x = 0; x < width; pos++)
                {
                    if (rawData[pos] == 0xFD)
                    {
                        for (int i = 0; i <= rawData[pos + 1]; i++, px++)
                        {
                            pi.PixelData[px] = rawData[pos + 2];
                        }
                        x   += rawData[pos + 1] + 1;
                        pos += 2;
                    }
                    else if (rawData[pos] == 0xFC)
                    {
                        for (int i = 0; i <= rawData[pos + 2]; i++, px++)
                        {
                            pi.PixelData[px] = rawData[pos + 1];
                        }
                        x   += rawData[pos + 2] + 1;
                        pos += 2;
                    }
                    else
                    {
                        byte p = (byte)(rawData[pos] >> 2);
                        for (int i = 0; i <= (rawData[pos] & 3); i++, px++)
                        {
                            pi.PixelData[px] = p;
                        }
                        x += (rawData[pos] & 3) + 1;
                    }
                }
            }
            _images[imageIndex] = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
            if (_palette != null)
            {
                _images[imageIndex].Palette = _palette;
            }
            BitmapData bmdata = GraphicsFunctions.GetBitmapData(_images[imageIndex]);

            GraphicsFunctions.CopyBytesToImage(pi.PixelData, bmdata);
            _images[imageIndex].UnlockBits(bmdata);
            return(pi);
        }
Ejemplo n.º 9
0
        /// <summary>Prepares the resource for writing and updates <see cref="Resource.RawData"/></summary>
        public override void EncodeResource()
        {
            BitmapData bd = GraphicsFunctions.GetBitmapData(_image);

            byte[] pixels  = new byte[bd.Stride * bd.Height];
            byte[] tempRaw = new byte[pixels.Length];
            // assuming 640 width, pixels[] is 80 bytes wide. for MASK to consume 80 bytes a row, it requires 79 color switches. Not happening
            // (although a pure alternating static mask would be 641 bytes wide, at that point wtf)
            GraphicsFunctions.CopyImageToBytes(bd, pixels);
            int len = 0;

            for (int y = 0; y < _image.Height; y++)
            {
                for (int x = 0, numBlack = 0, numWhite = 0, pos = y * bd.Stride; x < _image.Width; x++, len++)
                {
                    byte shift = (byte)(0x80 >> (x & 7));
                    if ((pixels[pos + x / 8] & shift) == shift)
                    {                           // white
                        if (x == 0)
                        {
                            tempRaw[len++] = 0xFF;
                        }
                        if (numBlack != 0)
                        {
                            if (numBlack >= 512)
                            {
                                len++;
                            }
                            if (numBlack >= 256)
                            {
                                len++;
                            }
                            if ((numBlack & 0xFF) != 0)
                            {
                                tempRaw[len] = (byte)(numBlack & 0xFF);
                            }
                            else
                            {
                                tempRaw[len] = 1;                               // SetMask ensures this is a "throw away" pixel, effectively x=Width
                            }
                        }
                        numWhite++;
                        numBlack = 0;
                    }
                    else
                    {                           // black
                        if (x == 0)
                        {
                            tempRaw[len++] = 1;
                        }
                        if (numWhite != 0)
                        {
                            if (numWhite >= 512)
                            {
                                len++;
                            }
                            if (numWhite >= 256)
                            {
                                len++;
                            }
                            if ((numWhite & 0xFF) != 0)
                            {
                                tempRaw[len] = (byte)(numWhite & 0xFF);
                            }
                            else
                            {
                                tempRaw[len] = 1;                               // SetMask ensures this is a "throw away" pixel, effectively x=Width
                            }
                        }
                        numWhite = 0;
                        numBlack++;
                    }
                }
            }
            byte[] raw = new byte[len + 2];
            ArrayFunctions.TrimArray(tempRaw, 0, raw);
            _rawData = raw;
        }
Ejemplo n.º 10
0
        /// <summary>Processes raw data to populate the resource</summary>
        /// <param name="raw">Raw byte data</param>
        /// <param name="containsHeader">Whether or not <i>raw</i> contains the resource Header information</param>
        /// <exception cref="ArgumentException">Header-defined <see cref="Type"/> is not <see cref="Resource.ResourceType.Mask"/></exception>
        public override void DecodeResource(byte[] raw, bool containsHeader)
        {
            _decodeResource(raw, containsHeader);
            if (_type != ResourceType.Mask)
            {
                throw new ArgumentException("Raw header is not for a Mask resource");
            }
            if (Width == 0)
            {
                for (int i = 1; ; i++)                  // get mask width
                {
                    // TODO: check all MASK resources, check size
                    if (_rawData[i] == 0)
                    {
                        Width += 0x100;
                    }
                    else if (_rawData[i] == _rawData[0])
                    {
                        break;                                                          // TODO: currently assumes there's no 1px or 255px lengths in the top row, try to account for it
                    }
                    else
                    {
                        Width += _rawData[i];
                    }
                }
            }
            int pos = 0, x, y;

            if (Height == 0)
            {
                for (Height = 0; pos < _rawData.Length; Height++)                       // get mask height
                {
                    if (_rawData[pos] == 0)
                    {
                        break;
                    }
                    for (x = 0; x < Width; pos++)
                    {
                        if (_rawData[pos] == 0)
                        {
                            x += 0x100; if (x == Width)
                            {
                                pos++;
                            }
                        }                                                                                       // won't end on 00, so there's an extra pixel
                        else
                        {
                            x += _rawData[pos];
                        }
                    }
                }
            }
            // start ze image!
            _image = new Bitmap(Width, Height, PixelFormat.Format1bppIndexed);
            BitmapData bd = GraphicsFunctions.GetBitmapData(_image);
            bool       draw;

            byte[] pixels = new byte[bd.Stride * bd.Height];
            for (y = 0, pos = 0, draw = false; y < Height; y++, draw = false)
            {
                if (raw[pos] == 0xFF)
                {
                    draw = true;
                }
                pos++;
                int len = 0;
                int w   = bd.Stride * y;
                for (x = 0; x < Width; pos++)
                {
                    if (_rawData[pos] == 0)
                    {
                        len += 0x100; continue;
                    }
                    len += _rawData[pos];
                    if (draw)
                    {
                        for (int x0 = x; x < x0 + len - 1; x++)
                        {
                            pixels[w + x / 8] |= (byte)(0x80 >> (x & 7));
                        }
                        if (x != Width)
                        {
                            pixels[w + x / 8] |= (byte)(0x80 >> (x & 7));                                       // will not fire for "throw away" pixel
                        }
                        x++;
                    }
                    else
                    {
                        x += len;
                    }
                    draw = !draw;
                    len  = 0;
                }
            }
            GraphicsFunctions.CopyBytesToImage(pixels, bd);
            _image.UnlockBits(bd);
        }