Can't find any info on how to write a filetype plugin for Paint.net. I have found only visual studio template at http://forums.getpaint.net/index.php?/topic/7984-filetype-plugin-template-v20/page__p__121651&#entry121651
and small description at codeproject, but I don't understand all of the parameters of OnSave event handler, what is PaintDotNet.Surface and how to work with data stored there.
I've written a plug-in like this once.
Forget about the template for a minute, you can do this from scratch.
Start by adding references to PaintDotnet.Base, PaintDotNet.Core and PaintDotNet.Data.
Next you'll need a class which inherits from the FileType class:
For example:
public class SampleFileType : FileType
{
public SampleFileType() : base ("Sample file type", FileTypeFlags.SupportsSaving |
FileTypeFlags.SupportsLoading,
new string[] { ".sample" })
{
}
protected override void OnSave(Document input, System.IO.Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback)
{
//Here you get the image from Paint.NET and you'll have to convert it
//and write the resulting bytes to the output stream (this will save it to the specified file)
using (RenderArgs ra = new RenderArgs(new Surface(input.Size)))
{
//You must call this to prepare the bitmap
input.Render(ra);
//Now you can access the bitmap and perform some logic on it
//In this case I'm converting the bitmap to something else (byte[])
var sampleData = ConvertBitmapToSampleFormat(ra.Bitmap);
output.Write(sampleData, 0, sampleData.Length);
}
}
protected override Document OnLoad(System.IO.Stream input)
{
//Input is the binary data from the file
//What you need to do here is convert that date to a valid instance of System.Drawing.Bitmap
//In the end you need to return it by Document.FromImage(bitmap)
//The ConvertFromFileToBitmap, just like the ConvertBitmapSampleFormat,
//is simply a function which takes the binary data and converts it to a valid instance of System.Drawing.Bitmap
//You will have to define a function like this which does whatever you want to the data
using(var bitmap = ConvertFromFileToBitmap(input))
{
return Document.FromImage(bitmap);
}
}
}
So, you inherit from FileType. In the constructor you specify what operations are supported (Loading/Saving) and which file extensions should be registered. Then you provide logic for both the Save and Load operations.
Basically that is all you need.
Finally you'll have to tell Pain.Net which FileType classes you want to load, in this case a single instance, but you could have more then one in a single library.
public class SampleFileTypeFactory : IFileTypeFactory
{
public FileType[] GetFileTypeInstances()
{
return new FileType[] { new SampleFileType() };
}
I hope this helps, let me know if you have questions.
}
Related
I am setting up a DICOM reader that I will be using to process CT scanner configurations. I am writing the application so that I can easily view DICOM either by dumping all tags or I would like to specify which tag I would like to look at. It is a C# console application using the fo-dicom library.
My problem is in my method definition I want to pass an argument in, I want the value of that argument to come from the user. Capture it through the console with a Console.Read().
I am able to dump all tags but can't seem to figure out just dumping the one.
public static void DumpAllTags(string dicomFile)
{
try
{
Console.WriteLine($"Attempting to dump all tags from DICOM
file:{dicomFile}...");
var file = DicomFile.Open(dicomFile);
foreach (var tag in file.Dataset)
{
Console.WriteLine($" {tag}
'{file.Dataset.GetValueOrDefault(tag.Tag, 0, "")}'");
}
}
catch (Exception e)
{
Console.WriteLine($"Error occured during DICOM file dump
operation -> {e.StackTrace}");
}
}
public static void DumpSingleDicomTag(string dicomFile, string tag)
{
try
{
Console.WriteLine($"Attempting to dump {tag} from DICOM file:
{dicomFile}...");
var file = DicomFile.Open(dicomFile);
var dicomDataset = file.Dataset;
var result = dicomDataset.Get<string>(DicomTag.tag);
Console.WriteLine(result);
}
catch (Exception e)
{
Console.WriteLine($"Error occured during DICOM file dump
operation -> {e.StackTrace}");
}
}
When trying to pass the tag variable that is captured by the keyboard and apply it to the DicomTag method I get an error.
DicomTag does not contain a definition for 'tag'
Your code cannot compile because your variable tag is a string value and not a property of class DicomTag.
Generally spoken: in DICOM a tag is defined by two number: group and element. So if you are doing some kind of configration, then you should not store texts like "Patientname" but the numbers like "0010,0010".
So this code will work:
public static void DumpSingleDicomTag(string dicomFile, string tagNumber)
{
var dataset = DicomFile.Open(dicomFile).Dataset;
var tag = Dicom.DicomTag.Parse(tagNumber);
var result = dataset.GetString(tag);
Console.Writeline(result);
}
// calling it with
DumpSignleDicomTag(dicomFile, "0010,0010");
If you have some good reasons why you need to store the names of the tags and not the numbers, then you need to iterate the DicomDictionary, which may cost quite some time.
There is a class DicomDictionary which holds a list of all defined DicomTags. This list is loadef from a resource file on demand, so when the class is first accessed. You then can iterate this whole list and find the first where the name matches:
using System.Linq;
public static void DumpSingleDicomTag(string dicomFile, string tagName)
{
var dataset = DicomFile.Open(dicomFile).Dataset;
var entry = Dicom.DicomDictionary.Default.FirstOrDefault(t => t.Keyword == tagName);
var result = dataset.GetString(entry.Tag);
Console.Writeline(result);
}
// calling it with
DumpSignleDicomTag(dicomFile, "PatientName");
But as I said, this code iterates the whole list of tags, which are currently about 4650 entries.
https://github.com/fo-dicom/fo-dicom/issues/942
I'm new to QuickGraph. I followed the examples on the documentation page to add vertices & edges to my graph.
Now, I want to display my graph on a windows form. I'm using Graphviz for that purpose, which generates a .DOT file as output. I'm following the code sample below for rendering:
IVertexAndEdgeListGraph<TVertex,TEdge> g= ...;
var graphviz = new GraphvizAlgorithm<TVertex,TEdge>(g);
string output = graphviz.Generate(new FileDotEngine(), "graph");
But, my compiler is not detecting FileDotEngine(). Moreover, I don't know what to do after the .DOT file is generated.
You have to provide a FileDotEngine yourself; see for instance this example on Github. A simple FileDotEngine that generates a jpg could be:
public sealed class FileDotEngine : IDotEngine
{
public string Run(GraphvizImageType imageType, string dot, string outputFileName)
{
string output = outputFileName;
File.WriteAllText(output, dot);
// assumes dot.exe is on the path:
var args = string.Format(#"{0} -Tjpg -O", output);
System.Diagnostics.Process.Start("dot.exe", args);
return output;
}
}
Then you could display the generated image in a picture box or similar.
Another approach would be to host a WPF control in your winforms app and then use Graph# to display the graph. I haven't tried this myself, however.
I'll do my best to explain.
My program takes screen shots which the user can save to their desktop or pass to a media server.
However, to pass to the server I first must have the file location of the image they are saving and so they must first save the file using the save file dialog and I store the location of that in a string which triggers a bool to say that the image has been save. The code looks like this to pass the file to server:
// sfd is the safe file dialog
UploadToServer.HttpUploadFile(Settings.Default.ServerAddress , sfd.FileName.ToString(), "file", "image/jpeg", nvc);
I tried to store the sfd in the following way so I could pass this call to another class:
public String SaveImageLocation
{
get { return sfd.FileName.ToString(); }
set { sfd.FileName.ToString() = value; }
}
But I get the following error:
Error 1 The left-hand side of an assignment must be a variable, property or indexer
What I'm trying to achieve is to take the file upload code and move it to another class. can someone help me with this error?
This is a method/function (call).
ToString()
You cannot assign a method/function (call) to a value..
.ToString() = value;
Try
public String SaveImageLocation
{
get { return sfd.FileName.ToString(); }
set { sfd.FileName = value; }
}
Please note you have not indicated what type FileName is, so it still may not work.
I tried to get the Tag value by using:
var vSAD = sel.VirtualSourceAxisDistance.Data;
I also tried var vSAD = dcm.FindAll("300A030A");
And it only returned one number (suppose to have 2).
Then I tried to read elements and save to another dicom file only and found for VR=FL, VM=2 case only one number showed up in the new file.
How can I fix this to get 2 numbers?
Does it mean when I use var dcm = DICOMFileReader.Read(openFileDialog1.FileName);
It already return with only one number?
I saw in the FloatingPiontSingle.cs file:
public class FloatingPointSingle : AbstractElement<float?>
{
public FloatingPointSingle() { }
public FloatingPointSingle(Tag tag, float? data)
{
Tag = tag;
Data = data;
VR = Enums.VR.FloatingPointSingle;
}
}
I didn't realize the FL VM could be more than one. I just looked at the DICOM specification though and realize that it is possible. It is actually an easy fix. Could you post a link to a sample (anonymized) DICOM file that contains such a value and I will patch the core framework.
FYI: To patch yourself, you would need to change the FloatingPointSingle to:
public class FloatingPointSingle : AbstractElement<float[]>
{
public FloatingPointSingle() { }
public FloatingPointSingle(Tag tag, float[] data)
{
Tag = tag;
Data = data;
VR = Enums.VR.FloatingPointSingle;
}
}
Then in the LittleEndianReader.ReadSinglePrecision(), and BigEndianReader.ReadSinglePrecision() method you will need to change out the logic to allow concatenated floating point numbers (no delimiter).
I am currently developing an Excel macro which allows creating Bugs in a Bugzilla instance.
After some trial and error this now turns out to work fine.
I wanted to enhance the client so that it's also possible to add screenshots to the newly created bug.
The environment I'm using is a little bit tricky:
I have to use MS Excel for my task.
As Excel does not understand XML-RPC, I downloaded an interface DLL (CookComputing.XmlRpcV2.dll from xml-rpc.net) which makes the XML-RPC interface accessible from .NET.
Then I created an additional DLL which can be called from Excel macros (using COM interop).
As already mentioned, this is working fine for tasks like browsing or adding new bugs.
But when adding an attachment to the bug, the image must be converted into a base64 data type. Although this seems to work fine and although the creation of the screenshot seems to succeed, the image seems to be corrupted and cannot be displayed.
Here's what I do to add the image:
The Bugzilla add_attachment method accepts a struct as input:
http://www.bugzilla.org/docs/4.0/en/html/api/Bugzilla/WebService/Bug.html#add_attachment.
This type was defined in C# and is visible also in VBA.
This is the struct definition:
[ClassInterface(ClassInterfaceType.AutoDual)]
public class TAttachmentInputData
{
public string[] ids;
public string data; // base64-encoded data
public string file_name;
public string summary;
public string content_type;
public string comment;
public bool is_patch;
public bool is_private;
public void addId(int id)
{
ids = new string[1];
ids[0] = id.ToString();
}
public void addData(string strData)
{
try
{
byte[] encData_byte = new byte[strData.Length];
encData_byte = System.Text.Encoding.ASCII.GetBytes(strData);
string encodedData = Convert.ToBase64String(encData_byte);
data = new Byte[System.Text.Encoding.ASCII.GetBytes(encodedData).Length];
data = System.Text.Encoding.ASCII.GetBytes(encodedData);
}
catch (Exception e)
{
throw new Exception("Error in base64Encode" + e.Message);
}
}
This is the part in my macro where I would like to add the attachment:
Dim attachmentsStruct As New TAttachmentInputData
fname = attachmentFileName
attachmentsStruct.file_name = GetFilenameFromPath(fname)
attachmentsStruct.is_patch = False
attachmentsStruct.is_private = False
'multiple other definitions
Open fname For Binary As #1
attachmentsStruct.addData (Input(LOF(1), #1))
Close #1
attachmentsStruct.file_name = GetFilenameFromPath(fname)
Call BugzillaClass.add_attachment(attachmentsStruct)
Where BugzillaClass it the interface exposed from my DLL to Excel VBA.
The method add_attachment refers to the XML-RPC method add_attachment.
I assume that my problem is the conversion from the binary file into base64.
This is done using the addData method in my C# DLL.
Is the conversion done correctly there?
Any idea why the images are corrupted?
I think the issue is that you are reading in binary data in the macro, but the addData method is expecting a string. Try declaring the parameter in addData as byte[].