|
Oh! Wonderful! there is a lot to think about, thank you!
|
|
|
|
|
Good Evening! I'm writing to say that I figured out the problem with incorrect displaying of my Tiff file. It was in this part of your code:
for (i = 0; i < bmd.Height; ++i)
{
byte* row = (byte*)bmd.Scan0 + (i * bmd.Stride);
i1 = i * bmd.Height; <----- HERE. It should be i1=i*bmd.Width
for (j = 0; j < bmd.Width; ++j)
{
sVal = (pixels16[i1 + j]); <-----Since we move along image strip equaled to Width of
lPixval = (sVal / 256.0); // Convert to a 256 value range Image
if (lPixval > 255) lPixval = 255;
if (lPixval < 0) lPixval = 0;
b = (byte)(lPixval);
j1 = j * pixelSize;
row[j1] = b; // Red
row[j1 + 1] = b; // Green
row[j1 + 2] = b; // Blue
}
}
So at last everything displays correctly! again, Thank you for your contribution! The next step is to process the image with my noise-removal algorithm and make it display the change during processing. Could you direct me to the idea of implementing this?
Thank you in advance!
|
|
|
|
|
Great!. I was also at a loss about where the bug was. Good that you found it out - need to correct it for future versions.
Meanwhile, did you find anything wrong with the TIFF decoder code I posted?
|
|
|
|
|
No! It works correctly, there is a lot of code, I haven't encountered anything wrong so far.
|
|
|
|
|
Hi! I've been changing your program for my purposes and embedded some functionality in it relating to a noise-removal filter , but came across a problem.
I put a button to the form which has to process an image after being pushed and it looks like this:
private void process_btn_Click(object sender, EventArgs e)
{
Algorithm a = new Algorithm(pixels16,width,height);
a.Set_D0_h1_h2_t_lambda_Iter(100, 1, 1, 1, 1,200);
a.Set_sigma(0.5);
a.PeronaMalik(ref pixels16, ref this.progressBar1);
CreateBitmap();
Invalidate();
}
So I have a class called Algorithm and some methods, including a constructor with parameters.
In the constructor I copy List pixels16 to a matrix U[height,width] and do some filtering with a method PeronaMalik, having sent pixels16 as a ref argument, in order to change it within the method, next the same way as in bnOpenImage_Click method I add CreateBitmap and Invalidate for it to be redrawn but nothing happens, I rechecked Algorithm as a console app and everything works well, I get modified pixels16. I'm confused, what am I doing wrong?
Thank you in advance!
|
|
|
|
|
Hi. I have added a button called 'Process' to just halve the pixel values. Here is the code. This works - reduces the intensity of the displayed image.
One word of caution with this code - it directly modifies the pixels16 values. In practice, you should make a copy of these values, so as to have the original values with you, in code.
Tell me if you find anything amiss.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;
namespace ImageDraw
{
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Panel panelImage;
private System.Windows.Forms.Button bnOpenImage;
private List<ushort> pixels16;
Graphics g;
uint width, height;
Bitmap bmp;
TiffDecoder tiff;
private Button bnProcess;
private System.ComponentModel.Container components = null;
public Form1()
{
InitializeComponent();
pixels16 = new List<ushort>();
g = panelImage.CreateGraphics();
tiff = new TiffDecoder();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.bnOpenImage = new System.Windows.Forms.Button();
this.panelImage = new System.Windows.Forms.Panel();
this.bnProcess = new System.Windows.Forms.Button();
this.SuspendLayout();
this.bnOpenImage.Location = new System.Drawing.Point(8, 8);
this.bnOpenImage.Name = "bnOpenImage";
this.bnOpenImage.Size = new System.Drawing.Size(88, 56);
this.bnOpenImage.TabIndex = 0;
this.bnOpenImage.Text = "Open TIFF Image";
this.bnOpenImage.Click += new System.EventHandler(this.bnOpenImage_Click);
this.panelImage.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
this.panelImage.Location = new System.Drawing.Point(104, 8);
this.panelImage.Name = "panelImage";
this.panelImage.Size = new System.Drawing.Size(512, 512);
this.panelImage.TabIndex = 2;
this.bnProcess.Location = new System.Drawing.Point(8, 70);
this.bnProcess.Name = "bnProcess";
this.bnProcess.Size = new System.Drawing.Size(88, 23);
this.bnProcess.TabIndex = 3;
this.bnProcess.Text = "Process";
this.bnProcess.UseVisualStyleBackColor = true;
this.bnProcess.Click += new System.EventHandler(this.bnProcess_Click);
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(624, 530);
this.Controls.Add(this.bnProcess);
this.Controls.Add(this.panelImage);
this.Controls.Add(this.bnOpenImage);
this.Name = "Form1";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Display 16-bit Raw Image Files";
this.Closing += new System.ComponentModel.CancelEventHandler(this.Form1_Closing);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
this.ResumeLayout(false);
}
#endregion
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void bnOpenImage_Click(object sender, System.EventArgs e)
{
pixels16.Clear();
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "TIFF Files(*.tif)|*.tif";
ofd.ShowDialog();
if( ofd.FileName.Length > 0 )
{
tiff.TiffFileName = ofd.FileName;
width = tiff.Width;
height = tiff.Height;
pixels16 = tiff.Pixels16;
CreateBitmap();
Invalidate();
}
ofd.Dispose();
}
private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
if( pixels16.Count > 0 )
g.DrawImage(bmp, 0, 0);
}
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
bmp.Dispose();
pixels16.Clear();
}
private void ReadImageFile(string fileName)
{
BinaryReader br = new BinaryReader(File.Open(fileName, FileMode.Open));
ushort pixShort;
int i;
long iTotalSize = br.BaseStream.Length;
for( i = 0; i < iTotalSize; i += 2 )
{
pixShort = br.ReadUInt16();
pixels16.Add(pixShort);
}
br.Close();
width = (uint)(Math.Sqrt(pixels16.Count));
height = width;
}
private void CreateBitmap()
{
bmp = new Bitmap((int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, (int)width, (int)height),
System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
unsafe
{
int pixelSize = 3;
int i, j, j1, i1;
byte b;
ushort sVal;
double lPixval;
for (i = 0; i < bmd.Height; ++i)
{
byte* row = (byte*)bmd.Scan0 + (i * bmd.Stride);
i1 = i * bmd.Width;
for (j = 0; j < bmd.Width; ++j)
{
sVal = (pixels16[i1 + j]);
lPixval = (sVal / 256.0);
if( lPixval > 255 ) lPixval = 255;
if( lPixval < 0 ) lPixval = 0;
b = (byte)(lPixval);
j1 = j * pixelSize;
row[j1] = b;
row[j1 + 1] = b;
row[j1 + 2] = b;
}
}
}
bmp.UnlockBits(bmd);
}
private void bnProcess_Click(object sender, EventArgs e)
{
for (int i = 0; i < pixels16.Count; ++i)
{
pixels16[i] /= 2;
}
CreateBitmap();
Invalidate();
}
}
}
|
|
|
|
|
private void process_btn_Click(object sender, EventArgs e)
{
Algorithm a = new Algorithm(pixels16,width,height);
a.Set_D0_h1_h2_t_lambda_Iter(100, 1, 1, 1, 1,200);
a.Set_sigma(0.5);
a.PeronaMalik(ref pixels16, ref this.progressBar1);
CreateBitmap();
Invalidate();
} I
Try changing the first line in this function to Algorithm a = new Algorithm( ref pixels16,width,height); . Of course, you need to change the signature of the Algorithm constructor.
|
|
|
|
|
Yeah! with this it works perfectly well! but if i want the image to be redrawn in time?, not just the final image, but all stages.
private void bnProcess_Click(object sender, EventArgs e)
{
for (int i = 0; i < pixels16.Count; ++i)
{
pixels16[i] /= 2;
}
CreateBitmap();
Invalidate();
}
I tried something like this but it just makes it darker without real-time effect despite the CreateBitmap and Invalidate Methods on each iteration of k
private void bnProcess_Click(object sender, EventArgs e)
{
for(int k=0; k<5; k++)
{
for (int i = 0; i < pixels16.Count; ++i)
{
pixels16[i] /= 2;
}
CreateBitmap();
Invalidate();
}
}
modified 24-Dec-15 6:47am.
|
|
|
|
|
A simple approach is like this: You should do some kind of animation with a Timer control. For each timer tick, the code should update the buffer onto the UI.
However, there are drawbacks with this approach. This may work fine for small images, but for large ones, the program will appear as though hanging.
To create a robust image updating program, you should do some kind of multi-threading - To split the image into different portions, and give each portion to a thread to process; and then upon receiving a completion notification from the thread, update the UI. Easier said than done.
There may be other approaches; you need to explore.
|
|
|
|
|
Ok, I have just started looking into threading in C#, i guess it will take some time to understand the technology, well at least it won't be the first iteration for me) since i have some background in MPI OpenMP equivalent in C++, anyway could I get in touch with you once i've got something done?
Thanks!
Happy Christmas but the way!
|
|
|
|
|
Wishing you and family Merry Christmas, and a Happy, Prosperous and Successful New Year 2016.
Yes - do update me when you have something up and running. All the best, and wish you early success.
|
|
|
|
|
Hi there! A new question in new year)
I've been looking into the Threading and bumped into some real pain in the neck, I have read some information in Shildt and decided to use TPL library since it's the most effective way to do multithreading, so I started with embedding Using System.Threading.Tasks in the program and it messaged me that this namespace doesn't exist in System.Threading, so I googled and found out that it might be .Net Framework problem. I checked to make sure I get the Latest version so it proved to be true, but the most mysterious thing is when I create a new Windows Form Project, this namespace is already inserted, but in your project it isn't, maybe it has smth to do with the fact that the program was written in 2008 and used an earlier version of .Net Framework? and What to do if it's true? rewrite the program or there is another way?
Thanks in advance!
|
|
|
|
|
how to display images TIFF (uncompressed) or as raw data using C #. because images can only be opened by the application ImageJ (http://rsbweb.nih.gov/ij/index.html)
and the example file can be downloaded at:
https://www.dropbox.com/s/z75v3v37bkhmvw7/tes.tiff
thnx...
|
|
|
|
|
|
sorry if there are examples projet that is so, because I find it difficult to seek references from the tutorial that you provide. There was an error message:'' System.Drawing.Image 'does not Contain a definition for' Source 'and no extension method' Source 'accepting a first argument of type' System.Drawing.Image 'could be found (are you missing a using directive or an assembly reference?) '
|
|
|
|
|
|
sorry did not work well, exit the error message: 'No imaging component suitable to complete this operation was found.', you can mencobamendownload file that I uploaded at the address: https://www.dropbox.com/s/z75v3v37bkhmvw7/tes.tiff[^]
to try
Thnx......
|
|
|
|
|
Looks like you have a .net version earlier than 3.0. Can you try updating to the .net version 3.0 or later, and then using Visual Studio 2008 or above, and opening the workspace given in that file.
|
|
|
|
|
I even had to use visual studio 2012, when it came out a different error message, namely:"No imaging component suitable to complete this operation was found."
in the script :" TiffBitmapDecoder decoder = new TiffBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);"
|
|
|
|
|
That workspace opens perfectly on my machine. I have Visual Studio 2008, and .Net 3.5. Try on a different machine if you have.
|
|
|
|
|
if you use an image file that I uploaded in https://www.dropbox.com/s/z75v3v37bkhmvw7/tes.tiff
to give it a try?
because the problem is in the picture, this picture I got from the x-ray machine in the form of raw files. but can be opened by ImageJ software (http://rsbweb.nih.gov/ij/index.html).
I want the images can be opened using C # programming language
|
|
|
|
|
There seems to be something wrong with your TIFF file. You need to get into the gory details of that TIFF file and find out the problem. Take a look at the CIPS book (http://homepages.inf.ed.ac.uk/rbf/BOOKS/PHILLIPS/[^]). That gives you a description of a TIFF file, along with source code (in C) to decode it.
|
|
|
|
|
You did tremendous job.
In your project you get array-list from raw file i.e. pixel16. Like this if i want to get back raw file from array-list how it can be possible...
|
|
|
|
|
Just write back array-list as a raw file using binary writer; in the left to right, top to bottom pixel order.
|
|
|
|
|
Nice example. I've faced the same problem, how to present 16bit grayscaled scientific image. Since I found using PixelFormat.Format16bppGrayScale unstable (.NET 2), I choosed similar way like you. Let me suggest some corrections of your code.
At first, dividing by 255 is completely wrong. What you need is scale 2 Byte value into 1 Byte (8 bits), which means "x >> 8". That's why you must use "if (lPixval > 255) lPixval = 255;" in your code. Also, you don't need testing of negative value, because you have array of ushort (unsigned) values. And at the end, put out some maths from cycles, which is a bad habit.
My offer is:
...
byte* row = (byte*)bmd.Scan0;
for (i = 0, i1 = 0; i < bmd.Height; ++i, row += bmd.Stride)
{
for (j = 0, j1 = 0; j < bmd.Width; ++j, j1 += 3, ++i1)
{
row[j1] = (byte)((ushort)pixels16[i1] / 256); // Red
row[j1 + 1] = row[j1]; // Green
row[j1 + 2] = row[j1]; // Blue
}
}
...
However, I personally prefer using PixelFormat.Format32bppRgb (don't care about right row's length) and simplify two "for" cycles into one.
I hope I wasn't to offensive
|
|
|
|
|