I'm trying to create a mini tool for my job. I'm using C# with Visual Studio 2010 to do that. Now I need to export an image to an act file.
Following here, http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.bitmappalette.aspx
I wrote
class Palette : List<Color>
{
public static Palette GetFromImage(String PathToImage)
{
//Load imgae
BitmapImage image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(PathToImage, UriKind.RelativeOrAbsolute);
image.EndInit();
//Load palette
BitmapPalette BitmapPalette = new BitmapPalette(image, 256);
//Convert it to list of Color
Palette pal = new Palette();
for (int i = 0; i < BitmapPalette.Colors.Count; i++)
{
pal.Add(Color.FromArgb(BitmapPalette.Colors[i].R, BitmapPalette.Colors[i].G, BitmapPalette.Colors[i].B));
}
//Return the palette has been creatted
return pal;
}
This code has effected, but the order of all colors in the result did not same as the order of all colors when I export by photoshop. So, when I write all colors to a act file, the act file is not correct.
Anybody can help me.
Many thank
Act file is compilated binary file.
You cannot encode an act file.
Perhaps Photoshop can import a css file (as like palet)
Related
I have the following image (have put a screen-grab of the image as its size is more than 2 MB - the original can be downloaded from https://drive.google.com/file/d/1rC2QQBzMhZ8AG5Lp5PyrpkOxwlyP9QaE/view?usp=sharing
I'm reading the image using the BitmapDecoder class and saving it using a JPEG Encoder.
This results in the following image which is off color and faded.
var frame = BitmapDecoder.Create(new Uri(inputFilePath, UriKind.RelativeOrAbsolute),BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None).Frames[0];
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(frame);
using (var stream = File.OpenWrite(outputFilePath))
{
encoder.Save(stream);
}
The image is using PhotoShop RGB Color scheme.I tried setting the color profile using the following code,but this results in this error The designated BitmapEncoder does not support ColorContexts
encoder.ColorContexts = frame.ColorContexts;
Update:
Cloning the image seems to fix the issue. But when i resize the image using the following code for transformation the color profile is not preserved
Transform transform = new ScaleTransform(width / frame.Width * 96 / frame.DpiX, height / frame.Height * 96 / frame.DpiY, 0, 0);
var copy = BitmapFrame.Create(frame);
var resized = BitmapFrame.Create(new
TransformedBitmap(copy, transform));
encoder.Frames.Add(resized);
using (var stream = File.OpenWrite(outputFilePath))
{
encoder.Save(stream);
}
The image bits are identical. This is a metadata issue. This image file contains lots of metadata (Xmp, Adobe, unknown, etc.) and this metadata contains two color profiles/spaces/contexts:
ProPhoto RG (usually found in C:\WINDOWS\system32\spool\drivers\color\ProPhoto.icm)
sRGB IEC61966-2.1 (usually found in WINDOWS\system32\spool\drivers\color\sRGB Color Space Profile.icm)
The problem occurs because the two contexts order may differ in the target file for some reason. An image viewer can either use no color profile (Paint, Pain3D, Paint.NET, IrfanView, etc.), or use (from my experience) the last color profile in the file (Windows Photo Viewer, Photoshop, etc.).
You can fix your issue if you clone the frame, ie:
var frame = BitmapDecoder.Create(new Uri(inputFilePath, UriKind.RelativeOrAbsolute),BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None).Frames[0];
var encoder = new JpegBitmapEncoder();
var copy = BitmapFrame.Create(frame);
encoder.Frames.Add(copy);
using (var stream = File.OpenWrite(outputFilePath))
{
encoder.Save(stream);
}
As in this case, the order is preserved as is.
If you recreate the frame or transform it in any way, you can copy the metadata and color contexts like this:
var ctxs = new List<ColorContext>();
ctxs.Add(frame.ColorContexts[1]); // or just remove this
ctxs.Add(frame.ColorContexts[0]); // first color profile is ProPhoto RG, make sure it's last
var resized = BitmapFrame.Create(new TransformedBitmap(frame, transform), frame.Thumbnail, (BitmapMetadata)frame.Metadata, ctxs.AsReadOnly());
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(resized);
using (var stream = File.OpenWrite("resized.jpg"))
{
encoder.Save(stream);
}
Note an image that has more than one color context is painful (and IMHO should not be created / saved). Color profiles are for there to ensure a correct display, so two or more (rather conflicting! sRGB vs ProPhoto) profiles associated with one image means it can be displayed ... in two or more ways.
You'll have to determine what's you're preferred color profile in this strange case.
im trying to make simple photo editor (for adjusting brightness, contrast, saturation etc...) in WPF and im using the Magick.NET which contains ToByteArray method but the problem is i can't make ByteArray with this method because i'm getting exception because it doesn't wanna make ByteArray from NEF format for some reason...
My first idea, was to take the NEF format convert it to temporary TIFF File which can be converted with this specific method to ByteArray and that file can be converted to bytearray, but i think is very inconvenient and not much smart.
Second thing is when i have the WritableBitmap. How can i make the image from it for Magick.NET to edit it? Should i make another MagickImage Instance which is created with already created ByteArray and edit that image?
public void ImageSelectBtn_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
if (dialog.ShowDialog() == true)
{
using (var imageRaw = new MagickImage(dialog.FileName))
{
imageRaw.Write("D:/Coding/C#/New/SoftlightWPF/SoftlightWPF/Resources/temp.tiff");
MagickImage image = new MagickImage();
image = new MagickImage("D:/Coding/C#/New/SoftlightWPF/SoftlightWPF/Resources/temp.tiff");
byte[] ImageBytes = image.ToByteArray();
Render(ImageBytes);
}
}
}
private void Render(byte[] BytesData)
{
using (var ms = new MemoryStream(BytesData))
{
BitmapImage ImageBitmapSource = new BitmapImage(); //Image
ImageBitmapSource.BeginInit();
ImageBitmapSource.CacheOption = BitmapCacheOption.OnLoad;
ImageBitmapSource.StreamSource = ms;
ImageBitmapSource.EndInit();
WriteableBitmap ImageWritableBitmap = new WriteableBitmap(ImageBitmapSource);
this.ImageField.Source = ImageWritableBitmap;
}
}
There is already a library that can help you with this: https://www.nuget.org/packages/Magick.NET.SystemWindowsMedia/. Add it to your project and then do image.ToBitmapSource() instead.
I need to convert a JPG image to PNG and change its white background to transparent instead. I am using ImageMagick.NET and I have found the following ImageMagick command that is supposed to do what I am trying to achieve:
convert image.jpg -fuzz XX% -transparent white result.png
I have tried converting this to c# but all I am getting is a png image with a white background. My code snippet:
using (var img = new MagickImage("image.jpg"))
{
img.Format = MagickFormat.Png;
img.BackgroundColor = MagickColors.White;
img.ColorFuzz = new Percentage(10);
img.BackgroundColor = MagickColors.None;
img.Write("image.png");
}
Any kind of help will be greatly appreciated. Thank you!!
This is a late response as it took me a while to find an answer myself, but this seems to work for me quite well. Look at where the Background property is assigned the Transparent value.
using (var magicImage = new MagickImage())
{
var magicReadSettings = new MagickReadSettings
{
Format = MagickFormat.Svg,
ColorSpace = ColorSpace.Transparent,
BackgroundColor = MagickColors.Transparent,
// increasing the Density here makes a larger and sharper output to PNG
Density = new Density(950, DensityUnit.PixelsPerInch)
};
magicImage.Read("someimage.svg", magicReadSettings);
magicImage.Format = MagickFormat.Png;
magicImage.Write("someimage.png");
}
In my case, I wanted to send this to UWP Image element, so instead of Write(), I did the following after the steps above:
// Create byte array that contains a png file
byte[] imageData = magicImage.ToByteArray();
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
using (DataWriter writer = new DataWriter(stream.GetOutputStreamAt(0)))
{
writer.WriteBytes(imageData);
await writer.StoreAsync();
}
await bitmapImage.SetSourceAsync(stream);
}
return bitMapImage; // new BitMapImage() was scoped before all of this
Then on the UWP Image element, simply use:
imageElement.Source = bitMapImage;
Most of the arguments on the command line are either properties or method on the MagickImage class. Your command would translate to this:
using (var img = new MagickImage("image.jpg"))
{
// -fuzz XX%
img.ColorFuzz = new Percentage(10);
// -transparent white
img.Transparent(MagickColors.White);
img.Write("image.png");
}
I have created an excel file and want to export its contents as a png or jpeg file.
Unfortunately the quality of the image is really low.
Is there a solution to this? I wish a really high resolution picture.
Thank you
My current code (from internet):
Excel.Range xlRange = xlWorksheet5.get_Range("A1", "K30");
xlRange.CopyPicture(Excel.XlPictureAppearance.xlScreen, Excel.XlCopyPictureFormat.xlPicture);
Excel.ChartObject chartObj;
chartObj = xlWorksheet5.ChartObjects().Add(xlRange.Left, xlRange.Top, xlRange.Width, xlRange.Height);
chartObj.Activate();
string path_image = path + "\\image.png";
Excel.Chart chart = chartObj.Chart;
chart.Paste();
chart.Export(path_image);
Try this. You'll need to put a [STAThread] attribute over the entry point of whatever thread you run this on.
//This first copy/paste is to convert from chart to image
chartObj.CopyPicture();
xlWorksheet5.Paste();
//This image has decent resolution
xlWorksheet5.Shapes.Item(xlWorksheet5.Shapes.Count).Copy();
//Save the image
System.Windows.Media.Imaging.BitmapEncoder enc = new System.Windows.Media.Imaging.BmpBitmapEncoder();
enc.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(System.Windows.Clipboard.GetImage()));
using (System.IO.MemoryStream outStream = new System.IO.MemoryStream())
{
enc.Save(outStream);
System.Drawing.Image pic = new System.Drawing.Bitmap(outStream);
pic.Save("image.png");
}
I am taking pictures and would like to save them according to the time they were exactly taken.
I would also like to create a folder named /pictures in the current directory and save the pictures in that folder. This is done in C# & WPF.
This is my code:
Image newimage = new Image();
BitmapImage myBitmapImage = new BitmapImage();
myBitmapImage.BeginInit();
newimage.Source = Capture(true) // Take picture
myBitmapImage.UriSource = new Uri(#"c:\" +
string.Format("{0:yyyy-MM-dd_hh-mm-ss-tt}", DateTime.Now) + ".jpg");
// Gives error: Could not find file 'c:\2013-05-26_04-40-25-AM.jpg'
myBitmapImage.EndInit();
newimage.Source = myBitmapImage;
newstackPanel.Children.Add(newimage);
Results in:
ERROR Could not find file 'c:\2013-05-26_04-44-59-AM.jpg'.
Why is it trying to find a file VS just saving the file on the c:\ drive?
If all you want to do is to save the image to disk, then you should use the BitmapEncoder class
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
var image = Capture(true); // Take picture
encoder.Frames.Add(BitmapFrame.Create(image));
// Save the file to disk
var filename = String.Format("...");
using (var stream = new FileStream(filename, FileMode.Create))
{
encoder.Save(stream);
}
The above example creates a JPEG image, but you any encoder you want - WFP comes with Png, Tiff, Gif, Bmp and Wmp encoders built in.