Charles Henington
Charles Henington

Reputation: 191

Unexpected image result converting to 8bpp

When converting Image to 8bpp there are vertical lines in the resulting 8bpp Image. Why does this occur?

static Bitmap To8bpp(Bitmap original)
        {
            int width = original.Width;
            int height = original.Height;
            Bitmap result = new Bitmap(width, height);
            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    Color color = original.GetPixel(x, y);
                    result.SetPixel(x, y, color);
                }
            }
            Rectangle rectangle = new Rectangle(0, 0, width, height);
            PixelFormat pixelFormat = PixelFormat.Format8bppIndexed;
            BitmapData bitmapData = result.LockBits(rectangle, ImageLockMode.ReadOnly, result.PixelFormat);
            Bitmap bitmap = new Bitmap(width * 4, height, bitmapData.Stride, pixelFormat, bitmapData.Scan0);
            result.UnlockBits(bitmapData);
            return bitmap;
        }

Upvotes: 1

Views: 113

Answers (1)

Charles Henington
Charles Henington

Reputation: 191

static Bitmap Get8bpp(Bitmap original)
{
  if (original == null) return null;
  if (original.PixelFormat == PixelFormat.Format8bppIndexed)
    return (Bitmap)original.Clone();

  Rectangle rectangle = new Rectangle(0, 0, original.Width, original.Height);
  Bitmap bitmap = original.Clone(rectangle, PixelFormat.Format32bppRgb);
  PixelFormat pixelFormat = PixelFormat.Format8bppIndexed;
  int w = bitmap.Width,
    h = bitmap.Height,
    ic = 0,
    oc = 0,
    bmpStride,
    outputStride,
    bytesPerPixel;
  PixelFormat pfIn = bitmap.PixelFormat;
  Bitmap output = new Bitmap(w, h, pixelFormat);
  BitmapData bmpData, outputData;

  switch (pfIn)
  {
    case PixelFormat.Format24bppRgb: bytesPerPixel = 3; break;
    case PixelFormat.Format32bppArgb: bytesPerPixel = 4; break;
    case PixelFormat.Format32bppRgb: bytesPerPixel = 4; break;
    default: throw new InvalidOperationException("Image format not supported");
  }
  bmpData = bitmap.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, pfIn);
  outputData = output.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.WriteOnly, pixelFormat);
  bmpStride = bmpData.Stride;
  outputStride = outputData.Stride;

  unsafe
  {
    byte* bmpPtr = (byte*)bmpData.Scan0.ToPointer(),
    outputPtr = (byte*)outputData.Scan0.ToPointer();
    if (bytesPerPixel == 3)
    {
      Set3BytesPerPixel(w, h, ref ic, ref oc, bmpStride, outputStride, bmpPtr, outputPtr);
    }
    else 
    {
      Set4BytesPerPixel(w, h, ref ic, ref oc, bmpStride, outputStride, bmpPtr, outputPtr);
    }
  }
  bitmap.UnlockBits(bmpData);
  output.UnlockBits(outputData);
  return output;
}

private static unsafe void Set3BytesPerPixel(int w, int h, ref int ic, ref int oc, int bmpStride, int outputStride, byte* bmpPtr, byte* outputPtr)
{
  int r;
  for (r = 0; r < h; r++)
    for (ic = oc = 0; oc < w; ic += 3, ++oc)
      outputPtr[r * outputStride + oc] = (byte)(int)
      (
        .299 * bmpPtr[r * bmpStride + ic] +
        .587 * bmpPtr[r * bmpStride + ic + 1] +
        .114 * bmpPtr[r * bmpStride + ic + 2]
      );
}

private static unsafe void Set4BytesPerPixel(int w, int h, ref int ic, ref int oc, int bmpStride, int outputStride, byte* bmpPtr, byte* outputPtr)
{
  int r;
  for (r = 0; r < h; r++)
    for (ic = oc = 0; oc < w; ic += 4, ++oc)
      outputPtr[r * outputStride + oc] = (byte)(int)
      ((bmpPtr[r * bmpStride + ic] / 255.0f) *
        (.299 * bmpPtr[r * bmpStride + ic + 1] +
          .587 * bmpPtr[r * bmpStride + ic + 2] +
          .114 * bmpPtr[r * bmpStride + ic + 3]
        )
      );
}

Upvotes: 1

Related Questions