I have imported a greyscale 16-bit image. I have it bot as a BitmapSource and an Image (of Controls namespace). How can i access the individual pixels? Is the CopyPixels i have read about the only or best way? If so, i don't get how to set the stride, and which pixel contains the pixel intensity value.
Method1:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO;
using Nikon;
using WindowsFormsApplication1;
using System.Windows.Media.Imaging;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Controls;
namespace Map
{
class OpenTIFF
{
static void OpenOne()
{
// Open a Stream and decode a TIFF image
Stream imageStreamSource = new FileStream("C:\\Users\\Me\\Desktop\\"MyTif.tif", FileMode.Open, FileAccess.Read, FileShare.Read);
TiffBitmapDecoder decoder = new TiffBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource bitmapSource = decoder.Frames[0];
System.Windows.Controls.Image image = new System.Windows.Controls.Image();
image.Source = bitmapSource;
}
}
}
I think this might be simpler (found here), but then i am unclear how to access individual pixels in a 1D byte array.
Method 2:
static void OpenTwo()
{
System.Drawing.Image imageToConvert = System.Drawing.Image.FromFile("aa.tif", true);
byte[] Ret = new byte[0];
using (MemoryStream ms = new MemoryStream())
{
imageToConvert.Save(ms, ImageFormat.Tiff);
Ret = ms.ToArray();
}
}
Thanks,
Dan
You might want to check out the free image library.
It has a C# wrapper.
http://freeimage.sourceforge.net/index.html
To get you started and give a quick example:
download the binary distribution
open FreeImage.NET.sln in visual studio (I used 2010)
build the Library project
if you receive errors in the XML comments do the following: go in the project properties, under build, change "treat warnings as errors" from "all" to "none"
Create new console project.
Add reference to the assembly you built in step 3.
FreeImage3154Win32\FreeImage\Wrapper\FreeImage.NET\cs\Library\bin\Debug\FreeImageNET.dll
Add the following code to Program.cs
using FreeImageAPI;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// load image, this can by your 16-bit tif
FIBITMAP dib = FreeImage.LoadEx("myfile.tif");
// convert to 8-bits
dib = FreeImage.ConvertToGreyscale(dib);
// rotate image by 90 degrees
dib = FreeImage.Rotate(dib, 90);
// save image
FreeImage.SaveEx(dib, "newfile.png");
// unload bitmap
FreeImage.UnloadEx(ref dib);
}
}
}
copy the FreeImage binary dll that you downloaded into the bin directory.
FreeImage3154Win32\FreeImage\Dist\FreeImage.dll
Run the application
There is a good selection of examples in the solution that contained the Library project.
Your detailed steps are very much what i needed...much thanks.
I followed directions similar to yours for installation (your steps 1-3) in a related thread. This was successful, and exactly as Romulus said.
Below are some additional details needed and errors I ran into (i hope its not too much detail...hope to help anyone else who runs into this).
I followed your directions from step 4 onwards (except i added it into my exisitng windows application). I copied the FreeImage.dll (step 8) into the bin directory of my project.
I run the code, and get this error:
An unhandled exception of type 'System.BadImageFormatException' occurred in WindowsFormsApplication1.exe
Additional information: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
I had two errors. First was that I had not copied to FreeImage binary dll (step 8 above) into the correct bin directory of the project (I had copied it to bin and not bin\Debug 8-). I copied it to:
\WindowsFormsApplication1\bin\Debug
Second, if I run it now, I get an error:
An unhandled exception of type 'System.TypeInitializationException' occurred in WindowsFormsApplication1.exe
Additional information: The type initializer for 'WindowsFormsApplication1.Form1' threw an exception.
The solution here is to change the Build platform to x86. I found either selecting x86, or Any CPU with the Prefer 32-bit box checked work. Tip for beginners like myself: The Build platform is accessed by right-clicking on the Project name (not the Solution) and selecting Properties. It can also be accessed from the DEBUG menu, where at the bottom will be "MyProject Properties".
or this also works:
So with these two fixes, the code runs fine. However, the file output is 0KB. But that's another post...
Thanks!
Dan
Related
I'am starting to learn SharpDX and Holographic template for C#.
While compiling project I have error at compilation of shader file.
var vertexShaderByteCode = ShaderBytecode.CompileFromFile("Content/Shaders/VertexSharderShared.hlsl", "VS", "vs_5_0", ShaderFlags.Debug);
fxc.exe exited with code 1.
In the sample they use some .cso file while loading shader into byte code:
code img
As I don't really understand where that .cso comes from and what Vprt is, I prefer loading hlsl file directly. I'm using SharpDX 3.0.2, SharpDX.Direct3D11 3.0.2 and SharpDX.D3DCompiler 3.0.2.
Thanks!
The CSO files need to be loaded then the relevant shader created. Below is an example of a function I use to load the shader. Please note, that you should hold onto the byte code as well as the vertex shader in this example.
The Helper function is my cross uwp/mfc wrapper, but it basically returns the file in a datastream in memory.
The CSO file is byte code, you need to attach it to the correct Sharpdx.Direct3D11 shader class.
The bytecode is also used to reference the semantic interface (for Vertex buffers only). once you have created that, your draw call can match the data against the GPU register that it is associated to. But the code below at least will load your CSO file in and create the vertexshader.
goodluck.
using (Stream fileStream = Helper.GetFileStream(a_fileName, a_filePath))
{
a_byteCode = new D3DCompiler.ShaderBytecode(fileStream);
if (a_byteCode != null)
{
a_child = new D3D11.VertexShader(a_device, a_byteCode)
{
DebugName = "a_fileName"
};
}
else
{
throw new Exception("Unable to load file: " + a_fileName);
}
}
Spreadsheet output of OpenXML works in Excel (and Google Docs) but throws a runtime error in OpenOffice 4.x...
Specific error is
General Error.
General input/output error.
with no further explanation. It, in practice, has only occurred for me if there were greater than 40 rows for the spreadsheet; however, there did not seems to be a specific number of rows that caused the issue.
I have already created a workaround for the issue. This post is just to share my horrible, horrible solution for those that just need something.
I suspect the cause might be in the Zip headers or part of the zip entries themselves and that their is either a bug in the library that writes the Zip output for the System.IO.Packaging namespace (which I assume that OpenXML uses) or that OpenOffice has a very simple zip reader. Maybe something with the central directory file offsets versus the compressed file size, but I did not bother to check as I had limited time.
I may investigate further one day, or if anyone knows a quick solution, then do let me know. The files are written using the examples found on MSDN and they do open correctly in Excel.
In the meantime, if anyone needs a band-aid to the issue, I am posting my quick fix here since I was unable to find one myself. It expects a byte array (perhaps dumped from MemorySteam or read a FileStream). It outputs another byte array.
Someone clever could have it accept a Stream, seek to 0 relative to Beginning, and then read from there, perhaps writing directly to another passed in stream. That would be an exercise to the reader, unless someone happens to post a response that does the same.
If anyone does have a better solution, I would not mind knowing.
Uses .NET 4.5
References System.IO.Compression
using System;
using System.IO;
using System.IO.Compression;
namespace redmasq {
public static class ExcelFileFixExample {
public static byte[] XLSXOpenOfficePackageFix(byte[] fileData) {
using (MemoryStream ms = new MemoryStream(fileData, false)) {
using (ZipArchive za = new ZipArchive(ms)) {
using (MemoryStream ms2 = new MemoryStream()) {
using (ZipArchive za2 = new ZipArchive(ms2, ZipArchiveMode.Create)) {
foreach (ZipArchiveEntry entry in za.Entries) {
ZipArchiveEntry zae = za2.CreateEntry(entry.FullName, System.IO.Compression.CompressionLevel.Optimal);
using (Stream src = entry.Open()) {
using (Stream dest = zae.Open()) {
src.CopyTo(dest);
}
}
}
}
return ms2.ToArray();
}
}
}
}
}
}
I'm working with a console application / WebJob which utilises the EPPlus library for working with Excel -files (.xlsx). My application basically opens a set of Workbooks and merges them together as one file.
The application is running fine locally, but not in Azure. According to the StackTrace the error happens inside the EEPlus library when trying to save an image (I assume this is done to move images from one Workbook to another).
Unhandled Exception: System.ApplicationException: A generic error occurred in GDI+.
---> System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI+.
at System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams)
at System.Drawing.Image.Save(Stream stream, ImageFormat format)
at OfficeOpenXml.Drawing.ExcelPicture..ctor(ExcelDrawings drawings, XmlNode node)
at OfficeOpenXml.Drawing.ExcelDrawing.GetDrawing(ExcelDrawings drawings, XmlNode node)
at OfficeOpenXml.Drawing.ExcelDrawings.AddDrawings()
at OfficeOpenXml.Drawing.ExcelDrawings..ctor(ExcelPackage xlPackage, ExcelWorksheet sheet)
at OfficeOpenXml.ExcelWorksheets.Add(String Name, ExcelWorksheet Copy)
The original code, which produces the error open calling ConvertTo.
Part = drawings.Part.Package.GetPart(UriPic);
FileInfo f = new FileInfo(UriPic.OriginalString);
ContentType = GetContentType(f.Extension);
_image = Image.FromStream(Part.GetStream());
ImageConverter ic=new ImageConverter();
var iby=(byte[])ic.ConvertTo(_image, typeof(byte[]));
var ii = _drawings._package.LoadImage(iby, UriPic, Part);
ImageHash = ii.Hash;
After reading several questions on the matter I've tried to modify it using a manual conversion and saving to a MemoryStream. However I'm still getting the error.
Part = drawings.Part.Package.GetPart(UriPic);
FileInfo f = new FileInfo(UriPic.OriginalString);
ContentType = GetContentType(f.Extension);
_image = Image.FromStream(Part.GetStream());
byte[] iby;
using (MemoryStream ms = new MemoryStream())
{
_image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
iby = ms.ToArray();
}
var ii = _drawings._package.LoadImage(iby, UriPic, Part);
ImageHash = ii.Hash;
I'm really stuck on what to try next. The exception doesn't produce that much to go on, and I feel I've already tried all the suggestions out there: Checking folder and file permissions (my app uses the temp folder, which I believe is safe), avoid reusing streams and so on.
Please let me know if you need any additional information and I'll gladly put it up.
This is not possible using the current versions of EPPlus, due to a dependency on the System.Drawing libraries internally.
See here for an official thread on the topic:
https://github.com/JanKallman/EPPlus/issues/427
And here for some other interesting reading: https://photosauce.net/blog/post/5-reasons-you-should-stop-using-systemdrawing-from-aspnet
It seems like the only way through this will be to identify the functions in EPP that depend on System.Drawing and work around them. Or adjust EPP to use a different library for graphics.
This may be a good start for you to begin determining the parts you can avoid: https://github.com/JanKallman/EPPlus/search?q=%22using+system.drawing%3B%22&unscoped_q=%22using+system.drawing%3B%22
I typically use EPPlus in this way:
Grab a template.xlsx I have previously formatted
Add data to it (using C# and EPPlus)
Return the new xlsx to the user
I recently had the same error:
A generic error occurred in GDI+
How it was solved:
My template.xlsx was using Excel's Camera Tool: that is, there was a snapshot in one of the sheets that was being pasted in another sheet.
This works fine locally (in my computer) but not in Azure... I don't know why.
But if I remove the snapshot it works
I am working on Emgu cv as a console application and I was trying to load an jpeg format image file from computer disk.I have tried the following ways but nothing is working?
Image input = Image.FromFile("C://Users//...//Image.jpg");
Bitmap master = (Bitmap)input;
Image<Gray,byte> InputImage = new Image<Gray,byte>(master);
RecognizeFaces(InputImage);
And this way too
Image<Bgr,byte> inputImage = new Image<Bgr,byte>("C:\\Users\...\Image.jpeg");
Image<Gray,byte> grayFrame = inputImage.Convert<Gray,byte>();
Both ways Its not working.Any other option? It stops running here
_ptr = CvInvoke.cvCreateImageHeader(new Size(cols, rows), CvDepth, numberOfChannels);
in a class known to be Image.cs of Emgu cv.And it throws type initializer for 'Emgu.CV.CvInvoke' Exception.The File path is perfect/correct.the error looks like this.
The inner exception is "System.BadImageFormatException An attempt was made to load a program with an incorrect format Exception for hresult 0x8007000B." Configuration manager and build target are the same both any cpu.
http://www.mediafire.com/view/myfiles/#6557l4iwzpza7m5
Could you please tell me what i am doing wrong here? Thanks
Had the same problem. My solution was to change the target platform of the application to explicitly "x64". (I have a 64bit system and the 64bit libraries)
The delimiters in the file path are reversed for Windows. Did you try it like this "C:\Users\...\Image.jpeg"? (instead of "//")
You can check it with File.Exists to be sure.
I would look for mistakes like that (simple mistakes). Generally I don't remember having problems loading an image from file with Emgu.
We have a process that pulls images from a remote server. Most of the time, we're good to go, the images are valid, we don't timeout, etc. However, every once and awhile we see this error similar to this:
Unhandled Exception: System.Runtime.InteropServices.ExternalException: A generic
error occurred in GDI+.
at System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder, EncoderPa
rameters encoderParams)
at ConsoleApplication1.Program.Main(String[] args) in C:\images\ConsoleApplic
ation1\ConsoleApplication1\Program.cs:line 24
After not being able to reproduce it locally, we looked closer at the image, and realized that there were artifacts, making us suspect corruption.
Created an ugly little unit test with only the image in question, and was unable to reproduce the error on Windows 7 as was expected. But after running our unit test on Windows Server 2008, we see this error every time.
Is there a way to specify non-strictness for jpegs when writing them? Some sort of check/fix we can use?
Unit test snippet:
var r = ReadFile("C:\\images\\ConsoleApplication1\\test.jpg");
using (var imgStream = new MemoryStream(r))
{
using (var ms = new MemoryStream())
{
var guid = Guid.NewGuid();
var fileName = "C:\\images\\ConsoleApplication1\\t" + guid + ".jpg";
Image.FromStream(imgStream).Save(ms, ImageFormat.Jpeg);
using (FileStream fs = File.Create(fileName))
{
fs.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
}
}
}
AFAIK, no, there is no way to ask GDI+ to be more lenient when decoding JPG files. In any application where you have consumers uploading arbitrary JPG files you will see a number of these Generic error in GDI+ exceptions being thrown all the time. You could try using WPF to read your image instead, but I suspect it too will object to corrupt images.
Maybe it's not answer to your direct question, but why would't you pull image and its md5 (or any other hash) that can verify correctnes of this image?