With that code I can split a multi tiff and save the images to files.
public void SplitImage(string file)
{
Bitmap bitmap = (Bitmap)Image.FromFile(file);
int count = bitmap.GetFrameCount(FrameDimension.Page);
var new_files = file.Split("_");
String new_file = new_files[new_files.Length - 1];
for (int idx = 0; idx < count; idx++)
{
bitmap.SelectActiveFrame(FrameDimension.Page, idx);
bitmap.Save($"C:\\temp\\{idx}-{new_file}", ImageFormat.Tiff);
}
}
here the code for the Pdf creation
public void CreatePDFFromImages(string path_multi_tiff)
{
Image img = new Image(ImageDataFactory.Create(path_multi_tiff));
var p = new Paragraph("Image").Add(img);
var writer = new PdfWriter("C:\\temp\\test.pdf");
var pdf = new PdfDocument(writer);
var document = new Document(pdf);
document.Add(new Paragraph("Images"));
document.Add(p);
document.Close();
Console.WriteLine("Done !");
}
now I would like to save the images to pdf pages and tried it with iText7. But this fails as
using System.Drawing.Imaging;
using Image = iText.Layout.Element.Image;
are to close to have them both in the same class. How could I save the splitted images to PDF pages ? I would like to avoid saving first to files and reloading all the images.
The line
using Image = iText.Layout.Element.Image;
is a so-called using alias directive. It creates the alias Image for the namespace or type iText.Layout.Element.Image. If this poses a problem, you can simply create a different alias. For example
using A = iText.Layout.Element.Image;
will create the alias A for the namespace or type iText.Layout.Element.Image.
After my method converts SVG code to PNG, it draw lines inside of square. Originally they were just square borders.
private void svgToPng(int itemId)
{
// Load created svg file
XmlDocument doc = new XmlDocument();
doc.Load("...\\lastCreated.svg");
XmlReader svgSrc = new XmlNodeReader(doc);
string svgSaveAs = "...\\lastCreated.png";
var quality = 100;
var svg = new SkiaSharp.Extended.Svg.SKSvg();
var pict = svg.Load(svgSrc);
var dimen = new SkiaSharp.SKSizeI
(
(int) Math.Ceiling(pict.CullRect.Width),
(int) Math.Ceiling(pict.CullRect.Height)
);
var matrix = SKMatrix.MakeScale(1, 1);
var img = SKImage.FromPicture(pict, dimen, matrix);
// Convert to PNG
var skdata = img.Encode(SkiaSharp.SKEncodedImageFormat.Png, quality);
using(var stream = System.IO.File.OpenWrite(svgSaveAs))
{
skdata.SaveTo(stream);
}
// Upload image
uploadImage("...\\lastCreated.png", itemId);
}
Here is pictures
Good:
Bad:
The best way is to use Inkscape via Process. Don't even try to use libraries, all of them have bugs.
I would check out https://github.com/wieslawsoltes/Svg.Skia
This library is far more complete and supports most of the SVG spec.
I am working on reading text from an image through OCR. It only supports TIFF format images.
So, I need to convert other formats to TIFF format. Can it be done? Please help by providing some references.
If you create an Image object in .NET, you can save it as a TIFF. It is one of the many ImageFormat choices at your disposal.
Example:
var png = Image.FromFile("some.png");
png.Save("a.tiff", ImageFormat.Tiff);
You'll need to include the System.Drawing assembly in your project. That assembly will give you a lot of image manipulation capabilities. Hope that helps.
Intro Note:
This answer cover the Bounty Question; which is: How do we
convert multiple files into 1 tiff? For example, let's say have pdfs,
jpegs, pngs, and I'd like to create 1 tiff out of them?
In this answer I use .net implementation of https://imagemagick.org/index.php for image manipulation and and Ghostscript for helping read an AI/EPS/PDF/PS file so we can translate it to image files both are credible and official source.
After I answered this question I got some extra question in my email asking other merging options, I have therefore extended my answer.
IMO there are 2 steps to your goal:
Install required tools for pdf conversion
Take all images including pdf formatted files from source and merge them together
in one tiff file.
1. Install tools that helps Pdf to Image conversion:
Step 1 is only required if you intend to convert AI/EPS/PDF/PS file formats. Otherwise just jump to step2.
To make it possible converting pdf to any image format, we need a library that can read pdf files and we need a tool to convert it to image type. For this purpose, we will need to install Ghostscript (GNU Affero General Public License).
Here after, we need to install ImageMagick.net for .net in Visual Studio, nuget link.
So far so good.
2. Code part
Second and Last step is we need to read files (png, jpg, bmp, pdf etc) from folder location and add each file to MagickImageCollection, then we have several options to merge use AppendHorizontally, AppendVertically, Montage or Multiple page Tiff. ImageMagick has tons of features, like resizing, resolution etc, this is just example to demonstrate merging features:
public static void MergeImage(string src, string dest, MergeType type = MergeType.MultiplePage)
{
var files = new DirectoryInfo(src).GetFiles();
using (var images = new MagickImageCollection())
{
foreach (var file in files)
{
var image = new MagickImage(file)
{
Format = MagickFormat.Tif,
Depth = 8,
};
images.Add(image);
}
switch (type)
{
case MergeType.Vertical:
using (var result = images.AppendVertically())
{
result.AdaptiveResize(new MagickGeometry(){Height = 600, Width = 800});
result.Write(dest);
}
break;
case MergeType.Horizontal:
using (var result = images.AppendHorizontally())
{
result.AdaptiveResize(new MagickGeometry(){Height = 600, Width = 800});
result.Write(dest);
}
break;
case MergeType.Montage:
var settings = new MontageSettings
{
BackgroundColor = new MagickColor("#FFF"),
Geometry = new MagickGeometry("1x1<")
};
using (var result = images.Montage(settings))
{
result.Write(dest);
}
break;
case MergeType.MultiplePage:
images.Write(dest);
break;
default:
throw new ArgumentOutOfRangeException(nameof(type), type, "Un-support choice");
}
images.Dispose();
}
}
public enum MergeType
{
MultiplePage,
Vertical,
Horizontal,
Montage
}
To run the code
public static void Main(string[] args)
{
var src = #"C:\temp\Images";
var dest1 = #"C:\temp\Output\MultiplePage.tiff";
var dest2 = #"C:\temp\Output\Vertical.tiff";
var dest3 = #"C:\temp\Output\Horizontal.tiff";
var dest4 = #"C:\temp\Output\Montage.tiff";
MergeImage(src, dest1);
MergeImage(src, dest2, MergeType.Vertical);
MergeImage(src, dest3, MergeType.Horizontal);
MergeImage(src, dest4, MergeType.Montage);
}
Here is 4 input files in C:\temp\Images:
After running the code, we get 4 new files under C:\temp\Output looks like this:
4 page Multiple Page Tiff
4 image Vertical Merge
4 image Horizontal Merge
4 image Montage Merge
Final note:
it is possible to merge multiple images to tiff using System.Drawing; and using System.Drawing.Imaging; with out using ImageMagick, but pdf does require a third party conversion library or tool, therefore I use Ghostscript and ImageMagick for C#.
ImageMagick has many features, so you can change the resolution, size of output file etc. it is well recognized library.
Disclaimer: A part of this answer is taken from my my personal web site https://itbackyard.com/how-to-convert-ai-eps-pdf-ps-to-image-file/ with source code to github.
To be covert the image in tif format.In the below example to be convert the image and set to a text box.to be see the image in text box is (.tif formate).This sources code is working.
private void btn_Convert(object sender, EventArgs e)
{
string newName = System.IO.Path.GetFileNameWithoutExtension(CurrentFile);
newName = newName + ".tif";
try
{
img.Save(newName, ImageFormat.Tiff);
}
catch (Exception ex)
{
string error = ee.Message.ToString();
MessageBox.Show(MessageBoxIcon.Error);
}
textBox2.Text = System.IO.Path.GetFullPath(newName.ToString());
}
I tested this with jpg, bmp, png, and gif. Works for single and multipage creation of tiffs. Pass it a full pathname to the file. Hope it helps someone. (extracted from MSDN)
public static string[] ConvertJpegToTiff(string[] fileNames, bool isMultipage)
{
EncoderParameters encoderParams = new EncoderParameters(1);
ImageCodecInfo tiffCodecInfo = ImageCodecInfo.GetImageEncoders()
.First(ie => ie.MimeType == "image/tiff");
string[] tiffPaths = null;
if (isMultipage)
{
tiffPaths = new string[1];
System.Drawing.Image tiffImg = null;
try
{
for (int i = 0; i < fileNames.Length; i++)
{
if (i == 0)
{
tiffPaths[i] = String.Format("{0}\\{1}.tif",
Path.GetDirectoryName(fileNames[i]),
Path.GetFileNameWithoutExtension(fileNames[i]));
// Initialize the first frame of multipage tiff.
tiffImg = System.Drawing.Image.FromFile(fileNames[i]);
encoderParams.Param[0] = new EncoderParameter(
System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.MultiFrame);
tiffImg.Save(tiffPaths[i], tiffCodecInfo, encoderParams);
}
else
{
// Add additional frames.
encoderParams.Param[0] = new EncoderParameter(
System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.FrameDimensionPage);
using (System.Drawing.Image frame = System.Drawing.Image.FromFile(fileNames[i]))
{
tiffImg.SaveAdd(frame, encoderParams);
}
}
if (i == fileNames.Length - 1)
{
// When it is the last frame, flush the resources and closing.
encoderParams.Param[0] = new EncoderParameter(
System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.Flush);
tiffImg.SaveAdd(encoderParams);
}
}
}
finally
{
if (tiffImg != null)
{
tiffImg.Dispose();
tiffImg = null;
}
}
}
else
{
tiffPaths = new string[fileNames.Length];
for (int i = 0; i < fileNames.Length; i++)
{
tiffPaths[i] = String.Format("{0}\\{1}.tif",
Path.GetDirectoryName(fileNames[i]),
Path.GetFileNameWithoutExtension(fileNames[i]));
// Save as individual tiff files.
using (System.Drawing.Image tiffImg = System.Drawing.Image.FromFile(fileNames[i]))
{
tiffImg.Save(tiffPaths[i], ImageFormat.Tiff);
}
}
}
return tiffPaths;
}
ImageMagick command line can do that easily. It is supplied on most Linux systems and is available for Mac or Windows also. See https://imagemagick.org/script/download.php
convert image.suffix -compress XXX image.tiff
or you can process a whole folder of files using
mogrify -format tiff -path path/to/output_directory *
ImageMagick supports combining multiple images into a multi-page TIFF. And the images can be of mixed types even including PDF.
convert image1.suffix1 image2.suffix2 ... -compress XXX imageN.suffixN output.tiff
You can choose from a number of compression formats or no compression.
See
https://imagemagick.org/script/command-line-processing.php
https://imagemagick.org/Usage/basics/
https://imagemagick.org/Usage/basics/#mogrify
https://imagemagick.org/script/command-line-options.php#compress
Or you can use Magick.Net for a C# interface. See https://github.com/dlemstra/Magick.NET
Main ImageMagick page is at https://imagemagick.org.
Supported formats are listed at https://imagemagick.org/script/formats.php
You can easily process your images to resize them, convert to grayscale, filter (sharpen), threshold, etc, all in the same command line.
See
https://imagemagick.org/Usage/
https://imagemagick.org/Usage/reference.html
This is how I convert images that are uploaded to a website. Changed it so it outputs Tiff files. The method input and outputs a byte array so it can easily be used in a variety of ways. But you can easily modify it.
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
public byte[] ConvertImageToTiff(byte[] SourceImage)
{
//create a new byte array
byte[] bin = new byte[0];
//check if there is data
if (SourceImage == null || SourceImage.Length == 0)
{
return bin;
}
//convert the byte array to a bitmap
Bitmap NewImage;
using (MemoryStream ms = new MemoryStream(SourceImage))
{
NewImage = new Bitmap(ms);
}
//set some properties
Bitmap TempImage = new Bitmap(NewImage.Width, NewImage.Height);
using (Graphics g = Graphics.FromImage(TempImage))
{
g.CompositingMode = CompositingMode.SourceCopy;
g.CompositingQuality = CompositingQuality.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawImage(NewImage, 0, 0, NewImage.Width, NewImage.Height);
}
NewImage = TempImage;
//save the image to a stream
using (MemoryStream ms = new MemoryStream())
{
EncoderParameters encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 80L);
NewImage.Save(ms, GetEncoderInfo("image/tiff"), encoderParameters);
bin = ms.ToArray();
}
//cleanup
NewImage.Dispose();
TempImage.Dispose();
//return data
return bin;
}
//get the correct encoder info
public ImageCodecInfo GetEncoderInfo(string MimeType)
{
ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
for (int j = 0; j < encoders.Length; ++j)
{
if (encoders[j].MimeType.ToLower() == MimeType.ToLower())
return encoders[j];
}
return null;
}
To test
var oldImage = File.ReadAllBytes(Server.MapPath("OldImage.jpg"));
var newImage = ConvertImageToTiff(oldImage);
File.WriteAllBytes(Server.MapPath("NewImage.tiff"), newImage);
I'm trying to save a copy of the source file directly into a response output stream. But, as a result of this code, the browser window has a dark background. How can I do it without using а MemoryStream?
public static void CreateCollage(IEnumerable<Stamp> stamps, Stream input)
{
using (PdfDocument outDoc = new PdfDocument())
using (PdfDocument inputDoc = PdfReader.Open(input, PdfDocumentOpenMode.Import))
{
for (int i = 0; i < inputDoc.PageCount; i++)
{
var page = inputDoc.Pages[i];
var pageOut = outDoc.AddPage(page);
foreach (var stamp in stamps.Where(s => s.xyp.page == (i + 1)))
InsertData(pageOut, stamp, page.Width.Value, page.Height.Value);
}
outDoc.Save(context.Response.OutputStream, true);
}
}
If I use Save() function - I get an error:
The specified method is not supported.
in System.Web.HttpResponseStream.get_Position()
in PdfSharp.Pdf.IO.PdfWriter.WriteFileHeader(PdfDocument document)
in d:\Users\yudina\Desktop\pdfsharp\PDFsharp\src\PdfSharp\Pdf.IO\PdfWriter.cs:row 488
You do not call outDoc.Close() and nothing ever gets written into your OutputStream.
I have the following code but this code add only the last image into pdf.
try {
filePath = (filePath != null && filePath.endsWith(".pdf")) ? filePath
: filePath + ".pdf";
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document,
new FileOutputStream(filePath));
document.open();
// document.add(new Paragraph("Image Example"));
for (String imageIpath : imagePathsList) {
// Add Image
Image image1 = Image.getInstance(imageIpath);
// Fixed Positioning
image1.setAbsolutePosition(10f, 10f);
// Scale to new height and new width of image
image1.scaleAbsolute(600, 800);
// image1.scalePercent(0.5f);
// Add to document
document.add(image1);
//document.bottom();
}
writer.close();
} catch (Exception e) {
LOGGER.error(e.getMessage());
}
Would you give me a hint about how to update the code in order to add all the images into the exported pdf? imagePathsList contains all the paths of images that that I want to add into a single pdf.
Best Regards,
Aurelian
Take a look at the MultipleImages example and you'll discover that there are two errors in your code:
You create a page with size 595 x 842 user units, and you add every image to that page regardless of the dimensions of the image.
You claim that only one image is added, but that's not true. You are adding all the images on top of each other on the same page. The last image covers all the preceding images.
Take a look at my code:
public void createPdf(String dest) throws IOException, DocumentException {
Image img = Image.getInstance(IMAGES[0]);
Document document = new Document(img);
PdfWriter.getInstance(document, new FileOutputStream(dest));
document.open();
for (String image : IMAGES) {
img = Image.getInstance(image);
document.setPageSize(img);
document.newPage();
img.setAbsolutePosition(0, 0);
document.add(img);
}
document.close();
}
I create a Document instance using the size of the first image. I then loop over an array of images, setting the page size of the next page to the size of each image before I trigger a newPage() [*]. Then I add the image at coordinate 0, 0 because now the size of the image will match the size of each page.
[*] The newPage() method only has effect if something was added to the current page. The first time you go through the loop, nothing has been added yet, so nothing happens. This is why you need set the page size to the size of the first image when you create the Document instance.
Android has the feature "PdfDocument" to achieve this,
class Main2Activity : AppCompatActivity() {
private var imgFiles: Array<File?>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
imgFiles= arrayOfNulls(2)
imgFiles!![0] = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString() + "/doc1.png")
imgFiles!![1] = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString() + "/doc3.png")
val file = getOutputFile(File(Environment.getExternalStorageDirectory().absolutePath)
, "/output.pdf")
val fOut = FileOutputStream(file)
val document = PdfDocument()
var i = 0
imgFiles?.forEach {
i++
val bitmap = BitmapFactory.decodeFile(it?.path)
val pageInfo = PdfDocument.PageInfo.Builder(bitmap.width, bitmap.height, i).create()
val page = document.startPage(pageInfo)
val canvas = page?.canvas
val paint = Paint()
canvas?.drawPaint(paint)
paint.color = Color.BLUE;
canvas?.drawBitmap(bitmap, 0f, 0f, null)
document.finishPage(page)
bitmap.recycle()
}
document.writeTo(fOut)
document.close()
}
private fun getOutputFile(path: File, fileName: String): File? {
if (!path.exists()) {
path.mkdirs()
}
val file = File(path, fileName)
try {
if (file.exists()) {
file.delete()
}
file.createNewFile()
} catch (e: Exception) {
e.printStackTrace()
}
return file
}
}
finally enable the storage permission in manifest, this should works