I have created a image button for my apps on windows mobile. There is a small problem though, when i have different screen resolutions,bigger for example, the image isn't automatic resized to fit in the control. How can this be done?
thanks in advance.
this is my code for the onPaint function
Dim gxOff As Graphics
'Offscreen graphics
Dim imgRect As Rectangle
'image rectangle
Dim backBrush As Brush
'brush for filling a backcolor
If m_bmpOffscreen Is Nothing Then
'Bitmap for doublebuffering
m_bmpOffscreen = New Bitmap(Me.Width, Me.Height)
End If
gxOff = Graphics.FromImage(m_bmpOffscreen)
gxOff.Clear(Me.BackColor)
If Not bPushed Then
backBrush = New SolidBrush(Parent.BackColor)
Else
backBrush = New SolidBrush(Color.Black)
'change the background when it's pressed
End If
gxOff.FillRectangle(backBrush, Me.ClientRectangle)
If m_image IsNot Nothing Then
'Center the image relativelly to the control
Dim imageLeft As Integer = (Me.Width - m_image.Width) / 2
Dim imageTop As Integer = (Me.Height - m_image.Height) / 2
If Not bPushed Then
imgRect = New Rectangle(imageLeft, imageTop, m_image.Width, m_image.Height)
Else
'The button was pressed
'Shift the image by one pixel
imgRect = New Rectangle(imageLeft + 1, imageTop + 1, m_image.Width, m_image.Height)
End If
'Set transparent key
Dim imageAttr As New Imaging.ImageAttributes()
imageAttr.SetColorKey(BackgroundImageColor(m_image), BackgroundImageColor(m_image))
'Draw image
gxOff.DrawImage(m_image, imgRect, 0, 0, m_image.Width, m_image.Height, GraphicsUnit.Pixel, imageAttr)
End If
If bPushed Then
'The button was pressed
'Prepare rectangle
Dim rc As Rectangle = Me.ClientRectangle
rc.Width -= 1
rc.Height -= 1
'Draw rectangle
gxOff.DrawRectangle(New Pen(Color.Black), rc)
End If
'Draw from the memory bitmap
e.Graphics.DrawImage(m_bmpOffscreen, 0, 0)
MyBase.OnPaint(e)
You need to scale image during OnPaint e.g.:
if (this._image != null)
{
int x = (this.Width - this._image.Width) / 2;
int y = (this.Height - this._image.Height) / 2;
var imgRect = new Rectangle(x, y, this._image.Width, this._image.Height);
var imageAttr = new ImageAttributes();
Color clr = this._image.GetPixel(0, 0);
imageAttr.SetColorKey(clr, clr);
gr2.DrawImage(this._image, imgRect, 0, 0, this._image.Width, this._image.Height, GraphicsUnit.Pixel, imageAttr);
}
Above example is how to draw image with transparent color based on first pixel. Now you need to ammend second 3 lines:
bool qvga = Screen.PrimaryScreen.Bounds.Height == 240 || Screen.PrimaryScreen.Bounds.Width == 240;
int x = (this.Width - (qvga ? this._image.Width : this._image.Width * 2)) / 2;
int y = (this.Height - (qvga ? this._image.Height : this._image.Height * 2)) / 2;
var imgRect = new Rectangle(x, y, (qvga ? this._image.Width : this._image.Width * 2), (qvga ? this._image.Height : this._image.Height * 2));
[Edit]
Seeing your code change is straight forward. Like I described in comment: For two main windows mobile resolutions, QVGA and VGA, we assuming that image is for QVGA size. Please convert my code to VB by yourself. So set qvga flag as I written:
bool qvga = Screen.PrimaryScreen.Bounds.Height == 240 || Screen.PrimaryScreen.Bounds.Width == 240;
now based on flag ammend following based on my above code:
Dim imageLeft As Integer = (Me.Width - m_image.Width) / 2
Dim imageTop As Integer = (Me.Height - m_image.Height) / 2
and then this ones:
If Not bPushed Then
imgRect = New Rectangle(imageLeft, imageTop, m_image.Width, m_image.Height)
Else
'The button was pressed
'Shift the image by one pixel
imgRect = New Rectangle(imageLeft + 1, imageTop + 1, m_image.Width, m_image.Height)
End If
Related
UPDATE as on 12 Nov 2015
I used PanoTools plugin with Photoshop and Hugin and played with all those parameters. End up i found the parameters for projection, HFOV and image output size that fulfill my lowest requirement.
Parameteres:
Processed Output:
My question is then how can i convert all these parameters and values into C# algorithm coding so that when I provide the original image, i will get the corrected output image?
Thanks a lot.
I have a square image captured from a circular fisheye camera. The size is 2650 * 2650 pixels.
Now, i will need to programmatically dewarp the image to a flat panorama image using C# language.
I had look around from internet with different algorithm example from Link for code below , Link1 and Link2 but just can't make it success. My maths sincerely sucks and can't help me with that. Hopefully someone able to guide me through this.
Thanks a lot.
Example of image output from the camera:
--Image grabbed from Wikipedia Fisheye Lens & size modified to fit my sample pixel.
The code i tried to dewarp it but no luck:
Bitmap sourceImage = (Bitmap)Bitmap.FromFile("circularfisheye.jpg");
double factor = 0.5;
Boolean autoCrop = false;
Color backgroundColor = Color.White;
Bitmap StartImage = null;
BitmapData srcBitmapData = null;
Byte[] srcPixels = null;
Byte[] dstPixels = null;
Bitmap NewImage = null;
BitmapData dstBitmapData = null;
try
{
// Checks whether bpp ( Bits Per Pixel ) is 8 , 24, or 32
int Depth = System.Drawing.Bitmap.GetPixelFormatSize(sourceImage.PixelFormat);
if (Depth != 8 && Depth != 24 && Depth != 32)
{
throw new ArgumentException("Only 8, 24 and 32 bpp images are supported.");
}
// Retrieves the count of the color components
int cCount = Depth / 8;
Size baseSize = new Size(sourceImage.Width, sourceImage.Height);
// check if a low image resize and need to improve the quality
// and not generate image aliasing
Int32 maxSize = Math.Max(sourceImage.Width, sourceImage.Height);
if (maxSize < 3000)
{
float percent = 3000F / (float)maxSize;
baseSize = new Size((Int32)((float)sourceImage.Width * percent), (Int32)((float)sourceImage.Height * percent));
}
StartImage = new Bitmap(baseSize.Width, baseSize.Height, sourceImage.PixelFormat);
StartImage.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
// Create the drawing object and white background
Graphics g = Graphics.FromImage(StartImage);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawImage(sourceImage, new Rectangle(-1, -1, baseSize.Width + 1, baseSize.Height + 1), 0, 0, sourceImage.Width, sourceImage.Height, GraphicsUnit.Pixel);
g.Dispose();
// Locks the source image and copies it to the byte array and releases the source image
srcBitmapData = StartImage.LockBits(new Rectangle(0, 0, StartImage.Width, StartImage.Height), ImageLockMode.ReadOnly, StartImage.PixelFormat);
srcPixels = new byte[StartImage.Width * StartImage.Height * (Depth / 8)];
Marshal.Copy(srcBitmapData.Scan0, srcPixels, 0, srcPixels.Length);
StartImage.UnlockBits(srcBitmapData);
srcBitmapData = null;
// Create the target image byte array
dstPixels = new Byte[srcPixels.Length];
// Fill the entire frame with the selected background color
Int32 index = ((1 * StartImage.Width) + 1) * cCount; //index = ((Y * Width) + X) * cCount
do
{
if (Depth == 32) //For 32 bpp defines Red , Green, Blue and Alpha
{
dstPixels[index++] = backgroundColor.B;
dstPixels[index++] = backgroundColor.G;
dstPixels[index++] = backgroundColor.R;
dstPixels[index++] = backgroundColor.A; // a
}
if (Depth == 24) //For 24 bpp defines Red , Green and Blue
{
dstPixels[index++] = backgroundColor.B;
dstPixels[index++] = backgroundColor.G;
dstPixels[index++] = backgroundColor.R;
}
if (Depth == 8)
// For 8 bpp defines the value of color ( Red , Green and Blue to be the same thing)
{
dstPixels[index++] = backgroundColor.B;
}
} while (index < srcPixels.Length);
// Calculate the maximum possible extent for the image and multiply by the desired factor
double amp = 0;
double ang = Math.PI * 0.5;
for (Int32 a = 0; a < StartImage.Height; a++)
{
int y = (int)((StartImage.Height / 2) - amp * Math.Sin(ang));
if ((y < 0) || (y > StartImage.Height))
break;
amp = a;
}
amp = (amp - 2) * (factor < -1 ? -1 : (factor > 1 ? 1 : factor));
// Define variables that calculates the cutoff points (if any)
Int32 x1, y1, x2, y2;
x1 = StartImage.Width;
y1 = StartImage.Height;
x2 = 0;
y2 = 0;
// Copy pixel by pixel for the new positions
index = ((1 * StartImage.Width) + 1) * cCount;
do
{
Int32 y = (Int32)((index / cCount) / StartImage.Width);
Int32 x = (index / cCount) - (y * StartImage.Width);
Point pt = NewPoint(new Point(x, y), StartImage.Width, StartImage.Height, amp, factor < 0);
//Values for crop
if (factor >= 0)
{
if (x == StartImage.Width / 2)
{
if (pt.Y < y1)
y1 = pt.Y;
if (pt.Y > y2)
y2 = pt.Y;
}
if (y == StartImage.Height / 2)
{
if (pt.X < x1)
x1 = pt.X;
if (pt.X > x2)
x2 = pt.X;
}
}
else
{
if ((x == 1) && (y == 1))
{
y1 = pt.Y;
x1 = pt.X;
}
if ((x == StartImage.Width - 1) && (y == StartImage.Height - 1))
{
y2 = pt.Y;
x2 = pt.X;
}
}
//Bytes Index which will apply the pixel
Int32 dstIndex = ((pt.Y * StartImage.Width) + pt.X) * cCount;
if (Depth == 32)
{
dstPixels[dstIndex] = srcPixels[index++];
dstPixels[dstIndex + 1] = srcPixels[index++];
dstPixels[dstIndex + 2] = srcPixels[index++];
dstPixels[dstIndex + 3] = srcPixels[index++]; // a
}
if (Depth == 24)
{
dstPixels[dstIndex] = srcPixels[index++];
dstPixels[dstIndex + 1] = srcPixels[index++];
dstPixels[dstIndex + 2] = srcPixels[index++];
}
if (Depth == 8)
{
dstPixels[dstIndex] = srcPixels[index++];
}
} while (index < srcPixels.Length);
//Creates a new image based on the byte array previously created
NewImage = new Bitmap(StartImage.Width, StartImage.Height, StartImage.PixelFormat);
NewImage.SetResolution(StartImage.HorizontalResolution, StartImage.VerticalResolution);
dstBitmapData = NewImage.LockBits(new Rectangle(0, 0, StartImage.Width, StartImage.Height), ImageLockMode.WriteOnly, StartImage.PixelFormat);
Marshal.Copy(dstPixels, 0, dstBitmapData.Scan0, dstPixels.Length);
NewImage.UnlockBits(dstBitmapData);
//Generates the final image to crop or resize the real coo
Bitmap FinalImage = new Bitmap(sourceImage.Width + 1, sourceImage.Height, StartImage.PixelFormat);
NewImage.SetResolution(StartImage.HorizontalResolution, StartImage.VerticalResolution);
Graphics g1 = Graphics.FromImage(FinalImage);
g1.SmoothingMode = SmoothingMode.AntiAlias;
g1.InterpolationMode = InterpolationMode.HighQualityBicubic;
g1.PixelOffsetMode = PixelOffsetMode.HighQuality;
//Performs the cut if enabled automatic cutting and there is need to cut
if ((autoCrop) && ((x1 > 0) || (y1 > 0) || (x2 < NewImage.Height) || (y2 < NewImage.Height)))
{
Rectangle cropRect = new Rectangle(x1, y1, x2 - x1, y2 - y1);
g1.DrawImage(NewImage, new Rectangle(-1, -1, FinalImage.Width + 1, FinalImage.Height + 1), cropRect.X, cropRect.Y, cropRect.Width, cropRect.Height, GraphicsUnit.Pixel);
}
else
{
g1.DrawImage(NewImage, new Rectangle(-1, -1, FinalImage.Width + 1, FinalImage.Height + 1), 0, 0, NewImage.Width, NewImage.Height, GraphicsUnit.Pixel);
}
g1.Dispose();
g1 = null;
NewImage = null;
FinalImage.Save("output.jpg");
FinalImage.Dispose();
}
finally
{
srcBitmapData = null;
srcPixels = null;
dstPixels = null;
dstBitmapData = null;
}
Such a distortion as a symmetry of revolution.
In polar coordinates, with the pole at the center of the image, it is expressed as
r' = f(r)
Θ' = Θ
where the quote indicates the distorted coordinates. The function f is unknown and should be measured empirically, by calibration (looking at a regular target).
To correct the image, you need to invert the function f and apply the reverse transform to the image. In fact, it is easier to measure g directly by calibration. As a starting approximation, a simple model like
r = r' + a.r'³
can do.
Most probably you don't have a picture of a grid taken with the same lens. Your last resort is to implement the undistortion function with adjustable parameters, and optimize these by trial and error.
It should also be possible to derive the calibration curve by looking at the deformation of straight lines, but this is more "technical".
In Cartesian coordinates, you can express the correction transform as
x = g(r').x'/r'
y = g(r').y'/r'
where r' = √x'²+y'².
Use the algorithm from here:
http://www.helviojunior.com.br/fotografia/barrel-and-pincushion-distortion/
It worked for me
I've made some revamp to the HelvioJunior's library (that was linked by #Tarek.Mh), I think this may suit your need:
Below, the code:
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using static System.Math;
namespace HelvioJunior
{
//https://www.helviojunior.com.br/fotografia/barrel-and-pincushion-distortion/
public class Program
{
private static void Main(string[] args)
{
Bitmap source = (Bitmap)Image.FromFile(#"JpwX0.png");
Bitmap bmp = BarrelDistortion(source, 4/10f, true);
bmp.Save(#"test.png");
bmp.Dispose();
source.Dispose();
}
static public Bitmap BarrelDistortion(Bitmap sourceImage, double factor = 0, bool autoCrop = true, uint previewRectangleWidth = 0, Color? fillerColor = null)
{
int sourceRight = sourceImage.Width - 1, sourceBottom = sourceImage.Height - 1;
// Vertical amplitude is half the height times factor
// Horizontal amplitude is missing ; vertical amplitude's applied to both directions
double amp = sourceBottom / 2f * factor;
// Inner shrinking area points
RePoint[] lPts;
bool inverse = factor < 0;
// Shrinking area coordinates (center point is considered always available)
double x1 = sourceRight / 2f,
y1 = sourceBottom / 2f,
x2 = sourceRight / 2f,
y2 = sourceBottom / 2f;
if (inverse)
{
lPts = new RePoint[]
{
new RePoint(0, 0),
new RePoint(0, sourceBottom),
new RePoint(sourceRight, sourceBottom),
new RePoint(sourceRight, 0)
};
}
else
{
lPts = new RePoint[]
{
new RePoint(sourceRight * 1 / 2f, 0),
new RePoint(0, sourceBottom * 1 / 2f),
new RePoint(sourceRight, sourceBottom * 1 / 2f),
new RePoint(sourceRight * 1 / 2f, sourceBottom)
};
}
foreach (var pN in lPts.Select(pt => NewPoint(pt, sourceImage.Width, sourceImage.Height, amp, inverse)))
{
if (pN.Y < y1) y1 = pN.Y;
if (pN.Y > y2) y2 = pN.Y;
if (pN.X < x1) x1 = pN.X;
if (pN.X > x2) x2 = pN.X;
}
// Bytes per color from bit per pixel (bpp) format
int bpcCount = Image.GetPixelFormatSize(sourceImage.PixelFormat) / 8;
Rectangle sourceRectangle = new Rectangle(0, 0, sourceImage.Width, sourceImage.Height);
int srcLength = sourceImage.Width * sourceImage.Height * bpcCount;
// Gets sourceImage byte array as srcpixels
BitmapData srcBitmapData = sourceImage.LockBits(sourceRectangle, ImageLockMode.ReadOnly, sourceImage.PixelFormat);
byte[] srcPixels = new byte[srcLength];
Marshal.Copy(srcBitmapData.Scan0, srcPixels, 0, srcLength);
sourceImage.UnlockBits(srcBitmapData);
srcBitmapData = null;
// Destination byte array preparation as dstPixels
byte[] dstPixels = new byte[srcLength];
int dstIndex = 0;
// Filler color preparation
Color fillColor = fillerColor ?? Color.Transparent;
if (!autoCrop)
{
if (bpcCount <= 4) // Depth > 32bpp may not work as expected, filler color's not applied for bit safety reason
do
{
dstPixels[dstIndex++] = fillColor.B;
if (bpcCount > 1)
{
dstPixels[dstIndex++] = fillColor.G;
dstPixels[dstIndex++] = fillColor.R;
if (bpcCount > 3)
dstPixels[dstIndex++] = fillColor.A; // a
}
} while (dstIndex < srcLength);
}
// Byte-to-byte copy (incl. Point transformation)
int index = 0, srcBpcLength = srcLength - bpcCount;
do
{
int comp = index / bpcCount; // comp yields the current "pixel" position
int y = comp / sourceImage.Width; // Each line is sourceImage.Width bytes wide
int x = comp - (y * sourceImage.Width); // Remaining (comp - lines) bytes is target column (ranges from 0 to width - 1)
// Destination "pixel"
RePoint pt = NewPoint(new RePoint(x, y), sourceImage.Width, sourceImage.Height, amp, inverse);
dstIndex = (((int)pt.Y * sourceImage.Width) + (int)pt.X) * bpcCount; // dstIndex++ overflows when |amp| >= 2
if (dstIndex >= 0 && dstIndex <= srcBpcLength)
for (int i = 0; i++ < bpcCount;)
dstPixels[dstIndex++] = srcPixels[index++];
else
index += bpcCount;
} while (index < srcLength);
srcPixels = null;
// Destination bytes application
BitmapData dstBitmapData = sourceImage.LockBits(sourceRectangle, ImageLockMode.WriteOnly, sourceImage.PixelFormat);
Marshal.Copy(dstPixels, 0, dstBitmapData.Scan0, srcLength);
sourceImage.UnlockBits(dstBitmapData);
dstBitmapData = null;
dstPixels = null;
// Final Image area
Rectangle cropRect = new Rectangle((int)Ceiling(x1), (int)Ceiling(y1), (int)Ceiling(x2 - x1), (int)Ceiling(y2 - y1));
Rectangle destRectangle = autoCrop ? cropRect : sourceRectangle;
// Final image preparation
Bitmap FinalImage = new Bitmap(destRectangle.Width, destRectangle.Height, sourceImage.PixelFormat);
FinalImage.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
Graphics g1 = Graphics.FromImage(FinalImage);
g1.DrawImage(sourceImage, -destRectangle.X, -destRectangle.Y);
// Previsualization rectangle
if (previewRectangleWidth > 0)
g1.DrawRectangle(new Pen(Color.Red, previewRectangleWidth), cropRect.X - 1, cropRect.Y - 1, cropRect.Width + previewRectangleWidth, cropRect.Height + previewRectangleWidth);
g1.Dispose();
g1 = null;
return FinalImage;
}
private static RePoint NewPoint(RePoint aP, double Width, double Height, double Amplitude, bool inverse)
{
double h = aP.Y / (Height - 1);
double w = aP.X / (Width - 1);
// Works ok for [0/2] to [1/2]
// Floating point error(s) here, in the range of ]1/2] to [2/2] (No workaround found)
double sinX = Round(Sin(PI * w), 15); // Range of [0] to [1] * PI ; result ranges from 0 (far from center) to 1 (at center)
double sinY = Round(Sin(PI * h), 15);
double caX = Amplitude * (1 - 2 * w);
double caY = Amplitude * (1 - 2 * h);
double aY = 0, aX = 0;
if (inverse)
{
aX = -caX;
aY = -caY;
}
double pY = aP.Y + aY + caY * sinX;
double pX = aP.X + aX + caX * sinY;
return new RePoint(pX, pY);
}
private struct RePoint
{
public double X;
public double Y;
public RePoint(double x, double y)
{
X = x;
Y = y;
}
}
}
}
I have a method that takes in a bitmap object and overlays dates and times strings over it and returns that new bitmap. The code is below.
public static Bitmap overlayBitmap(Bitmap sourceBMP, int width, int height, List<String> times, List<String> dates, IEnumerable<Color> colors) {
// Determine the new width
float newWidth = width + (width / 3.0f);
float newHeight = height + (height / 3.0f);
// Intelligent vertical + horizontal text distance calculator
float verticalDistance = height / (times.Count - 1.0f);
float horizontalDistance = width / (dates.Count - 1.0f);
Bitmap result = new Bitmap((int)newWidth, (int)newHeight);
using (Graphics g = Graphics.FromImage(result)) {
// Background color
Brush brush = new SolidBrush(colors.First());
g.FillRectangle(brush, 0, 0, newWidth, newHeight);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
// Times text configs
StringFormat stringFormatTimes = new StringFormat();
stringFormatTimes.LineAlignment = StringAlignment.Center;
stringFormatTimes.Alignment = StringAlignment.Center;
Font drawFontY = new Font("Whitney", newHeight / 70);
// Dates text configs
StringFormat stringFormatDates = new StringFormat();
stringFormatDates.LineAlignment = StringAlignment.Center;
stringFormatTimes.Alignment = StringAlignment.Center;
stringFormatDates.FormatFlags = StringFormatFlags.DirectionVertical;
Font drawFontX = new Font("Whitney", newHeight / 70);
// Location of times text
for (int i = 0; i < times.Count; i++) {
if (i % determineIncrementTimes(times.Count) == 0) {
g.DrawString(times[i], drawFontX, Brushes.White, (((newWidth - width) / 2) / 2), ((newHeight - height) / 2) + (verticalDistance * i), stringFormatTimes);
}
}
// Location of dates text
for (int i = 0; i < dates.Count; i++) {
if (i % determineIncrementDates(dates.Count) == 0) {
g.DrawString(dates[i], drawFontY, Brushes.White, ((newWidth - width) / 2) + (horizontalDistance * i), ((newHeight - height) / 2) + height, stringFormatDates);
}
}
// New X and Y Position of the sourceBMP within the new BMP.
int XPos = width / 6;
int YPos = height / 6;
// Int -> Float casting for the outline
float fXPos = width / 6.0f;
float fYPos = height / 6.0f;
float fWidth = width / 1.0f;
float fHeight = height / 1.0f;
// Draw new image at the position width/6 and height/6 with the size at width and height
g.DrawImage(sourceBMP, fXPos, fYPos, fWidth, fHeight);
g.DrawRectangle(Pens.White, fXPos, fYPos, fWidth, fHeight); // white outline
g.Dispose();
}
return result;
}
My concern is, I would like to be able, for the next developer, to easily access and set particular values that currently I've only "hardcoded" in. An example being the x-position of the time text calculated via this snippet of code:
(((newWidth - width) / 2) / 2)
Realistically I'd like to have the developer be able to access and/or set this value through simply typing in:
something.XPos = [someFloat];
How my method above is used (is pseudo-code) is as the following:
private readonly Bitmap _image;
private readonly Bitmap _overlayedImage;
public myConstructor(int someInputValues){
// some code that generates the first bitmap called _image
_newImage = overlayImage(_image, ....);
}
For reference this is the image drawn:
My question is - since some values need to be casted and initialized first, can I set my instance variables at the end of the method, before the closing brace?
public Bitmap overlayBitmap
{
get
{
// Build bitmap overlay
return overlayBitmapOutput;
}
...
}
[Edit: Answer Insufficient >> Wait]
I am hoping someone can help. In my software I have dynamic Data Grid Views, which all share the common grd name when being made. Each placed into dynamic tabs. All works fine, but I wanted to add an image to the Grid Row Header. There are examples on here for non dynamic grid views, but not for dynamic, so I adapted and used the following code:
private void grd_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
if (e.InheritedRowStyle.BackColor == Color.Gold)
{
Bitmap myBitmap = new Bitmap(imageList1.Images[0]);
Icon myIcon = Icon.FromHandle(myBitmap.GetHicon());
Graphics graphics = e.Graphics;
//Set Image dimension - Users choice
int iconHeight = 16;
int iconWidth = 32;
//Set x/y position - As the center of the RowHeaderCell
int xPosition = ((e.RowBounds.Height * 2) - iconWidth) / 2;
int yPosition = ((e.RowBounds.Y + (e.RowIndex * e.RowBounds.Height) - iconHeight) / 2)+ e.RowBounds.Height + 1;
Rectangle rectangle = new Rectangle(xPosition, yPosition, iconWidth, iconHeight);
graphics.DrawIcon(myIcon, rectangle);
}
else if (e.InheritedRowStyle.BackColor == Color.PowderBlue)
{
Bitmap myBitmap = new Bitmap(imageList1.Images[1]);
Icon myIcon = Icon.FromHandle(myBitmap.GetHicon());
Graphics graphics = e.Graphics;
//Set Image dimension - Users choice
int iconHeight = 16;
int iconWidth = 16;
//Set x/y position - As the center of the RowHeaderCell
int xPosition = ((e.RowBounds.Height * 2) - iconWidth) / 2;
int yPosition = ((e.RowBounds.Y + (e.RowIndex * e.RowBounds.Height) - iconHeight) / 2) + e.RowBounds.Height + 1;
Rectangle rectangle = new Rectangle(xPosition, yPosition, iconWidth, iconHeight);
graphics.DrawIcon(myIcon, rectangle);
}
else if (e.InheritedRowStyle.BackColor == Color.YellowGreen)
{
//Convert the image to icon, inorder to load it in the row header column
Bitmap myBitmap = new Bitmap(imageList1.Images[2]);
Icon myIcon = Icon.FromHandle(myBitmap.GetHicon());
Graphics graphics = e.Graphics;
//Set Image dimension - Users choice
int iconHeight = 16;
int iconWidth = 16;
//Set x/y position - As the center of the RowHeaderCell
int xPosition = ((e.RowBounds.Height *2) - iconWidth) / 2;
int yPosition = ((e.RowBounds.Y + (e.RowIndex * e.RowBounds.Height) - iconHeight) / 2) + e.RowBounds.Height + 1;
Rectangle rectangle = new Rectangle(xPosition, yPosition, iconWidth, iconHeight);
graphics.DrawIcon(myIcon, rectangle);
}
else if (e.InheritedRowStyle.BackColor == Color.White)
{
//Convert the image to icon, inorder to load it in the row header column
Bitmap myBitmap = new Bitmap(imageList1.Images[3]);
Icon myIcon = Icon.FromHandle(myBitmap.GetHicon());
Graphics graphics = e.Graphics;
//Set Image dimension - Users choice
int iconHeight = 16;
int iconWidth = 16;
//Set x/y position - As the center of the RowHeaderCell
int xPosition = ((e.RowBounds.Height * 2) - iconHeight) / 2;
int yPosition = ((e.RowBounds.Y + (e.RowIndex * e.RowBounds.Height) - iconHeight) / 2) + e.RowBounds.Height + 1;
Rectangle rectangle = new Rectangle(xPosition, yPosition, iconWidth, iconHeight);
graphics.DrawIcon(myIcon, rectangle);
}
}
And I am calling this code from a place in the code after the searching is completed and the data sent to the grid using:
grd.RowPostPaint += new System.Windows.Forms.DataGridViewRowPostPaintEventHandler(this.grd_RowPostPaint);
There is a problem however when the software runs maximized the images display ok, when it runs at any size other than the only time they display is on mouseover (not coded that way it just happends that way) and when I scroll they disappear at the bottom of the grid ... any ideas what I am doing wrong (I am not a coder with much experience ... please be kind).
I am making an Analogue Clock in which i have to rotate the image in my pictureBox...
e.g. i want to rotate my image by 6 degrees every second.
what can i do for this?
Thanks....
I remember ever writing a Clock-like UserControl some time ago. Here's the fundamental code to do your request.
Private Sub Paint_Clock(ByVal sender As Object, _
ByVal e As System.Windows.Forms.PaintEventArgs) _
Handles Clock.Paint
Dim _independentHands as Boolean = False
Dim g As Graphics = e.Graphics
Dim centrePoint As Point = New Point(Clock.Width \ 2, Clock.Height \ 2)
Dim _time As New TimeSpan(5, 2, 15)
'pens'
Dim hourPen As New Pen(Color.Black, 3)
Dim minPen As New Pen(Color.Black, 2)
Dim secPen As New Pen(Color.Red, 1)
'clock hand lengths'
Dim halfClockWidth As Integer = Clock.Width \ 2
Dim hourLength As Integer = CInt(halfClockWidth * (4 / 6)) - 5
Dim minLength As Integer = CInt(halfClockWidth * (5 / 6)) - 5
Dim secLength As Integer = CInt(halfClockWidth * (5 / 6)) - 5
Dim secLength2 As Integer = CInt(halfClockWidth * (1 / 6))
'angles'
Dim secAngle As Single = CSng(_time.Seconds / 60) * 360
Dim secAngle2 As Single = secAngle - 180
Dim minAngle As Single = CSng(_time.Minutes / 60) * 360
Dim hrAngle As Single = CSng((_time.Hours - 12) / 12) * 360
If Not _independentHands Then minAngle += (secAngle / 60)
If Not _independentHands Then hrAngle += (minAngle / 12)
'centre point'
Dim pointPen As New Pen(Color.Black, 4)
Dim pointRect As New Rectangle(centrePoint.X - 2, centrePoint.Y - 2, 4, 4)
'antialias on'
g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
'draw the background'
g.DrawImage(My.Resources.ClockBack, 0, 0, Clock.Width, Clock.Height)
'draw the hands'
g.DrawLine(hourPen, centrePoint, GetPoint2(centrePoint, hrAngle, hourLength))
g.DrawLine(minPen, centrePoint, GetPoint2(centrePoint, minAngle, minLength))
g.DrawLine(secPen, centrePoint, GetPoint2(centrePoint, secAngle, secLength))
g.DrawLine(secPen, centrePoint, GetPoint2(centrePoint, secAngle2, secLength2))
'draw the centre point'
g.DrawEllipse(pointPen, pointRect)
'draw the glass'
g.DrawImage(My.Resources.ClockGlass, 0, 0, Clock.Width, Clock.Height)
End Sub
Private Function GetPoint2(ByVal startPoint As Point, _
ByVal angle As Single, _
ByVal length As Integer) As Point
Dim x, y As Integer
Dim sp As Point = startPoint
'normalize'
Do While angle - 360 > 0
angle -= 360
Loop
Do While angle < 0
angle += 360
Loop
If angle = 360 Then angle = 0
Dim rad = angle * (Math.PI / 180) 'angle in radians'
'calc the new point'
x = CInt(length * Math.Sin(rad))
y = CInt(length * Math.Cos(rad))
Return New Point(sp.X + x, sp.Y - y)
End Function
Notes
1. Add a PictureBox with the name Clock to your form (or usercontrol)
2. Add a resource called ClockBack for the background of your clock (the clock's face).
3. Add a resource called ClockGlass for the clock's glassy face.
4. Drop the code above in your form.
5. Set a timer's interval to 1000 and have its Tick event Refresh or Invalidate the Clock [which is a PictureBox].
Please note that the variable _independentHands makes the clock's hands independent of each other when set to true.
For example, when set to False, 4:30 will have the hour hand halfway between 4 and 5. When True, the hour hand will be on 4 up till 4:59:59 and will 'jump' to 5 at 5:00:00.
I prefer to leave it to false so as to give the natural clock feel.
Here below links for question
C# Image/PictureBox Rotations - CodeProject
Rotating PictureBox Control - CodeProject
try this
pictureBox1.Image.RotateFlip((RotateFlipType.Rotate90FlipX));
or rotate this in a thread per 1000 ms
I'm searching for a button control that will AutoSize its image. Normal button controls won't do this. I'm using C#.Net 2.0.
For example, I have a Button that is 200 x 50px and an image that is 800 x 100px. I want to resize the Image so that it is a little to the left, near the text of the button. With a PictureBox I can do this. But when I lay a PictureBox over the Button its very ugly because you can't click there.
You can do this as follows:
button.Image = Image.FromFile(path);
button.AutoSize = true;
E.g: Or, You can create a new Button type that will change the size of the image:
public class AutoSizeButton : Button
{
public new Image Image
{
get { return base.Image; }
set
{
Image newImage = new Bitmap(Width, Height);
using (Graphics g = Graphics.FromImage(newImage))
{
g.DrawImage(value, 0, 0, Width, Height);
}
base.Image = newImage;
}
}
}
Test:
AutoSizeButton button = new AutoSizeButton();
button.Location = new Point(27, 52);
button.Name = "button";
button.Size = new Size(75, 23);
button.Text = "Test";
button.UseVisualStyleBackColor = true;
button.Image = Image.FromFile(path);
Controls.Add(button);
I was looking for a version of this in vb.net, so I started with mykhaylo's answer and improved it a bit. This code resizes the image to fit proportionally, centers the image in the button, and provides inner padding for the image.
This button actually does not use the "Image" property of the button and exposes a property "AutoScaleImage" that should be set alternately.
Here is the C# version - VB.net at bottom. Enjoy!
[System.ComponentModel.DesignerCategory("")]
public class AutoScaleButton : Button
{
private Image _AutoScaleImage;
public Image AutoScaleImage {
get { return _AutoScaleImage; }
set {
_AutoScaleImage = value;
if (value != null)
this.Invalidate();
}
}
private int _AutoScaleBorder;
public int AutoScaleBorder {
get { return _AutoScaleBorder; }
set {
_AutoScaleBorder = value;
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
DrawResizeImage(ref e.Graphics);
}
private void DrawResizeImage(Graphics g)
{
if (_AutoScaleImage == null)
return;
int iB = AutoScaleBorder;
int iOff = 0;
Rectangle rectLoc = default(Rectangle);
Rectangle rectSrc = default(Rectangle);
Size sizeDst = new Size(Math.Max(0, this.Width - 2 * iB),
Math.Max(0, this.Height - 2 * iB));
Size sizeSrc = new Size(_AutoScaleImage.Width,
_AutoScaleImage.Height);
double ratioDst = sizeDst.Height / sizeDst.Width;
double ratioSrc = sizeSrc.Height / sizeSrc.Width;
rectSrc = new Rectangle(0, 0, sizeSrc.Width, sizeSrc.Height);
if (ratioDst < ratioSrc) {
iOff = (sizeDst.Width -
(sizeDst.Height * sizeSrc.Width / sizeSrc.Height)) / 2;
rectLoc = new Rectangle(iB + iOff,
iB,
sizeDst.Height * sizeSrc.Width / sizeSrc.Height,
sizeDst.Height);
} else {
iOff = (sizeDst.Height - (sizeDst.Width * sizeSrc.Height / sizeSrc.Width)) / 2;
rectLoc = new Rectangle(iB,
iB + iOff,
sizeDst.Width,
sizeDst.Width * sizeSrc.Height / sizeSrc.Width);
}
g.DrawImage(_AutoScaleImage, rectLoc, rectSrc, GraphicsUnit.Pixel);
}
}
Or my original VB.NET Version.
<System.ComponentModel.DesignerCategory("")> _
Public Class AutoScaleButton
Inherits Button
Private _AutoScaleImage As Image
Public Property AutoScaleImage() As Image
Get
Return _AutoScaleImage
End Get
Set(value As Image)
_AutoScaleImage = value
If value IsNot Nothing Then Me.Invalidate()
End Set
End Property
Private _AutoScaleBorder As Integer
Public Property AutoScaleBorder() As Integer
Get
Return _AutoScaleBorder
End Get
Set(ByVal value As Integer)
_AutoScaleBorder = value
Me.Invalidate()
End Set
End Property
Protected Overrides Sub OnPaint(e As PaintEventArgs)
MyBase.OnPaint(e)
DrawResizeImage(e.Graphics)
End Sub
Private Sub DrawResizeImage(ByRef g As Graphics)
If _AutoScaleImage Is Nothing Then Exit Sub
Dim iB As Integer = AutoScaleBorder, iOff As Integer = 0
Dim rectLoc As Rectangle, rectSrc As Rectangle
Dim sizeDst As Size = New Size(Math.Max(0, Me.Width - 2 * iB), Math.Max(0, Me.Height - 2 * iB))
Dim sizeSrc As Size = New Size(_AutoScaleImage.Width, _AutoScaleImage.Height)
Dim ratioDst As Double = sizeDst.Height / sizeDst.Width
Dim ratioSrc As Double = sizeSrc.Height / sizeSrc.Width
rectSrc = New Rectangle(0, 0, sizeSrc.Width, sizeSrc.Height)
If ratioDst < ratioSrc Then
iOff = (sizeDst.Width - (sizeDst.Height * sizeSrc.Width / sizeSrc.Height)) / 2
rectLoc = New Rectangle(iB + iOff, iB, _
sizeDst.Height * sizeSrc.Width / sizeSrc.Height, _
sizeDst.Height)
Else
iOff = (sizeDst.Height - (sizeDst.Width * sizeSrc.Height / sizeSrc.Width)) / 2
rectLoc = New Rectangle(iB, iB + iOff, _
sizeDst.Width, _
sizeDst.Width * sizeSrc.Height / sizeSrc.Width)
End If
g.DrawImage(_AutoScaleImage, rectLoc, rectSrc, GraphicsUnit.Pixel)
End Sub
End Class
public class ExtButton : Button
{
public new Image Image
{
get { return base.Image; }
set {
base.Image = ScaleImage(value, this.Width, this.Height);
}
}
private Image ScaleImage(Image image, int maxWidth, int maxHeight)
{
var ratioX = (double)maxWidth / image.Width;
var ratioY = (double)maxHeight / image.Height;
var ratio = Math.Min(ratioX, ratioY);
var newWidth = (int)(image.Width * ratio);
var newHeight = (int)(image.Height * ratio);
var newImage = new Bitmap(newWidth, newHeight);
Graphics.FromImage(newImage).DrawImage(image, 0, 0, newWidth, newHeight);
return newImage;
}
}
I originally proposed using a standard ImageButton but then read your comment that you are trying to size the button to the image. For that use a LinkButton:
<asp:LinkButton ID="foo" runat="server" OnClick="LinkButton1_Click">
<asp:Image ID="imagefoo" runat="server" ImageUrl="~/Foo.jpg" />
</asp:LinkButton>