I ahve a dgv inside a winform and i want to display an image from the dgv image column inside a combo box drop down list.
i can add other values within the dgv to the combobox:
var cbString = dgvLineSymbols.Rows[i].Cells["LINE_NAME"].Value.ToString();
if (cbString != "")
{
cbAllSymbols.Items.Add(dgvLineSymbols.Rows[i].Cells["LINE_NAME"].Value.ToString());
}
if i try adding the value of the image column i get text describing the image as a bitmap.
Ive tried a bunch of things but there isnt a lot of information available on this one.
This was my most hopeful attempt but still did not work, also this required additional dll's being loaded and was causing errors elsewhere in my application.
System.Windows.Controls.Image theImage = new System.Windows.Controls.Image();
BitmapImage bitmap = new BitmapImage();
MemoryStream strm = new MemoryStream();
strm.Write(bytearr, 0, bytearr.Length);
bitmap.BeginInit();
bitmap.StreamSource = strm;
bitmap.EndInit();
theImage.Source = bitmap;
There must be an easier way to achieve this considering how straightforward it is to add an image to a dgv:
if (File.Exists(file))
{
Bitmap img;
img = new Bitmap(#"" + file);
dgvLineSymbols.Columns[1].Width = 100;
dgvLineSymbols.Rows[i].Cells[1].Value = img;
}
Related
What I'm trying to do:
Load images from a number of .png files saved to disk (if the file doesn't exist, create a new image and fill it with a given colour)
Add these images to a Canvas (they are the same size as the canvas and are expected to mostly be off screen with a portion overlapping the actual Canvas area)
Draw onto the Canvas using lines, ellipses, etc
(On save) take the Canvas and convert it to a flat image held in memory (let's call it the CanvasImage)
For each image I loaded in step 1, calculate the portion that overlaps the actual Canvas area and copy that portion of the CanvasImage into the appropriate portion of the original image
Save the resulting images to disk, overwriting the existing files
I've had different portions of this working at different times, using code I found by searching for how to do each exact step, but never the full process. I'm mostly struggling with steps 4 to 6 as I don't really understand all the different image-related classes, how you convert between them, and which to use at each step in the process. Though I'm also having some issues with step 1, as I need to be able to overwrite the files at the end.
I've read a lot of the related questions (overwriting images, converting a canvas to an image, copying a portion of an image, etc) and tried the solutions (some of which worked in more simple examples), but I'm struggling to put it all together.
Any help or advice would be greatly appreciated. If there's anything you'd like me to elaborate on I'd be happy to, and if you'd like to see some of the code I can share it (I've just tried a lot of different things so I'm not sure how useful it would be)
I've managed to solve the problem. I'll post the code below for each step I had trouble with in case anyone else will find it useful. The code here is slightly modified to suit the general case.
Step 1: Loading an image from the disk that can be overwritten
public static System.Windows.Controls.Image LoadImage(string filePath)
{
var image = new System.Windows.Controls.Image();
image.Stretch = Stretch.Uniform;
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
bitmapImage.UriSource = new Uri(filePath, UriKind.Absolute);
bitmapImage.EndInit();
image.Width = bitmapImage.PixelWidth;
image.Height = bitmapImage.PixelHeight;
image.Source = bitmapImage;
return image;
}
Step 4: Convert canvas to a BitmapImage
public static BitmapImage Convert(Canvas canvas)
{
var sizeRender = new Size(canvas.ActualWidth, canvas.ActualHeight);
var dv = new DrawingVisual();
using (DrawingContext ctx = dv.RenderOpen())
{
VisualBrush vb = new VisualBrush(canvas);
ctx.DrawRectangle(vb, null, new Rect(new Point(), sizeRender));
}
var renderBitmap =
new RenderTargetBitmap(
(int)canvas.ActualWidth,
(int)canvas.ActualHeight,
96d,
96d,
PixelFormats.Pbgra32);
renderBitmap.Render(dv);
BitmapEncoder pngEncoder = new PngBitmapEncoder();
pngEncoder.Frames.Add(BitmapFrame.Create(renderBitmap));
BitmapImage bitmap;
using (var stream = new MemoryStream())
{
pngEncoder.Save(stream);
bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = stream;
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.EndInit();
bitmap.Freeze();
}
return bitmap;
}
Step 5: Copy a portion of an image into a different image
public static void SaveImage(Image inputImage, BitmapImage canvasImage, string fileName)
{
... Calculate the portion that overlaps (left, top, width, height) ...
var canvasImageAsBitmap = BitmapConverter.ConvertBitmapImageToBitmap(canvasImage);
var croppingRectangle = new Rectangle(left, top, width, height);
var croppedRegion = canvasImageAsBitmap.Clone(croppingRectangle, canvasImageAsBitmap.PixelFormat);
var image = BitmapConverter.ConvertBitmapImageToBitmap((BitmapImage)inputImage.Source);
var bitmap = new Bitmap((int)inputImage.Width, (int)inputImage.Height);
... Calculate the position of the cropped image in the input image (xPos, yPos) ...
using (var graphics = Graphics.FromImage(bitmap))
{
graphics.DrawImage(image, 0, 0);
graphics.DrawImage(croppedRegion, xPos, yPos);
graphics.Flush();
}
bitmap.Save(fileName);
}
This step relies on the following code to work:
public static Bitmap ConvertBitmapImageToBitmap(BitmapImage bitmapImage)
{
using (MemoryStream memoryStream = new MemoryStream())
{
BitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapImage));
encoder.Save(memoryStream);
Bitmap bitmap = new Bitmap(memoryStream);
return new Bitmap(bitmap);
}
}
Step 6: Overwrite the image file to save in the disk.
This is just the line bitmap.Save(fileName); shown in Step 5, which works due to the implementation of Step 1
I put my pictures of letters in a separate table and I defined an foriegn key for that
I now want to click on any data in the data grid view to show the photos of that level in the control of the image.
I wrote the order for the retrieval of the photos, Of course, I do not know if it's right and I do not know how to control the image.
code
SqlConnection imageConnection = new SqlConnection(#"Data Source = ZAHRA; Initial Catalog = Baygani; inte");
SqlCommand imageCommand = new SqlCommand(#"select Pictures.pic1,Pictures.pic2,Pictures.pic3,Pictures.pic4,Pictures.pic5,Pictures.pic6,Pictures.pic7,Pictures.pic8,Pictures.pic9,
Pictures.pic10 from Pictures,Latters where Pictures.idlatter=Latters.id ", imageConnection);
imageConnection.Open();
SqlDataReader imageReader = imageCommand.ExecuteReader();
string imageFilename = (string)imageReader.GetValue(0);
byte[] imageBytes = (byte[])imageReader.GetValue(1);
MemoryStream ms = new MemoryStream(imageBytes);
Assuming that you are using Bindings to display your data in your UI and thus using viewmodels, I would suggest utilizing an ImageSource.
To initialize an ImageSource from a byte array I wrote the following method:
public ImageSource LoadImageSourceFromBytes(byte[] imageBytes)
{
BitmapImage bitmapImage = new BitmapImage();
using (MemoryStream imageStream = new MemoryStream(imageBytes))
{
bitmapImage.BeginInit();
bitmapImage.StreamSource = imageStream;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
}
bitmapImage.Freeze();
return bitmapImage;
}
This is my code:
BitmapImage bitmapImage;
if (ImagesInBase64[imageName.ToString()].Equals(string.Empty))
{
bitmapImage = new BitmapImage(new Uri(string.Format("{0}\\Images\\Application\\{1}.png", AppDomain.CurrentDomain.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar), imageName), UriKind.Relative));
}
else
{
bitmapImage = ImageProcessor.Base64StringToBitmap(ImagesInBase64[imageName.ToString()]);
ImageProcessor.SaveMyImage(ImagesInBase64[imageName.ToString()], imageName);
}
var image = new Image();
image.Source = bitmapImage;
image.SetValue(Grid.RowProperty, row);
image.SetValue(Grid.ColumnProperty, column);
image.Margin = new Thickness(10, 5, 10, 5);
grid.Children.Add(image);
When the code enters in the else, everything works as expected. I can see the image as a part of the grid. However, when the code enters the if part, even though bitmapImage is a valid BitmapImage, the image isn't shown in the grid. WHat's going on?
I'm trying to set a Grid's backgroud through code.
The Grid has 1000 x 1000 size, the same size of the loaded PNG.
I load this PNG into a Stream, then execute the following code:
using (StreamWrapper wrapper = new StreamWrapper(streamImg))
using (BinaryReader reader = new BinaryReader(wrapper))
{
originalImage = new BitmapImage();
originalImage.BeginInit();
originalImage.CacheOption = BitmapCacheOption.OnLoad;
originalImage.StreamSource = reader.BaseStream;
originalImage.EndInit();
originalImage.Freeze();
}
ib = new ImageBrush() { ImageSource = ConvertToGrayScale(ref originalImage) };
grdQuebraCabeƧa.Background = ib;
private FormatConvertedBitmap ConvertToGrayScale(ref BitmapImage image)
{
FormatConvertedBitmap grayImage = new FormatConvertedBitmap();
grayImage.BeginInit();
grayImage.Source = image;
grayImage.DestinationFormat = PixelFormats.Gray32Float;
grayImage.EndInit();
return grayImage;
}
The following screenshot is the result:
You can see black blocks on lower and right sides.
I want to center the image in the grid.
Is that possible? How can I achieve this result?
I'm making a player and I'm stuck in a apparently simple problem.
I need to make the cover art of the song to be displayed in one Image box.
I found these two solutions:
This:
var file = TagLib.File.Create(filename);
if (file.Tag.Pictures.Length >= 1)
{
var bin = (byte[])(file.Tag.Pictures[0].Data.Data);
PreviewPictureBox.Image = Image.FromStream(new MemoryStream(bin)).GetThumbnailImage(100, 100, null, IntPtr.Zero);
}
and this:
System.Drawing.Image currentImage = null;
// In method onclick of the listbox showing all mp3's
TagLib.File f = new TagLib.Mpeg.AudioFile(file);
if (f.Tag.Pictures.Length > 0)
{
TagLib.IPicture pic = f.Tag.Pictures[0];
MemoryStream ms = new MemoryStream(pic.Data.Data);
if (ms != null && ms.Length > 4096)
{
currentImage = System.Drawing.Image.FromStream(ms);
// Load thumbnail into PictureBox
AlbumArt.Image = currentImage.GetThumbnailImage(100,100, null, System.IntPtr.Zero);
}
ms.Close();
}
But both are to Windows Forms, I suppose, because I have problems with them.
I'm not sure which solution makes the most sense. Could anyone give me some pointers?
Use System.Windows.Controls.Image to display your images on UI. You must set it's Source property in order to provide image data to render on UI.
// Load you image data in MemoryStream
TagLib.IPicture pic = f.Tag.Pictures[0];
MemoryStream ms = new MemoryStream(pic.Data.Data);
ms.Seek(0, SeekOrigin.Begin);
// ImageSource for System.Windows.Controls.Image
BitmapImage bitmap= new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = ms;
bitmap.EndInit();
// Create a System.Windows.Controls.Image control
System.Windows.Controls.Image img = new System.Windows.Controls.Image();
img.Source = bitmap;
Then you can add/place this Image control to UI.