using ImageMagick;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Net.Mime.MediaTypeNames;
namespace Weather
{
public class RadarPixels
{
public RadarPixels(string imageToChange, string folderToSave)
{
ConvertRadarImages(imageToChange, folderToSave);
}
public static Bitmap Create32bpp(System.Drawing.Image image, Size size)
{
Bitmap bmp = new Bitmap(size.Width, size.Height,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using (Graphics gr = Graphics.FromImage(bmp))
{
gr.Clear(Color.White);
gr.DrawImage(image, new Rectangle(0, 0, bmp.Width, bmp.Height));
}
return bmp;
}
public void ConvertRadarImages(string imageToChange, string folderToSave)
{
var image1 = Create32bpp(System.Drawing.Image.FromFile(imageToChange), new Size(512, 512));
var image2 = new Bitmap(Properties.Resources.radar_without_clouds);
image1.SetResolution(96, 96);
image2.SetResolution(96, 96);
int tolerance = 64;
var img1 = new LockBitmap(image1);
var img2 = new LockBitmap(image2);
img1.LockBits();
img2.LockBits();
for (int x = 0; x < image1.Width; x++)
{
for (int y = 0; y < image1.Height; y++)
{
Color pixelColor = img1.GetPixel(x, y);
// just average R, G, and B values to get gray. Then invert by 255.
int invertedGrayValue = 255 - (int)((pixelColor.R + pixelColor.G + pixelColor.B) / 3);
if (invertedGrayValue > tolerance) { invertedGrayValue = 255; }
// this keeps the original pixel color but sets the alpha value
img1.SetPixel(x, y, Color.FromArgb(invertedGrayValue, pixelColor));
}
}
img1.UnlockBits();
img2.UnlockBits();
using (Graphics g = Graphics.FromImage(image2))
{
g.CompositingMode = CompositingMode.SourceOver;
g.CompositingQuality = CompositingQuality.HighQuality;
g.DrawImage(image1, new Point(0, 0));
}
string fileToSave = Path.GetFileName(imageToChange);
image2.Save(Path.Combine(folderToSave, fileToSave), ImageFormat.Png);
}
}
}
in form1
radarPixels = new RadarPixels(savedFile, Path.GetDirectoryName(savedFile));
i'm getting exception error on the line :
image2.Save(Path.Combine(folderToSave, fileToSave), ImageFormat.Png);
System.Runtime.InteropServices.ExternalException: 'A generic error
occurred in GDI+.'
folderToSAve contains : "E:\Downloaded Images\Radar\Tuesday 02.07.2023 at 23.09 PM"
fileToSave contains : "2023_02_07_23_05.png"
the current image file on the hard disk is : 2023_02_07_22_55.png
what i want to do is that after manipulating on the image 2023_02_07_22_55.png to save the changes made overwriting the same file name : 2023_02_07_22_55.png
but getting this exception error.
tried :
image2.Save(Path.Combine(folderToSave, fileToSave), ImageFormat.Png);
but getting the exception error.
Related
In a new class i added two methods : ChangeSize and ResizeImage
using ImageMagick;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Weather
{
public class RadarPixels
{
public RadarPixels(string[] imagesToChangeSize,Bitmap image1, Bitmap image2)
{
ChangeSize(imagesToChangeSize);
ReadSetPixels(image1, image2);
}
private void ReadSetPixels(Bitmap image1, Bitmap image2)
{
int tolerance = 64;
for (int x = 0; x < image1.Width; x++)
{
for (int y = 0; y < image1.Height; y++)
{
Color pixelColor = image1.GetPixel(x, y);
// just average R, G, and B values to get gray. Then invert by 255.
int invertedGrayValue = 255 - (int)((pixelColor.R + pixelColor.G + pixelColor.B) / 3);
if (invertedGrayValue > tolerance) { invertedGrayValue = 255; }
// this keeps the original pixel color but sets the alpha value
image1.SetPixel(x, y, Color.FromArgb(invertedGrayValue, pixelColor));
}
}
// composite image1 on top of image2
using (Graphics g = Graphics.FromImage(image2))
{
g.CompositingMode = CompositingMode.SourceOver;
g.CompositingQuality = CompositingQuality.HighQuality;
g.DrawImage(image1, new Point(0, 0));
}
image2.Save(#"d:\mynewbmp.bmp");
image1.Dispose();
image2.Dispose();
}
private void ChangeSize(string[] images)
{
for(int i = 0; i < images.Length; i++)
{
Bitmap bmpResized = ResizeImage(Image.FromFile(images[i]), 512, 512);
bmpResized.Save(images[i]);
bmpResized.Dispose();
}
}
public static Bitmap ResizeImage(Image image, int width, int height)
{
var destRect = new Rectangle(0, 0, width, height);
var destImage = new Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
}
}
This is the saving line in the ChangeSize method : i want to keep the same folder and files names and overwrite the existing files with the new sized files.
bmpResized.Save(images[i]);
before that i used to save it like this : and this is was working fine :
bmpResized.Save(#"d:\sized\" + Path.GetFileName(images[i]));
but when i try to overwrite the files i'm getting exception error on the line :
bmpResized.Save(images[i]);
System.Runtime.InteropServices.ExternalException: 'A generic error occurred in GDI+.'
System.Runtime.InteropServices.ExternalException
HResult=0x80004005
Message=A generic error occurred in GDI+.
Source=System.Drawing
StackTrace:
at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
at System.Drawing.Image.Save(String filename, ImageFormat format)
at System.Drawing.Image.Save(String filename)
at Weather.RadarPixels.ChangeSize(String[] images) in D:\Csharp Projects\Weather\RadarPixels.cs:line 56
at Weather.RadarPixels..ctor(String[] imagesToChangeSize, Bitmap image1, Bitmap image2) in D:\Csharp Projects\Weather\RadarPixels.cs:line 20
at Weather.Form1..ctor() in D:\Csharp Projects\Weather\Form1.cs:line 113
at Weather.Program.Main() in D:\Csharp Projects\Weather\Program.cs:line 19
the files in the array images :
this is how i'm using it in form1 :
RadarPixels rp = new RadarPixels(radarImages,
new Bitmap(Image.FromFile(#"D:\123.png")),
new Bitmap(Image.FromFile(#"D:\2.jpg")));
Maybe the problem is because i'm displaying the images in pictureBox before changing the sizes ? maybe because the images are in use ?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Read_Drawn
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Bitmap image = new Bitmap(#"d:\drawplane1.jpg");
Bitmap mynewimage = new Bitmap(image.Width, image.Height);
for (int i = 0; i < image.Height; i++)
{
for (int j = 0; j < image.Width; j++)
{
Color c = image.GetPixel(j, i);
if (c.R == 0 && c.G == 0 && c.B == 0)
{
mynewimage.SetPixel(j, i, Color.Black);
}
}
}
pictureBox1.Image = mynewimage;
}
}
}
If I just assign the image to the pictureBox1 it will show png fine in the pictureBox1 but I want now to show only the black pixels I mean to show only the draw without the white background but it's showing only few if at all black pixels in the pictureBox1.
If I'm doing :
if (c.R == 0 && c.G == 0 && c.B == 0)
{
mynewimage.SetPixel(j, i,c);
}
else
{
mynewimage.SetPixel(j, i, c);
}
Then it will draw a copy of the original file image but I want only the black draw without the white background.
Update :
This is the original image :
I want to get only the drawn airplane without the white background and without any other stuff.
This is the script now :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Read_Drawn_Sketches
{
public partial class Form1 : Form
{
private Bitmap bmp;
private Bitmap image;
public Form1()
{
InitializeComponent();
trackBar1.Minimum = 0;
trackBar1.Maximum = 50;
image = new Bitmap(#"d:\drawplane1.jpg");
bmp = (CreateNonIndexedImage(image));
ConvertImageToBlackAndWhite(bmp);
GetImagePixels();
pictureBox1.Image = bmp;
}
private void GetImagePixels()
{
for (int i = 0; i < image.Height; i++)
{
for (int j = 0; j < image.Width; j++)
{
Color c = image.GetPixel(j, i);
if (c.R == 255 && c.G == 255 && c.B == 255) // white is an equal mix of every colour
{
bmp.SetPixel(j, i, Color.Transparent);
}
}
}
}
private void ConvertImageToBlackAndWhite(Bitmap SourceImage)
{
using (Graphics gr = Graphics.FromImage(SourceImage)) // SourceImage is a Bitmap object
{
var gray_matrix = new float[][] {
new float[] { 0.299f, 0.299f, 0.299f, 0, 0 },
new float[] { 0.587f, 0.587f, 0.587f, 0, 0 },
new float[] { 0.114f, 0.114f, 0.114f, 0, 0 },
new float[] { 0, 0, 0, 1, 0 },
new float[] { 0, 0, 0, 0, 1 }
};
var ia = new System.Drawing.Imaging.ImageAttributes();
ia.SetColorMatrix(new System.Drawing.Imaging.ColorMatrix(gray_matrix));
ia.SetThreshold(trackBar1.Value); // Change this threshold as needed
var rc = new Rectangle(0, 0, SourceImage.Width, SourceImage.Height);
gr.DrawImage(SourceImage, rc, 0, 0, SourceImage.Width, SourceImage.Height, GraphicsUnit.Pixel, ia);
}
}
public Bitmap CreateNonIndexedImage(Image src)
{
Bitmap newBmp = new Bitmap(src.Width, src.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using (Graphics gfx = Graphics.FromImage(newBmp))
{
gfx.DrawImage(src, 0, 0);
}
return newBmp;
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
bmp = (CreateNonIndexedImage(image));
ConvertImageToBlackAndWhite(bmp);
pictureBox1.Image = bmp;
}
}
}
When running the application I see in the pictureBox :
It looks like transparent but the airplane and other things that was in black are in white. I want it to be transparent but to keep only the black drawn.
Now if I'm moving the trackBar by one to the right I'm getting this :
It's ion black but the background is now not transparent :
Now I moved the trackbar a bit more to the right now you can see more black stuff around the airplane :
And last I moved the trackbar to the far end to the right and this is I think how it should be the airplane but the background should be transparent and not white:
The main goal is to take the image source from the hard disk and get only the airplane in black with transparent background and I prefer to make it in the code without an external tool or in some website even if it's more slower.
This is a link for the image file : https://easyupload.io/3l01vf
I'm not sure, but if you want to remove whiteback ground and make it transparent, you want to look for color = 255. So that would be:
public Form1()
{
InitializeComponent();
Bitmap image = new Bitmap(#"d:\drawplane1.jpg");
Bitmap mynewimage = new Bitmap(image.Width, image.Height);
for (int i = 0; i < image.Height; i++)
{
for (int j = 0; j < image.Width; j++)
{
Color c = image.GetPixel(j, i);
if (c.R == 255 && c.G == 255 && c.B == 255) // white is an equal mix of every colour
{
mynewimage.SetPixel(j, i, Color.Transparent);
}
}
}
pictureBox1.Image = mynewimage;
Note: this only works for complete white. If your background has some slightly different shades of white, you may need to use a range instead, such as 200 < c.R && c.R < 255 &&.. but I don't know how your image looks like so you'll have to play with the numbers yourself.
All that said, if your goal is to just remove the image background, you can use a free online background image remover. I normally just do that, works very quickly.
I need to create a figure (square) where for each client registered in the system, I put a pixel in a chosen location of the square by the client. I have this example . I need a hint in C # on how to get started.This is only exemple to start.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace RandomPixelImage
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
int width = 640, height = 320;
//bitmap
Bitmap bmp = new Bitmap(width, height);
//random number
Random rand = new Random();
//create random pixels
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
//generate random ARGB value
int a = rand.Next(256);
int r = rand.Next(256);
int g = rand.Next(256);
int b = rand.Next(256);
//set ARGB value
bmp.SetPixel(x, y, Color.FromArgb(a, r, g, b));
}
}
//load bmp in picturebox1
pictureBox1.Image = bmp;
//save (write) random pixel image
bmp.Save("D:\\Image\\RandomImage.png");
}
}
}
Since you have already made a Bitmap, all you need to do is assign that to PictureBox control:
First add a PictureBox control to your form, and then add this code to get your image onto it.
pictureBox.Image = bmp;
As your example shows, you can use Bitmap.SetPixel() to alter single pixels.
need help converting this short[] into a grayscale bmp
Current Error : http://grabilla.com/04c0f-dcadafc9-1274-4cbf-a3a9-dc47d5148c25.html#
the tdata array is a short[] or list< int16>its short grayscale height map
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Windows.Media.Imaging;
using System.Drawing.Imaging;
namespace ConvertSHTtobmp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int h, w;
h = 1536;
w = 1536;
List<byte> tdata = new List<byte>();
using (BinaryReader br = new BinaryReader(File.Open("C:\\Users\\Keith\\Desktop\\StartZone_1536_1536_0.sht", FileMode.Open)))
{
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
byte temp = br.ReadByte();
tdata.Add (temp);
temp = br.ReadByte();
tdata.Add(temp);
}
}
CreateBitmapFromBytes(tdata.ToArray(), w, h);
}
}
private static void CreateBitmapFromBytes(byte[] pixelValues, int width, int height)
{
//Create an image that will hold the image data
Bitmap pic = new Bitmap(width, height, PixelFormat.Format16bppGrayScale);
//Get a reference to the images pixel data
Rectangle dimension = new Rectangle(0, 0, pic.Width, pic.Height);
BitmapData picData = pic.LockBits(dimension, ImageLockMode.ReadWrite, pic.PixelFormat);
IntPtr pixelStartAddress = picData.Scan0;
//Copy the pixel data into the bitmap structure
System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, pixelStartAddress, pixelValues.Length);
pic.UnlockBits(picData);
pic.Save(#"C:\Users\Keith\Desktop\heightmap.bmp", ImageFormat.Bmp);
}
}
}
https://social.msdn.microsoft.com/Forums/vstudio/en-US/10252c05-c4b6-49dc-b2a3-4c1396e2c3ab/writing-a-16bit-grayscale-image?forum=csharpgeneral
finally found the right search terms after a few hours of searching :)
ok so the above link got me thinking about the following stuff.
the end solution was this
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.IO;
namespace WpfApplication1
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
short[] Buf = new short[64 * 64];
BitmapSource bmpSrc = BitmapSource.Create(
64, 64, 96, 96, PixelFormats.Gray16, null, Buf, 128);
TransformedBitmap transformedBmp = new TransformedBitmap(bmpSrc, new RotateTransform(-90));
PngBitmapEncoder enc = new PngBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(transformedBmp));
using (FileStream fs = new FileStream("D:\\Temp\\Test.png", FileMode.Create))
{
enc.Save(fs);
}
}
}
}
sources:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/1a0919e9-95df-4479-95b8-103e1914e08e/problems-saving-a-12bpp-short-array-as-a-grayscale-bmp?forum=csharpgeneral
Please imagine I have a very simple chequerboard image.
Here I represent the image with letters as pixels: black pixel 'B', white pixel 'W'
Here is the starting 2x2 pixel image:
BW
WB
I want to resize the image, lets say by scale of 2x to give me :
BBWW
BBWW
WWBB
WWBB
or scale 4x
BBBBWWWW
BBBBWWWW
WWWWBBBB
WWWWBBBB
So that the pixel colours are not dithered in any way at all.
I have tried this in C# but the image is a mess, all dithered, I need to learn how to do this without dithering/color change.
Here is my code so far:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
namespace PageTwine
{
public partial class RandonGiff : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// create 2x2 chequerboard:
Bitmap oBitmap = new Bitmap(2, 2);
Graphics oGraphic = Graphics.FromImage(oBitmap);
// color black pixels (i think the default is black but this helps to explain)
SolidBrush oBrush = new SolidBrush(Color.FromArgb(255, 255, 255));
oGraphic.FillRectangle(oBrush, 0, 0, 1, 1);
oGraphic.FillRectangle(oBrush, 1, 1, 1, 1);
//color white pixels
oBrush = new SolidBrush(Color.FromArgb(0, 0, 0));
oGraphic.FillRectangle(oBrush, 0, 1, 1, 1);
oGraphic.FillRectangle(oBrush, 1, 0, 1, 1);
// expand to 4x4
Bitmap result = new Bitmap(4, 4);
using (Graphics graphics = Graphics.FromImage(result))
{
// I don't know what these settings should be :
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
//draw the image into the target bitmap
graphics.DrawImage(oBitmap, 0, 0, result.Width, result.Height);
}
//send image directly to the browser
Response.ContentType = "image/gif";
result.Save(Response.OutputStream, ImageFormat.Gif);
}
}
}
The result is a dithered image, but I need a clean crisp chequerboard effect.
Please can you help me.
EDIT:07/02/12
Thanks for the suggestions so far but I am still searching without finding a solution.
I have created a demo page so you can see the results for yourself.
The URL for the demo is :
http://www.leansoftware.net/servicedesk/publicadhoc/randomgif.aspx?columns=3&rows=3
The demo will create a chequerboard with initial columns x rows as pixels, then enlarge to a gif image 300x300 px.
You will see that colours are distorted/bitty - this I am trying to solve.
Here is the source code for the demo:
using System;
using System.Collections.Generic;
using System.Web;
using System.IO;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Linq;
public partial class RandomGif : System.Web.UI.Page
{
public class Coordinates
{
public int x { get; set; }
public int y { get; set; }
}
static Random rand = new Random();
protected void Page_Load(object sender, EventArgs e)
{
// Output type gif
int iwidth;
int iheight;
int bits;
Response.ContentType = "image/gif";
// Get parameters
if (Request.QueryString["count"] != null)
{
bits = Convert.ToInt32(Request.QueryString["count"]);
int square = Convert.ToInt32(Math.Ceiling(Math.Sqrt(bits + Math.Floor(bits / 4.0))));
iwidth = square;
iheight = square;
bits = (square * square)-1;
}
else
if (Request.QueryString["rows"] != null && Request.QueryString["columns"] != null)
{
iwidth = Convert.ToInt32(Request.QueryString["columns"]);
iheight = Convert.ToInt32(Request.QueryString["rows"]);
bits = (iwidth * iheight);
}
else {
return;
}
if (bits > 1000){
Response.Write("Please specify a grid <= 1000 pixels");
return;
}
int plotCount = 0;
//web safe colors : 00, 33, 66, 99, CC, FF;
List<int> webSafeColor = new List<int>();
webSafeColor.Add(0); //00
webSafeColor.Add(51);//33
webSafeColor.Add(102);//66
webSafeColor.Add(153);//99
webSafeColor.Add(204);//CC
webSafeColor.Add(255);//FF
// Create a structure to hold all possible coordinates
var Grid = new List<Coordinates>();
for (int xi = 1; xi <= iwidth; xi++)
{
for (int yi = 1; yi <= iheight; yi++)
{
Grid.Add(new Coordinates { x = xi, y = yi });
plotCount++;
}
}
//create a new Bitmap object
Bitmap oBitmap = new Bitmap(iwidth, iheight);
//create a new Graphics object, which will allow us to draw on our bitmap:
Graphics oGraphic = Graphics.FromImage(oBitmap);
//fill the image rectangle with n bits
for (int i = 1; i <= bits; i++)
{
//Random rand = new Random();
int row = rand.Next(Grid.Count());
// random red
int ircolor = webSafeColor[rand.Next(5)];
// random green
int igcolor = webSafeColor[rand.Next(5)];
// random blue
int ibcolor = webSafeColor[rand.Next(5)];
Color randomColor = Color.FromArgb(ircolor, igcolor, ibcolor);
SolidBrush oBrush = new SolidBrush(randomColor);
oGraphic.FillRectangle(oBrush, Grid[row].x - 1, Grid[row].y - 1, 1, 1);
// Delete this coordinate#
Grid.Remove(Grid[row]);
}
// resize image
Bitmap result = new Bitmap(300, 300);
using (Graphics graphics = Graphics.FromImage(result))
{
//set the resize quality modes to high quality
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.AssumeLinear;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
//draw the image into the target bitmap
graphics.DrawImage(oBitmap, 0, 0, result.Width, result.Height);
}
//send image directly to the browser
Response.ContentType = "image/gif";
result.Save(Response.OutputStream, ImageFormat.Gif);
}
}
If you can suggest modifications we can try them out and see if it fixes the problem.
Thanks Richard
This is a possible duplicate of c# Draw Image (Scaled) to Graphics, does not interpolate correctly. Fixes?
You need to add:
graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
Alternately, you could use
graphics.DrawImage(oBitmap, 0, 0, result.Width * 2, result.Height * 2);
to achieve a similar effect of forcing the brush to fill without warping at the right-bottom image edges.
Update:
Adding link for creating indexed images with a custom color palette.
http://support.microsoft.com/kb/319061
Use:
System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;