Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have 400 sequence images.
I want to create from them video file ( clip .. mpeg )
I download the 'AForge.NET' and i try to look into it to see if it possible - but i don't fine any way to do it.
How can i do it ?
Look up the documentation, find the VideoFileWriter Class, look at it's members, see the WriteVideoFrame method(s), read the line: "Write new video frame into currently opened video file.". Bingo. Half way there.
If you can't connect the dots when reading the methods' signature (WriteVideoFrame(Bitmap)) or don't understand how to use the Open() overloads or Close() method (why wouldn't you, the last two are pretty common for File I/O) you can always Google "VideoFileWriter WriteVideoFrame example", find code, go from there. The meat of the function there is:
VideoFileWriter writer = new VideoFileWriter();
writer.Open("myfile.avi", width, height, 25, VideoCodec.MPEG4, 1000000);
// ... here you'll need to load your bitmaps
writer.WriteVideoFrame(image);
}
writer.Close();
So something like this should probably work:
using (VideoFileWriter writer = new VideoFileWriter())
{
writer.Open(#"d:\myfile.avi", 640, 480, 25, VideoCodec.MPEG4);
foreach (var file in Directory.GetFiles(#"d:\foo\bar", "*.jpg"))
{
writer.WriteVideoFrame(Bitmap.FromFile(file) as Bitmap);
}
writer.Close();
}
Which, with a few minutes of fiddling around, gave me something like this:
var size = new Size(1600, 1200); // The desired size of the video
var fps = 25; // The desired frames-per-second
var codec = VideoCodec.MPEG4; // Which codec to use
var destinationfile = #"d:\myfile.avi"; // Output file
var srcdirectory = #"d:\foo\bar"; // Directory to scan for images
var pattern = "*.jpg"; // Files to look for in srcdirectory
var searchoption = SearchOption.TopDirectoryOnly; // Search Top Directory Only or all subdirectories (recursively)?
using (var writer = new VideoFileWriter()) // Initialize a VideoFileWriter
{
writer.Open(destinationfile, size.Width, size.Height, fps, codec); // Start output of video
foreach (var file in Directory.GetFiles(srcdirectory, pattern, searchoption)) // Iterate files
{
using (var original = (Bitmap)Image.FromFile(file)) // Read bitmap
using (var resized = new Bitmap(original, size)) // Resize if necessary
writer.WriteVideoFrame(resized); // Write frame
}
writer.Close(); // Close VideoFileWriter
} // Dispose VideoFileWriter
This resizes images; should not all images in the sequence be the same. If they are you can skip that step simply by changing
using (var original = (Bitmap)Image.FromFile(file)) // Read bitmap
using (var resized = new Bitmap(original, size)) // Resize if necessary
writer.WriteVideoFrame(resized); // Write frame
to:
using (var mybitmap = (Bitmap)Image.FromFile(file)) // Read bitmap
writer.WriteVideoFrame(mybitmap); // Write frame
Also make sure you add the correct using statements; you will, at a minimum, need the following for above examples:
using AForge.Video.FFMPEG;
using System.Drawing;
using System.IO;
Also you'll need to reference the DLL's as described here:
... you should have created a project, added a reference to the AForge.Video.FFMPEG library, set the target platform to x86 and the target framework version to 3.5 or lower now. If so, it can go on.
... we need a few more dlls from the AForge archive. You can find these in the folder “Externals\ffmpeg” inside the AForge archive. All files in this folder have to be copied to the output folder of your Visual Studio project. (After we changed the target architecture this now should be “YourProjectFolder\bin\x86\Debug”.)
If it still doesn't work then tell us what happens, exact error messages etc.
Related
I have a requirement to insert a unique ID into image files without modifying the image content – ie it’s just the metadata that I want to modify. I’m starting with the JPEG files because there is an appropriate EXIF property available: ImageUniqueID.
I’m using C# with .NET Core 3.1 for this exercise with ImageSharp.
I can change the EXIF data with the ImageSharp using the following code (show simplified without existing record checks, etc):
using (var image = Image.Load(filename))
{
var imageUniqueIdentifier = Guid.NewGuid().ToString().ToLower().Replace("-", "");
image.Metadata.ExifProfile.SetValue(ExifTag.ImageUniqueID, imageUniqueIdentifier);
var jpegEncoder = new JpegEncoder() { Quality = 100 };
image.Save(filename, jpegEncoder);
}
I did play with the Quality setting in the JpegEncoder, but was still getting either unacceptable quality degradation or file size increases.
Is there a way of just reading the meta data, altering it and then writing it back without affecting the image at all?
I also looked at MetadataExtractor.NET but this doesn’t have a write facility and would happily look at other .NET Core methods or libraries.
After some research I've found that there is ExifLibrary which allow you to modify only image metadata.
Documentation (examples included)
Example how to add unique image id for jpg file:
var file = ImageFile.FromFile("path_to_jpg_file");
var imageUniqueIdentifier = Guid.NewGuid().ToString().ToLower().Replace("-", "");
file.Properties.Set(ExifLibrary.ExifTag.ImageUniqueID, imageUniqueIdentifier);
file.Save("path_to_jpg_file");
Nuget package: ExifLibNet.
Here is some code that just needs .NET with PresentationCore and WindowsBase. The underlying technology that WPF uses is WIC (Windows Imaging Component). WIC has full support for image metadata.
EXIF's ImageUniqueID is handled specifically as a Windows Property named System.Image.ImageID
Some other properties such as System.Photo.CameraModel can be seen directly in Windows Explorer detailed views if you add the corresponding column "Camera Model", but not System.Image.ImageID, AFAIK.
// needs PresentationCore & WindowsBase references
var frame = BitmapDecoder.Create(new Uri("test1.jpg", UriKind.RelativeOrAbsolute), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None).Frames[0];
// create encoder, add frame, we need to copy since we want to update metadata
var encoder = BitmapEncoder.Create(frame.Decoder.CodecInfo.ContainerFormat);
var copy = BitmapFrame.Create(frame);
// get frame metadata
var metaData = (BitmapMetadata)copy.Metadata;
// show existing System.Image.ImageID (if any)
Console.WriteLine("ImageUniqueID: " + metaData.GetQuery("System.Image.ImageID"));
// for some reason, we can't use "System.Image.ImageID" to set the meta data
// so use the "Metadata Query Language"
metaData.SetQuery("/app1/ifd/exif/{ushort=42016}", "My Super ID");
// write file back
encoder.Frames.Add(copy);
using (var stream = File.OpenWrite("test1copy.jpg"))
{
encoder.Save(stream);
}
My goal is to add company logo to every page of an existing pdf(not watermark).
Due to pdf file and logo specifics, I can only place the logo on top of the pdf content(not underneath) and the logo has to support transparency.
One more limitation is I have to use .NET Core.
Posting this with an answer, because I could not find a clear solution.
Suggestions/corrections/improvements are welcome.
Hope someone finds this useful.
The newest iTextSharp library to support .NET Core is iText7 however I cannot use it legitemately; neither making my code open source, nor purchasing the licence is an option for me. Therefore I use old, third party library:
Install-Package iTextSharp.LGPLv2.Core
Latest version, the one I'm using, at the time of this post is 1.3.2
Following usings are required
using System;
using System.Drawing.Imaging;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
To acheve image transparency in pdf, image has to be opened in a correct format
var preImage = System.Drawing.Image.FromFile(imagePath);
var image = Image.GetInstance(preImage, ImageFormat.Png);
When adding the image, it is also important to not select the image to be inline
canvas.AddImage(image);//do not put .AddImage(image, true);
Here is all the code
var imagePath = "logo.png";
var pdfPath = "edit_this.pdf";
//load pdf file
var pdfBytes = File.ReadAllBytes(pdfPath);
var oldFile = new PdfReader(pdfBytes);
//load image
var preImage = System.Drawing.Image.FromFile(imagePath);
var image = Image.GetInstance(preImage, ImageFormat.Png);
preImage.Dispose();
//optional: if image is wider than the page, scale down the image to fit the page
var sizeWithRotation = oldFile.GetPageSizeWithRotation(1);
if (image.Width > sizeWithRotation.Width)
image.ScalePercent(sizeWithRotation.Width / image.Width * 100);
//set image position in top left corner
//in pdf files, cooridinates start in the left bottom corner
image.SetAbsolutePosition(0, sizeWithRotation.Height - image.ScaledHeight);
//in production, I use MemoryStream
//I put FileStream here to test the code in console application
using (var newFileStream = new FileStream("with_logo.pdf", FileMode.Create))
{
//setup PdfStamper
var stamper = new PdfStamper(oldFile, newFileStream);
//iterate through the pages in the original file
for (var i = 1; i <= oldFile.NumberOfPages; i++)
{
//get canvas for current page
var canvas = stamper.GetOverContent(i);
//add image with pre-set position and size
canvas.AddImage(image);
}
stamper.Close();
}
This code works with local files.
In my (real world) case, I receive pdf files as Base64 string, add a logo from local storage, convert it back to Base64 string and output it on a web-page.
I open the image as PNG forcefully(hardcoded) because I control what extension does the logo have. If necessary you can dynamicaly set the image format.
This question already has answers here:
How to resize an animated gif image using C#?
(3 answers)
Closed 9 years ago.
I have a animated .gif images. I want to resize the images to specific height/width without losing the aniamtion part and want an output as stream.
or
Getthumbnail for the same images without losing the animation.
I have gone through the solutions mention related the same but not being able to solve.
Would any one mind providing sample code for the same.
Thanks in advance for any help.
(disclaimer - I work for Atalasoft)
If you use the Photo Free version of our toolkit, you can do something this:
// read in all the frames
GifDecoder decoder = new GifDecoder();
ImageInfo info = decoder.GetImageInfo(mySourceStream);
GifFrameCollection collection = decoder.Frames;
foreach (GifFrameFrame frame in collection)
{
// resize each frame
AtalaImage image = frame.Image;
AtalaImage resizedImage = new ReampleCommand(new Size(newWidth, newHeight)).Apply(image).Image;
frame.Image = resizedImage;
}
// set the size in the collection
collection.Width = newWith;
collection.Height = newHeight;
// save out to a stream
GifEncoder encoder = new GifEncoder();
encoder.Save(outputStream, collection, null);
My application receives a sequence of images (BitmapImage) from external device with rate 30 fps.
I'm using Aforge.net library for save the received stream in .avi file.
I used the following code for inizializing the AVIWriter:
AVIWriter writer;
writer = new AVIWriter("wmv3");
writer.FrameRate = 30;
writer.Open("test.avi", 320, 240);
And for each frame received I add it in the video stream, with the following code line:
writer.AddFrame(ResizeBitmap(BitmapImage2Bitmap(e.ColorFrame.BitmapImage),320,240));
But the generated file is too heavy. (10 secondos corresponds to about 3Mb).
I tryied also setting a low level of writer.Quality , but the result seems the same (just 5-7% less).
So, I need a more efficient compression.
What are the compressions supported in Aforge.net ? What compression should I use in order to reducing the weight of saved file?
I suspect that interframe compression is not used in AVIWriter (but I may be wrong).
You may try to use VideoFileWriter from Aforge.Video.FFMPEG instead:
var writer = new VideoFileWriter();
writer.Open("test.mpg", 320, 240, 30, VideoCodec.Default, 1000);
// add your frame
writer.WriteVideoFrame(frame);
Remember to put dlls from Externals/ffmpeg/bin from AForge zip into your output directory.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
Improve this question
I have found various code and libraries for editing Exif.
But they are only lossless when the image width and height is multiple of 16.
I am looking for a library (or even a way to do it myself) to edit just the Exif portion in a JPEG file (or add Exif data if it doesn't exist yet), leaving the other data unmodified. Isn't that possible?
So far I could only locate the Exif portion (starts with 0xFFE1) but I don't understand how to read the data.
Here are the specifications for the Exif interchange format, if you plan to code your own library for editing tags.
http://www.exif.org/specifications.html
Here's a library written in Perl that meets your needs that you may be able to learn from:
http://www.sno.phy.queensu.ca/~phil/exiftool/
Here's a decent .NET library for Exif evaluation from The Code Project:
http://www.codeproject.com/KB/graphics/exiftagcol.aspx
You can do this without any external lib:
// Create image.
Image image1 = Image.FromFile("c:\\Photo1.jpg");
// Get a PropertyItem from image1. Because PropertyItem does not
// have public constructor, you first need to get existing PropertyItem
PropertyItem propItem = image1.GetPropertyItem(20624);
// Change the ID of the PropertyItem.
propItem.Id = 20625;
// Set the new PropertyItem for image1.
image1.SetPropertyItem(propItem);
// Save the image.
image1.Save("c:\\Photo1.jpg", ImageFormat.Jpg);
List of all possible PropertyItem ids (including exif) you can found here.
Update: Agreed, this method will re-encode image on save. But I have remembered another method, in WinXP SP2 and later there is new imaging components added - WIC, and you can use them to lossless write metadate - How-to: Re-encode a JPEG Image with Metadata.
exiv2net library (a .NET wrapper on top of exiv2) may be what you're looking for.
I wrote a small test where I compress one file many times to see the quality degradation and you can see it in the third-fourth compression, which is very bad.
But luckily, if you always use same QualityLevel with JpegBitmapEncoder there is no degradation.
In this example I rewrite keywords 100x in metadata and the quality seems not to change.
private void LosslessJpegTest() {
var original = "d:\\!test\\TestInTest\\20150205_123011.jpg";
var copy = original;
const BitmapCreateOptions createOptions = BitmapCreateOptions.PreservePixelFormat | BitmapCreateOptions.IgnoreColorProfile;
for (int i = 0; i < 100; i++) {
using (Stream originalFileStream = File.Open(copy, FileMode.Open, FileAccess.Read)) {
BitmapDecoder decoder = BitmapDecoder.Create(originalFileStream, createOptions, BitmapCacheOption.None);
if (decoder.CodecInfo == null || !decoder.CodecInfo.FileExtensions.Contains("jpg") || decoder.Frames[0] == null)
continue;
BitmapMetadata metadata = decoder.Frames[0].Metadata == null
? new BitmapMetadata("jpg")
: decoder.Frames[0].Metadata.Clone() as BitmapMetadata;
if (metadata == null) continue;
var keywords = metadata.Keywords == null ? new List<string>() : new List<string>(metadata.Keywords);
keywords.Add($"Keyword {i:000}");
metadata.Keywords = new ReadOnlyCollection<string>(keywords);
JpegBitmapEncoder encoder = new JpegBitmapEncoder {QualityLevel = 80};
encoder.Frames.Add(BitmapFrame.Create(decoder.Frames[0], decoder.Frames[0].Thumbnail, metadata,
decoder.Frames[0].ColorContexts));
copy = original.Replace(".", $"_{i:000}.");
using (Stream newFileStream = File.Open(copy, FileMode.Create, FileAccess.ReadWrite)) {
encoder.Save(newFileStream);
}
}
}
}