I am capturing desktop screen and drawing on picturebox.
Below is a sample code for testing.Basically i am updating small portion of images on picture box coming from socket. so for performance prospective i am not invalidate whole image always, instead of just invalidate area which need to repaint considering scaling.
On paint event using below DrawImage overload to draw only specific region of picture box
if you try to run below code it not drawing properly.
Text areas are not readable.What is wrong i am doing here.I search extensively but did not got any solution.
Here is my code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
private Bitmap initial = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height,
PixelFormat.Format32bppArgb);
private Rectangle GetViewRect() { return pictureBox1.ClientRectangle; }
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
initial = CaptureDesktop();
Rectangle imageRect = new Rectangle(0, 0, initial.Width, initial.Height);
var viewRect = GetViewRect();
var scaleX = (float)viewRect.Width / initial.Width;
var scaleY = (float)viewRect.Height / initial.Height;
// Make sure the target rectangle includes the new block
var targetRect = Rectangle.FromLTRB(
(int)Math.Truncate(imageRect.X * scaleX),
(int)Math.Truncate(imageRect.Y * scaleY),
(int)Math.Ceiling(imageRect.Right * scaleX),
(int)Math.Ceiling(imageRect.Bottom * scaleY));
pictureBox1.Invalidate(targetRect);
pictureBox1.Update();
}
private Bitmap CaptureDesktop()
{
var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height,
PixelFormat.Format32bppArgb);
// Create a graphics object from the bitmap.
var gfxScreenshot = Graphics.FromImage(bmpScreenshot);
// Take the screenshot from the upper left corner to the right bottom corner.
gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y,
0,
0,
Screen.PrimaryScreen.Bounds.Size,
CopyPixelOperation.SourceCopy);
return bmpScreenshot;
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
lock (initial)
{
e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
e.Graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
var viewRect = GetViewRect();
var scaleX = (float)initial.Width / viewRect.Width;
var scaleY = (float)initial.Height / viewRect.Height;
var targetRect = e.ClipRectangle;
var imageRect = new RectangleF(targetRect.X * scaleX, targetRect.Y * scaleY, targetRect.Width * scaleX, targetRect.Height * scaleY);
e.Graphics.DrawImage(initial, targetRect, imageRect, GraphicsUnit.Pixel);
}
}
}
}
`
Edit : if i change to below code. it works fine.
e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
e.Graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High
;
Related
for now i did it all manually , i set the variable Point myPieLocation location and the Size myPieSize variable and i added 3 lines for helping to see the middle point.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Doppler_Radar
{
public partial class Form1 : Form
{
int myPiePercent = 15;
public Form1()
{
InitializeComponent();
pictureBox1.Image = Image.FromFile(#"D:\New folder (4)\Weather Radar\WithClouds.bmp");
timer1.Enabled = true;
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.DrawRectangle(Pens.Green, 0, 0, pictureBox1.Width - 1, pictureBox1.Height - 1);
Pen p = new Pen(Color.Red);
e.Graphics.DrawLine(p, 256, 0, 256, 512);
e.Graphics.DrawLine(p, 0, 256, 512, 256);
DrawPieOnPicturebox(e.Graphics);
}
public void DrawPieOnPicturebox(Graphics myPieGraphic)
{
Color myPieColors = Color.FromArgb(150, Color.LightGreen);
Point myPieLocation = new Point(180, 180);
Size myPieSize = new Size(150, 150);
DrawMyPie(myPiePercent, myPieColors, myPieGraphic, myPieLocation, myPieSize);
}
public void DrawMyPie(int myPiePerecent, Color myPieColor, Graphics myPieGraphic, Point
myPieLocation, Size myPieSize)
{
using (SolidBrush brush = new SolidBrush(myPieColor))
{
myPieGraphic.FillPie(brush, new Rectangle(myPieLocation, myPieSize), Convert.ToSingle(myPiePerecent * 360 / 100), Convert.ToSingle(15 * 360 / 100));
}
}
private void timer1_Tick(object sender, EventArgs e)
{
myPiePercent++;
pictureBox1.Invalidate();
}
}
}
The result is the pie is in the middle of the picturebox :
but if for example i change the pie size to 200,200 now the pie is not in the middle :
Size myPieSize = new Size(200, 200);
what i want to do is that no matter if i change the size of the pie keep the pie to be drawn in the middle of the pictureBox.
i tried instead 180, 108
Point myPieLocation = new Point(180, 180);
also
Point myPieLocation = new Point(pictureBox1.Width / 2,
pictureBox1.Height / 2);
but it's far away from the pictureBox1 middle :
i tried also clientsize and size in the myPieLocation but it's never in the middle.
i want to have outer glow text in a label for my winform application some thing like:
i searched for it in stackoverflow and I found this:
private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
//Create a bitmap in a fixed ratio to the original drawing area.
Bitmap bm=new Bitmap(this.ClientSize.Width/5, this.ClientSize.Height/5);
//Create a GraphicsPath object.
GraphicsPath pth=new GraphicsPath();
//Add the string in the chosen style.
pth.AddString("Text Halo",new FontFamily("Verdana"),(int)FontStyle.Regular,100,new Point(20,20),StringFormat.GenericTypographic);
//Get the graphics object for the image.
Graphics g=Graphics.FromImage(bm);
//Create a matrix that shrinks the drawing output by the fixed ratio.
Matrix mx=new Matrix(1.0f/5,0,0,1.0f/5,-(1.0f/5),-(1.0f/5));
//Choose an appropriate smoothing mode for the halo.
g.SmoothingMode=SmoothingMode.AntiAlias;
//Transform the graphics object so that the same half may be used for both halo and text output.
g.Transform=mx;
//Using a suitable pen...
Pen p=new Pen(Color.Yellow,3);
//Draw around the outline of the path
g.DrawPath(p,pth);
//and then fill in for good measure.
g.FillPath(Brushes.Yellow,pth);
//We no longer need this graphics object
g.Dispose();
//this just shifts the effect a little bit so that the edge isn't cut off in the demonstration
e.Graphics.Transform=new Matrix(1,0,0,1,50,50);
//setup the smoothing mode for path drawing
e.Graphics.SmoothingMode=SmoothingMode.AntiAlias;
//and the interpolation mode for the expansion of the halo bitmap
e.Graphics.InterpolationMode=InterpolationMode.HighQualityBicubic;
//expand the halo making the edges nice and fuzzy.
e.Graphics.DrawImage(bm,ClientRectangle,0,0,bm.Width,bm.Height,GraphicsUnit.Pixel);
//Redraw the original text
e.Graphics.FillPath(Brushes.Black,pth);
//and you're done.
pth.Dispose();
}
but the PROBLEM IS I CAN NOT MOVE IT please help me i need it to be movable and I want to be able to change it's size. the code above, just adds it automatically to somewhere in my form but I want to move that.
thank you
A better approach is to create a custom control for this to use/add some relevant drawing properties. Mainly, the Font and color of the text, the size and color of the outline. Then, you can lay out the custom control in any container at any location and with any size.
Here's a simple example.
[DesignerCategory("Code")]
public class GlowTextLabel : Control
{
private Color outlineColor = SystemColors.Highlight;
private int outlineSize = 1;
public GlowTextLabel() : base()
{
SetStyle(ControlStyles.Selectable, false);
SetStyle(ControlStyles.OptimizedDoubleBuffer |
ControlStyles.ResizeRedraw |
ControlStyles.SupportsTransparentBackColor, true);
}
[DefaultValue(typeof(Color), "Highlight")]
public Color OutlineColor
{
get => outlineColor;
set
{
if (outlineColor != value)
{
outlineColor = value;
Invalidate();
}
}
}
[DefaultValue(1)]
public int OutlineSize
{
get => outlineSize;
set
{
if (outlineSize != value)
{
outlineSize = Math.Max(1, value);
Invalidate();
}
}
}
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.Clear(BackColor);
var w = Math.Max(8, ClientSize.Width / 5);
var h = Math.Max(8, ClientSize.Height / 5);
using (var bmp = new Bitmap(w, h))
using (var gp = new GraphicsPath())
using (var sf = new StringFormat(StringFormat.GenericTypographic))
{
sf.Alignment = sf.LineAlignment = StringAlignment.Center;
gp.AddString(Text,
Font.FontFamily, (int)Font.Style, GetEmFontSize(Font),
ClientRectangle, sf);
using (var g = Graphics.FromImage(bmp))
using (var m = new Matrix(1.0f / 5, 0, 0, 1.0f / 5, -(1.0f / 5), -(1.0f / 5)))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.Transform = m;
using (var pn = new Pen(OutlineColor, OutlineSize))
{
g.DrawPath(pn, gp);
g.FillPath(pn.Brush, gp);
}
}
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Optional for wider blur...
// e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
e.Graphics.DrawImage(bmp,
ClientRectangle, 0, 0, bmp.Width, bmp.Height,
GraphicsUnit.Pixel);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
using (var br = new SolidBrush(ForeColor))
e.Graphics.FillPath(br, gp);
}
}
}
private float GetEmFontSize(Font fnt) =>
fnt.SizeInPoints * (fnt.FontFamily.GetCellAscent(fnt.Style) +
fnt.FontFamily.GetCellDescent(fnt.Style)) / fnt.FontFamily.GetEmHeight(fnt.Style);
Rebuild, find the GlowTextLabel control on the ToolBox under your project's components group, drop an instance, try the Font, ForeColor, OutlineColor, and OutlineSize properties with different values.
Pen width 1.
Pen width 10.
Pen width 20.
I am using DevExpress 18.1 on Windows 10 with VS 2017 for a WPF application. Additionally I am using the DevExpress BarCode Class. I am trying to create a QR Code that is 1 inch in size but am unable to do it without using something like Photoshop to shrink the output. I think I must be missing something in the process. Below is the code being used:
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Windows;
using DevExpress.BarCodes;
namespace WpfBarcode01
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Btn_1_Click(object sender, RoutedEventArgs e)
{
BarCode barCode = new BarCode();
barCode.Symbology = Symbology.QRCode;
barCode.CodeText =
"Alexander Johnathon Stevenson JR;Senior Software Developer;alexanderjohnathonstevensonjr#somesamplewebsite.com;20180709-08:00:00;9993334444;Los Angeles;CA;USA;ABC Company";
barCode.BackColor = Color.White;
barCode.ForeColor = Color.Black;
barCode.RotationAngle = 0;
barCode.CodeBinaryData = Encoding.Default.GetBytes(barCode.CodeText);
barCode.Options.QRCode.Version = QRCodeVersion.Version5;
barCode.Options.QRCode.CompactionMode = QRCodeCompactionMode.Byte;
barCode.Options.QRCode.ErrorLevel = QRCodeErrorLevel.H;
barCode.Options.QRCode.ShowCodeText = false;
barCode.DpiX = 100;
barCode.DpiY = 100;
barCode.AutoSize = false;
barCode.Unit = GraphicsUnit.Millimeter;
barCode.ImageWidth = (float)70;
barCode.ImageHeight = (float)70;
barCode.BarCodeImage.Save("d1.png", System.Drawing.Imaging.ImageFormat.Png);
Process.Start("d1.png");
}
}
}
When this runs, a QR Code is created which a hand held scanner is able to scan both on paper and screen. The problem is it is about 2.76 inches in size. I want one about 1 inch so I end up importing the .png file to Photoshop and reducing the image size to 1 inch. This works as the images now becomes small enough for label or document printing. This workflow though seems too time consuming if someone has to do this for a few hundred QR Codes.
I tried different values for the ImageWidth and ImageHeight as well as different values for DpiX and DPiY but no luck. And I tried to change the GraphicsUnit to Inches but that option does not seem to work as I always get an image of very irregular size. So I ended up using the Millimeter option for GraphicsUnit with a basis that 1 inch = 25.4 millimeters. If I use an ImageWidth or ImageHeight value lower than 65 the QR Code box gets clipped and becomes invalid for scanning.
Is there something else I can do to make the output be 1 inch and still valid? Or perhaps some graphic library call in DevExpress I can call to reduce the .png file to 1 inch like Photoshop does? Thanks in advance.
=====================================
Update July 9, 2018
Based on PepitoSH's suggested link below I was able to find a solution which I have added here in the code update. This code produces a 1 inch .png QRCode file which is a resize from the original that was 2.76 inches.
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Text;
using System.Windows;
using DevExpress.BarCodes;
namespace WpfBarcode01
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Btn_1_Click(object sender, RoutedEventArgs e)
{
BarCode barCode = new BarCode();
barCode.Symbology = Symbology.QRCode;
barCode.CodeText =
"Alexander Johnathon Stevenson JR;Senior Software Developer;alexanderjohnathonstevensonjr#somesamplewebsite.com;20180709-08:00:00;9993334444;Los Angeles;CA;USA;ABC Company";
barCode.BackColor = Color.White;
barCode.ForeColor = Color.Black;
barCode.RotationAngle = 0;
barCode.CodeBinaryData = Encoding.Default.GetBytes(barCode.CodeText);
barCode.Options.QRCode.Version = QRCodeVersion.Version5;
barCode.Options.QRCode.CompactionMode = QRCodeCompactionMode.Byte;
barCode.Options.QRCode.ErrorLevel = QRCodeErrorLevel.H;
barCode.Options.QRCode.ShowCodeText = false;
barCode.Dpi = 200;
barCode.AutoSize = false; //needs to be off if specifying unit and widths
barCode.Unit = GraphicsUnit.Millimeter; // Note: 1 inch = 25.4 Millimeters
barCode.ImageWidth = 70F;
barCode.ImageHeight = 70F;
Bitmap bitmap = ResizeImage(barCode.BarCodeImage, 200, 200);
bitmap.Save("QRCode.png");
Process.Start("QRCode.png");
}
public static Bitmap ResizeImage(Image originalImage, int newWidthInPixels, int newHeightInPixels)
{
var destRect = new Rectangle(0, 0, newWidthInPixels, newHeightInPixels);
var destImage = new Bitmap(newWidthInPixels, newHeightInPixels);
destImage.SetResolution(originalImage.HorizontalResolution, originalImage.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(originalImage, destRect, 0, 0, originalImage.Width, originalImage.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
}
}
Update July 9, 2018
Based on PepitoSH's suggested link I was able to find a solution which I have added here in the code update. This code produces a 1 inch .png QRCode file which is a resize from the original that was 2.76 inches.
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Text;
using System.Windows;
using DevExpress.BarCodes;
namespace WpfBarcode01
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Btn_1_Click(object sender, RoutedEventArgs e)
{
BarCode barCode = new BarCode();
barCode.Symbology = Symbology.QRCode;
barCode.CodeText =
"Alexander Johnathon Stevenson JR;Senior Software Developer;alexanderjohnathonstevensonjr#somesamplewebsite.com;20180709-08:00:00;9993334444;Los Angeles;CA;USA;ABC Company";
barCode.BackColor = Color.White;
barCode.ForeColor = Color.Black;
barCode.RotationAngle = 0;
barCode.CodeBinaryData = Encoding.Default.GetBytes(barCode.CodeText);
barCode.Options.QRCode.Version = QRCodeVersion.Version5;
barCode.Options.QRCode.CompactionMode = QRCodeCompactionMode.Byte;
barCode.Options.QRCode.ErrorLevel = QRCodeErrorLevel.H;
barCode.Options.QRCode.ShowCodeText = false;
barCode.Dpi = 200;
barCode.AutoSize = false; //needs to be off if specifying unit and widths
barCode.Unit = GraphicsUnit.Millimeter; // Note: 1 inch = 25.4 Millimeters
barCode.ImageWidth = 70F;
barCode.ImageHeight = 70F;
Bitmap bitmap = ResizeImage(barCode.BarCodeImage, 200, 200);
bitmap.Save("QRCode.png");
Process.Start("QRCode.png");
}
public static Bitmap ResizeImage(Image originalImage, int newWidthInPixels, int newHeightInPixels)
{
var destRect = new Rectangle(0, 0, newWidthInPixels, newHeightInPixels);
var destImage = new Bitmap(newWidthInPixels, newHeightInPixels);
destImage.SetResolution(originalImage.HorizontalResolution, originalImage.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(originalImage, destRect, 0, 0, originalImage.Width, originalImage.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
}
}
I have a picturebox in my c# windows forms application, and i've made some code so that I can alter the height and width of the picturebox, essentially zooming in. However, this only focuses on the top right area and I would like the user to be able to scroll the map to the area they need to using the scrollbar.
Whenever I zoom in, then use the scrollbar, my image goes to its default size, and then only scrolls in that size.
How can I move the entire image so that the user can pan the picturebox map?
Here's my code:
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 Mapping_Application
{
public partial class Form1 : Form
{
//Declare zoom variable counter
int zoom;
//Main Void
public Form1()
{
InitializeComponent();
}
//Zoom In
private void button1_Click(object sender, EventArgs e)
{
if(zoom != 3)
{
pictureBox1.Height = pictureBox1.Height * 2;
pictureBox1.Width = pictureBox1.Width * 2;
zoom = zoom + 1;
}
}
//Zoom out
private void button2_Click(object sender, EventArgs e)
{
if (zoom != 0)
{
pictureBox1.Height = pictureBox1.Height / 2;
pictureBox1.Width = pictureBox1.Width / 2;
zoom = zoom -= 1;
}
}
//The horizontal scrollbar
private void horizontal_Scroll(object sender, ScrollEventArgs e)
{
//Create a graphics object and draw a portion of the image in the PictureBox.
Graphics g = pictureBox1.CreateGraphics();
int x;
int y;
if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)
{
x = e.NewValue * 19;
y = vertical.Value * 19;
}
else //e.ScrollOrientation == ScrollOrientation.VerticalScroll
{
y = e.NewValue * 19;
x = horizontal.Value * 19;
}
g.Clear(Color.White);
g.DrawImage(pictureBox1.Image,
new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Width), //where to draw the image
new Rectangle(x, y, pictureBox1.Width, pictureBox1.Width), //the portion of the image to draw
GraphicsUnit.Pixel);
pictureBox1.Update();
}
//The vertical scrollbar
private void vertical_Scroll(object sender, ScrollEventArgs e)
{
//Create a graphics object and draw a portion of the image in the PictureBox.
Graphics g = pictureBox1.CreateGraphics();
int x;
int y;
if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)
{
x = e.NewValue * 19;
y = vertical.Value * 19;
}
else //e.ScrollOrientation == ScrollOrientation.VerticalScroll
{
y = e.NewValue * 19;
x = horizontal.Value * 19;
}
g.Clear(Color.White);
g.DrawImage(pictureBox1.Image,
new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Width), //where to draw the image
new Rectangle(x, y, pictureBox1.Width, pictureBox1.Width), //the
portion of the image to draw
GraphicsUnit.Pixel);
pictureBox1.Update();
}
}
}
The scroll currently seems to work, but for no zoom in only. There is no zoom negative feature and i'm using a var named zoom to store which level zoom the program is at. Can't zoom to -2x , hence the if (zoom!=0)
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;