I'm creating graphic at picturebox from left to right side, by adding single pixel columns, with predetermined time intervals(300ms). When subsequent pixel columns exceed the picturebox width, I can't see more of them.
How to make moving picturebox window, which would allow to see the current pixel column all the time?
I'm using BASS library, code is below.
private void timer1_Tick_1(object sender, EventArgs e)
{
graphic = pictureBox1.CreateGraphics();
bool spectrum3DVoicePrint = visuals.CreateSpectrum3DVoicePrint(rHandle, graphic, pictureBox1.Bounds, Color.Navy, Color.Navy, pos, false, true);`
graphic.Dispose();
pos = ++;
}
you need to store each position in array.
Here is my simple code for demonstrate to draw line and move after reaches at width of picturebox. Make sure any mistake of any value of pixel,x,y,etc.. leads to wrong output.
int x = -1;
int y = 50;
Random rnd = new Random();
bool check = true;
int[,] pos;
int index = -1;
private void Form1_Load(object sender, EventArgs e)
{
//Initalize array
pos = new int[pictureBox1.Width + 2, 2];
}
private void timer1_Tick(object sender, EventArgs e)
{
Graphics graphic = pictureBox1.CreateGraphics();
if (x < pictureBox1.Width)
{
index++;
x++;
}
else
{
graphic.Clear(Color.Black);
for (int i = 0; i < pictureBox1.Width; i++)
{
pos[i, 1] = pos[i + 1, 1];
graphic.DrawRectangle(System.Drawing.Pens.Lime, pos[i, 0], pos[i, 1], 1, 1);
}
}
graphic.DrawRectangle(System.Drawing.Pens.Lime, x, y, 1, 1);
pos[index, 0] = x;
pos[index, 1] = y;
graphic.Dispose();
//for random dots
//y = rnd.Next(5, 95);
//for line
if (check)
y++;
else
y--;
if (y == 100)
check = false;
if (y == 5)
check = true;
}
Related
I'm trying to find the best path to go about creating a pixel "grid" that would allow basic paint functions such as coloring the pixels by clicking and moving the mouse, selecting an area for copying, pasting, or moving, or using other graphics functions in order to render text or shapes to the pixels. I've looked at a few samples, such as this example which overrides the panel control and has a similar look to what I'm trying to achieve, but the painting is slow and it seems like it wouldn't perform well for drawing with the mouse. Is there a control, or one that I could override, that would allow for the functionality that I'm looking for?
Here's a sample of what the above example looks like:
Sample pixel grid
And the code I adapted from the above example:
public class Pixel
{
public Rectangle Bounds { get; set; }
public bool IsOn { get; set; }
public bool IsSelected { get; set; }
}
public class PixelGridControl : Panel
{
public int Columns = 99;
public int Rows = 63;
private readonly Pixel[,] pixels;
public PixelGridControl()
{
this.DoubleBuffered = true;
this.ResizeRedraw = true;
// initialize pixel grid:
pixels = new Pixel[Columns, Rows];
for (int y = 0; y < Rows; ++y)
{
for (int x = 0; x < Columns; ++x)
{
pixels[x, y] = new Pixel();
}
}
}
// adjust each column and row to fit entire client area:
protected override void OnResize(EventArgs e)
{
int top = 0;
for (int y = 0; y < Rows; ++y)
{
int left = 0;
int height = (this.ClientSize.Height - top) / (Rows - y);
for (int x = 0; x < Columns; ++x)
{
int width = (this.ClientSize.Width - left) / (Columns - x);
pixels[x, y].Bounds = new Rectangle(left, top, width, height);
left += width;
}
top += height;
}
base.OnResize(e);
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
for (int y = 0; y < Rows; ++y)
{
for (int x = 0; x < Columns; ++x)
{
if (pixels[x, y].IsOn)
{
e.Graphics.FillRectangle(Brushes.Gold, pixels[x, y].Bounds);
}
else
{
ControlPaint.DrawButton(e.Graphics, pixels[x, y].Bounds,
ButtonState.Normal);
}
}
}
base.OnPaint(e);
}
// determine which button the user pressed:
protected override void OnMouseDown(MouseEventArgs e)
{
for (int y = 0; y < Rows; ++y)
{
for (int x = 0; x < Columns; ++x)
{
if (pixels[x, y].Bounds.Contains(e.Location))
{
pixels[x, y].IsOn = true;
this.Invalidate();
MessageBox.Show(
string.Format("You pressed on button ({0}, {1})",
x.ToString(), y.ToString())
);
}
}
}
base.OnMouseDown(e);
}
}
Here is an minimal example that uses a bitmap as the pixel storage and displays the enlarged pixels in a panel for editing.
You can use it by setting it up to edit the pixels in an Picturebox pBox_Target.Image, maybe like this:
public Form1()
{
InitializeComponent();
..
..
pixelEditor1.APBox = pBox_Target;
pixelEditor1.TgtBitmap = (Bitmap)pixelEditor1.APBox.Image;
..
}
The editor exposes the pixel size and the color to draw with among a minimum of properties..
all in all it is slightly over 100 lines - of course it is meant to be expanded!
Here it is at work:
class PixelEditor : Panel
{
public Color DrawColor { get; set; }
public Color GridColor { get; set; }
int pixelSize = 8;
public int PixelSize
{
get { return pixelSize; }
set
{
pixelSize = value;
Invalidate();
}
}
public Bitmap TgtBitmap { get; set; }
public Point TgtMousePos { get; set; }
Point lastPoint = Point.Empty;
PictureBox aPBox = null;
public PictureBox APBox {
get { return aPBox; }
set
{
if (value == null) return;
aPBox = value;
aPBox.MouseClick -=APBox_MouseClick;
aPBox.MouseClick +=APBox_MouseClick;
}
}
private void APBox_MouseClick(object sender, MouseEventArgs e)
{
TgtMousePos = e.Location;
Invalidate();
}
public PixelEditor()
{
DoubleBuffered = true;
BackColor = Color.White;
GridColor = Color.DimGray;
DrawColor = Color.Red;
PixelSize = 10;
TgtMousePos = Point.Empty;
if (APBox != null && APBox.Image != null)
TgtBitmap = (Bitmap)APBox.Image;
MouseClick +=PixelEditor_MouseClick;
MouseMove +=PixelEditor_MouseMove;
Paint +=PixelEditor_Paint;
}
private void PixelEditor_Paint(object sender, PaintEventArgs e)
{
if (DesignMode) return;
Graphics g = e.Graphics;
int cols = ClientSize.Width / PixelSize;
int rows = ClientSize.Height / PixelSize;
if (TgtMousePos.X < 0 || TgtMousePos.Y < 0) return;
for (int x = 0; x < cols; x++)
for (int y = 0; y < rows; y++)
{
int sx = TgtMousePos.X + x;
int sy = TgtMousePos.Y + y;
if (sx > TgtBitmap.Width || sy > TgtBitmap.Height) continue;
Color col = TgtBitmap.GetPixel(sx, sy);
using (SolidBrush b = new SolidBrush(col))
using (Pen p = new Pen(GridColor))
{
Rectangle rect = new Rectangle(x * PixelSize, y * PixelSize,
PixelSize, PixelSize);
g.FillRectangle(b, rect);
g.DrawRectangle(p, rect);
}
}
}
private void PixelEditor_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
int x = TgtMousePos.X + e.X / PixelSize;
int y = TgtMousePos.Y + e.Y / PixelSize;
if (new Point(x, y) == lastPoint) return;
Bitmap bmp = (Bitmap)APBox.Image;
bmp.SetPixel(x,y, DrawColor);
APBox.Image = bmp;
Invalidate();
lastPoint = new Point(x, y);
}
private void PixelEditor_MouseClick(object sender, MouseEventArgs e)
{
int x = TgtMousePos.X + e.X / PixelSize;
int y = TgtMousePos.Y + e.Y / PixelSize;
Bitmap bmp = (Bitmap)APBox.Image;
bmp.SetPixel(x,y, DrawColor);
APBox.Image = bmp;
Invalidate();
}
}
Note that this solution neither uses a special pixel class nor makes any provisions for selecting sets of pixels. To implement most selection tools you can use a GraphicsPath; you can the e.g. fill the path or loop over its bounds using IsVisible to enumerate the pixels in the path..
Update: Instead of a Panel, which is a Container control and not really meant to draw onto you can use a Picturebox or a Label (with Autosize=false); both have the DoubleBuffered property turned on out of the box and support drawing better than Panels do.
I need to develop a chart using datavisualization. Now the chart looks like
below
In the above chart i am using rangebar to show min and max values, in rangebar the label (65---210) now comes in the middle part. But i need to show the min and max like one in red. ie min value in the start position of the rangebar and max value in the end position of the rangebar.
Please let me know if there is any way to do it
The way to do it is by handling the chart's Paint event.
You would need to do some more sophisticated calculations using the Graphics object to make it work for the generic case. But it should get you started.
public partial class WebForm1 : System.Web.UI.Page
{
float deltax, deltay, deltay2;
Font font;
Brush brush;
Random r;
protected void Page_Load(object sender, EventArgs e)
{
deltax = 7.5F;
deltay = 60;
deltay2 = 5;
font = new Font("Courier", 14);
brush = new SolidBrush(Color.Red);
r = new Random();
for (int i = 1; i <= 5; i++)
Chart1.Series[0].Points.Add(new DataPoint(i, new double[2] { r.Next(10, 40), r.Next(60, 90) }));
}
protected void Chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
if (e.ChartElement.ToString().Contains("Series"))
{
int count = Chart1.Series[0].Points.Count - 1;
for (int i = count; i >= 0; i--)
{
DataPoint dp = Chart1.Series[0].Points[i];
float size = (float)(deltax*(dp.YValues[1] - dp.YValues[0] + deltay2));
float x = (float)(deltax * dp.YValues[0]);
float y = (float)(deltay * (count - dp.XValue + 2));
e.ChartGraphics.Graphics.DrawString(string.Format("{0}", dp.YValues[0]), font, brush, new PointF(x, y));
e.ChartGraphics.Graphics.DrawString(string.Format("{0}", dp.YValues[1]), font, brush, new PointF(x + size, y));
}
}
}
}
I have a ball bouncing off of paddles and walls as desired, i have then added a singular brick via the draw.Rectangle tool and had the ball bounce off of this and then change its colour but could not make it invisible to stop any further collisions.
I am using an array for my bricks as i can have many and can turn them true or false after being hit
My issue is that i am trying to get the ball to collide with said array bricks, but cannot for the life of me figure it out even with as much googling as possible. here is the snippet of my code i think 'should' work for the collision
for (int i = 0; 1 < brickLive.Length; i++)
if ((y == brickLocation[i, 0]) && (x >= brickLocation[0, i]) && (x <= (brickLocation[0, i] + 60)))
yChange = -yChange;
to my understanding this code is saying for the value of i check if ball coords are in the parameters of a bricks location. if it is then change direction.
with the current code it runs fine until i start the game (i click the insert button and that enables the bounce button to work)
here is my full 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 Breakout
{
public partial class Form1 : Form
{
private int x, y, x2, y2;
private int xChange, yChange;
int bat, batX, batXX, mouseX;
private Graphics paper;
private Pen pen, pen2, pen3;
private Pen brkpen;
private Random ranNum;
int brkLength = 60;
int brkHeight = 20;
int[,] brickLocation = { { 0, 100 }, { 61, 100 }, { 122, 100 } };
bool[] brickLive = { true, true, true };
public Form1()
{
InitializeComponent();
paper = picDisplayBat.CreateGraphics();
pen = new Pen(Color.Red);
pen.Width = 10;
ranNum = new Random();
paper = picDisplayBat.CreateGraphics();
pen = new Pen(Color.Blue);
pen.Width = 3;
paper = picDisplayBat.CreateGraphics();
pen2 = new Pen(Color.Red);
pen.Width = 3;
picDisplayBat.MouseMove += new
System.Windows.Forms.MouseEventHandler(picDraw_MouseMove);
paper = picDisplayBat.CreateGraphics();
brkpen = new Pen(Color.Black);
brkpen.Width = 3;
//paper = picDisplayBat.CreateGraphics();
//pen3 = new Pen(Color.Green);
//pen3.Width = 5;
}
private void picDraw_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) //DRAWING THE BAT TO MOVE WITH MOUSE
{
//paper.Clear(Color.White);
mouseX = e.X;
}
private void btnInsert_Click_1(object sender, EventArgs e)
{
{
btnBounce.Visible = true;
}
}
private void btnBounce_Click_1(object sender, EventArgs e)
{
{
timer1.Interval = 25;
timer1.Enabled = true;
x = ranNum.Next(1, picDisplayBat.Height);
y = ranNum.Next(1, picDisplayBat.Width);
xChange = ranNum.Next(1, 10); yChange = ranNum.Next(1, 10);
for (int i = 0; i < brickLive.Length; i++)
{
paper.DrawRectangle(brkpen, brickLocation[i, 0], brickLocation[i, 1], brkLength, brkHeight);
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
{
x = x + xChange;
y = y + yChange;
if (x >= picDisplayBat.Width)
xChange = -xChange;
if (y >= picDisplayBat.Height)
yChange = -yChange;
if (x <= 0)
xChange = -xChange;
if (y <= 0)
yChange = -yChange;
if ((y > picDisplayBat.Height - 20) && (x >= batX + 10) && (x <= batX + 50))
yChange = -yChange;
if ((y < picDisplayBat.Height - 295) && (x >= batX + 10) && (x <= batX + 50))
yChange = -yChange;
for (int i = 0; 1 < brickLive.Length; i++)
if ((y == brickLocation[i, 0]) && (x >= brickLocation[0, i]) && (x <= (brickLocation[0, i] + 60)))
yChange = -yChange;
paper.Clear(Color.White);
paper.DrawRectangle(pen, mouseX + 10, picDisplayBat.Height - 20, 50, 10); //bat 1
paper.DrawEllipse(pen, x, y, 10, 10); //ball
paper.DrawRectangle(pen2, mouseX + 10, picDisplayBat.Height - 295, 50, 10); //bat2
//paper.DrawRectangle(pen3, x2, y2, 60, 10);
bat = mouseX;
batX = mouseX;
batXX = mouseX;
for (int i = 0; i < brickLive.Length; i++)
{
paper.DrawRectangle(brkpen, brickLocation[i, 0], brickLocation[i, 1], brkLength, brkHeight);
}
}
}
private void btnExit_Click(object sender, EventArgs e)
{
Environment.Exit(0);
}
private void btnStop_Click(object sender, EventArgs e)
{
timer1.Enabled = false;
paper.Clear(Color.White);
}
}
}
This looks wrong to me.
if ((y == brickLocation[i, 0])
&& (x >= brickLocation[0, i])
&& (x <= (brickLocation[0, i] + 60)))
It seems to me you should always have [i, ... for the brick array position, so either [i, 0] for tests against the horizontal component and [i, 1] for the vertical component.
I am working with the XBox-Kinect (Beta SDK).
I try to direct a robot to grab an object from a box that contains many objects (bachelorthesis), for that I need to find the closest point of the nearest object to the kinect. Than i can localize the complete object by region growing and find out the grabbing point for the robot.
Now I have two question for that topic:
How can I find out the x and y coordinate of this point? ( I have the distance already)
How can I access the private byte[] FindMinimum(ImageFrame imageFrame)
by button click to find the closest distance?
Here is my code:
void nui_DepthFrameReady(object sender, ImageFrameReadyEventArgs e)
{
image1.Source = e.ImageFrame.ToBitmapSource();
byte[] Minumum = FindMinimum(e.ImageFrame);
}
private void button1_Click(object sender, RoutedEventArgs e)
{
FindMinimum();
}
private byte[] FindMinimum(ImageFrame imageFrame)
{
int height = imageFrame.Image.Height;
int width = imageFrame.Image.Width;
Byte[] depthData = imageFrame.Image.Bits;
Byte[] colorFrame = new byte[imageFrame.Image.Height * imageFrame.Image.Width * 4];
int min = int.MaxValue, max = int.MinValue;
for (int i = 0; i < depthData.Length; i += 2)
{
int dist = GetDistance(depthData[i], depthData[i + 1]);
if (dist < min && dist > 0) min = dist;
if (dist > max) max = dist;
}
textBox1.Text = Convert.ToString(min);
return colorFrame;
}
private int GetDistance(byte firstFrame, byte secondFrame)
{
int distance = (int)(firstFrame | secondFrame << 8);
return distance;
}
private void Window_Closed(object sender, EventArgs e)
{
nui.Uninitialize();
}
}
}
How do i draw this more efficiently?
I can feel the lag when i call the code below. NOTE this is about pixel editing and not clearing the screen.
int colorIndex = 0;
private void pictureBox1_Click(object sender, EventArgs e)
{
if (colorIndex == 0)
draw(Color.DimGray);
else if(colorIndex ==1)
draw(Color.ForestGreen);
colorIndex++;
colorIndex = colorIndex % 2;
pictureBox1.Invalidate();
//pictureBox1.Update();
}
void draw(Color c)
{
//var bdata = b.LockBits(Rectangle.Empty, System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
//var px = bdata.Scan0;
var px = b;
{
for (int y = 0; y < b.Height; y++)
{
for (int x = 0; x < b.Width; x++)
//px[y * b.Width + x] = -1;
px.SetPixel(x, y, c);
}
}
//b.UnlockBits(bdata);
}
Have you enable double buffering?
btw, If you are just drawing rectangle, you can use the DrawRectangle method.
How about:
void draw(Color c) {
using (Graphics g = Graphics.FromImage(b)) {
g.Clear(c);
}
}
SetPixel/GetPixel are generally slow operations. If you can use unsafe code (code which uses pointers), there are faster methods of access, but they're slightly more involved. There is a tutorial here which explains how it works, however:
http://www.codeproject.com/KB/GDI-plus/csharpgraphicfilters11.aspx