FF-1543: Using ImageMagick for PDF operations in comics

This commit is contained in:
John Andrews
2024-05-12 13:05:12 +12:00
parent cd2a071628
commit 4d6203a8ba
7 changed files with 145 additions and 122 deletions
-3
View File
@@ -23,9 +23,6 @@
<PackageReference Include="MSTest.TestAdapter" Version="3.3.1" />
<PackageReference Include="MSTest.TestFramework" Version="3.3.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Docnet.Core" Version="2.6.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="FileFlows.Plugin">
<HintPath>..\FileFlows.Plugin.dll</HintPath>
+30 -8
View File
@@ -143,7 +143,7 @@ public class ComicConverter: Node
var metadata = new Dictionary<string, object>();
metadata.Add("Format", currentFormat);
var pageCountResult = GetPageCount(args, currentFormat, localFile);
if (pageCountResult.Success(out int pageCount))
if (pageCountResult.Success(out int pageCount) && pageCount > 0)
{
args.Logger?.ILog("Page Count: " + pageCount);
metadata.Add("Pages", pageCount);
@@ -289,9 +289,15 @@ public class ComicConverter: Node
if (cancellation.IsCancellationRequested)
return -1;
string newFile = CreateComic(args, destinationPath, this.Format);
var newFileResult = CreateComic(args, destinationPath, this.Format);
if (newFileResult.Failed(out error))
{
args.FailureReason = "Failed Creating Comic: " + error;
args.Logger?.ELog(args.FailureReason);
return -1;
}
args.SetWorkingFile(newFile);
args.SetWorkingFile(newFileResult.Value);
return 1;
}
@@ -321,7 +327,7 @@ public class ComicConverter: Node
switch (format)
{
case "PDF":
return Helpers.PdfHelper.GetPageCount(file);
return 0; //Helpers.PdfHelper.GetPageCount(file);
default:
return args.ArchiveHelper.GetFileCount(file,@"\.(jpeg|jpg|jpe|jp2|png|bmp|tiff|webp|gif)$");
}
@@ -335,18 +341,30 @@ public class ComicConverter: Node
/// <param name="format">the format to create the comic</param>
/// <returns>the path to the newly created comic</returns>
/// <exception cref="Exception">if the format is not supported</exception>
private string CreateComic(NodeParameters args, string directory, string format)
private Result<string> CreateComic(NodeParameters args, string directory, string format)
{
string file = Path.Combine(args.TempPath, Guid.NewGuid() + "." + format.ToLower());
args.Logger?.ILog("Creating comic: " + file);
int? pageCount = null;
if (format == "CBZ")
args.ArchiveHelper.Compress(directory, file);
//else if (format == "CB7")
// Helpers.SevenZipHelper.Compress(args, directory, file + ".7z");
else if (format == "PDF")
Helpers.PdfHelper.Create(args, directory, file);
{
var images = new DirectoryInfo(directory).GetFiles("*.*")
.Where(x => Regex.IsMatch(x.Extension, @"\.(jpeg|jpe|jpg|webp|png)$",
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant))
.OrderBy(x => x.Name)
.Select(x => x.FullName)
.ToArray();
if (args.ImageHelper.CreatePdfFromImages(file, images).Failed(out string error))
return Result<string>.Fail(error);
pageCount = images.Length;
//Helpers.PdfHelper.Create(args, directory, file);
}
else
throw new Exception("Unknown format:" + format);
return Result<string>.Fail("Unknown format:" + format);
Directory.Delete(directory, true);
args.Logger?.ILog("Created comic: " + file);
args.Logger?.ILog("Deleted temporary extraction directory: " + directory);
@@ -354,8 +372,12 @@ public class ComicConverter: Node
var metadata = new Dictionary<string, object>();
metadata.Add("Format", format);
if(GetPageCount(args, format, file).Success(out var count))
if(pageCount != null)
metadata.Add("Pages", pageCount.Value);
else if(GetPageCount(args, format, file).Success(out var count) && count > 0)
metadata.Add("Pages", count);
args.SetMetadata(metadata);
args.Logger?.ILog("Setting metadata: " + format);
+5 -1
View File
@@ -31,7 +31,11 @@ internal class ComicExtractor
args.Logger?.ILog("Extracting comic pages to: " + destinationPath);
if (currentFormat == "PDF")
PdfHelper.Extract(args, file, destinationPath, "page", halfProgress: halfProgress, cancellation: cancellation);
{
args.ImageHelper.ExtractPdfImages(file, destinationPath);
// PdfHelper.Extract(args, file, destinationPath, "page", halfProgress: halfProgress,
// cancellation: cancellation);
}
else if (currentFormat is "CBZ" or "CB7" or "CBR" or "GZ" or "BZ2")
return args.ArchiveHelper.Extract(file, destinationPath, (percent) =>
{
+108 -108
View File
@@ -1,108 +1,108 @@
using Docnet.Core;
using Docnet.Core.Editors;
using Docnet.Core.Models;
namespace FileFlows.ComicNodes.Helpers;
internal class PdfHelper
{
public static void Extract(NodeParameters args, string pdfFile, string destinationDirectory, string filePrefix, bool halfProgress, CancellationToken cancellation)
{
using var library = DocLib.Instance;
using var docReader = library.GetDocReader(pdfFile, new PageDimensions(1080, 1920));
if (args?.PartPercentageUpdate != null)
args?.PartPercentageUpdate(halfProgress ? 50 : 0);
int pageCount = docReader.GetPageCount();
for (int i = 1; i < pageCount; i++)
{
using var pageReader = docReader.GetPageReader(i);
var rawBytes = pageReader.GetImage();
var file = Path.Combine(destinationDirectory,
filePrefix + "-" + i.ToString(new string('0', pageCount.ToString().Length)));
var result = args!.ImageHelper.SaveImage(rawBytes, file);
if (result.Failed(out string error))
{
args.Logger?.WLog("Failed to save image: " + error);
continue;
}
if (args?.PartPercentageUpdate != null)
{
float percent = (i / pageCount) * 100f;
if (halfProgress)
percent = (percent / 2);
args?.PartPercentageUpdate(percent);
}
if (cancellation.IsCancellationRequested)
return;
}
if (args?.PartPercentageUpdate != null)
args?.PartPercentageUpdate(halfProgress ? 50 : 0);
}
/// <summary>
/// Creates a PDF from images
/// </summary>
/// <param name="args">the NodeParameters</param>
/// <param name="directory">the directory to of images</param>
/// <param name="output">the output file of the pdf</param>
/// <param name="halfProgress">if the NodePArameter.PartPercentageUpdate should start at 50%</param>
internal static void Create(NodeParameters args, string directory, string output, bool halfProgress = true)
{
if (args.PartPercentageUpdate != null)
args.PartPercentageUpdate(halfProgress ? 50 : 0);
var rgxImages = new Regex(@"\.(jpeg|jpg|jpe|png|webp)$");
var files = Directory.GetFiles(directory).Where(x => rgxImages.IsMatch(x)).ToArray();
List<JpegImage> images = new List<JpegImage>();
for(int i = 0; i < files.Length; i++)
{
var file = files[i];
if (file.ToLowerInvariant().EndsWith(".png") || file.ToLowerInvariant().EndsWith(".webp"))
{
string jpegImage = Path.ChangeExtension(file, "jpg");
args!.ImageHelper.ConvertToJpeg(file, jpegImage, null);
file = jpegImage;
}
(int width, int height) = args!.ImageHelper.GetDimensions(file).Value;
var jpeg = new JpegImage
{
Bytes = File.ReadAllBytes(file),
Width = width,
Height = height
};
images.Add(jpeg);
if (args?.PartPercentageUpdate != null)
{
float percent = (i / ((float)files.Length)) * 100f;
if (halfProgress)
percent = 50 + (percent / 2);
args?.PartPercentageUpdate(percent);
}
}
var bytes = DocLib.Instance.JpegToPdf(images);
File.WriteAllBytes(output, bytes);
if (args?.PartPercentageUpdate != null)
args?.PartPercentageUpdate(100);
}
/// <summary>
/// Gets the number of pages in a PDF
/// </summary>
/// <param name="pdfFile">the PDF file</param>
/// <returns>the number of pages in the PDF</returns>
internal static int GetPageCount(string pdfFile)
{
using var library = DocLib.Instance;
using var docReader = library.GetDocReader(pdfFile, new PageDimensions(1080, 1920));
return docReader.GetPageCount();
}
}
// using Docnet.Core;
// using Docnet.Core.Editors;
// using Docnet.Core.Models;
//
// namespace FileFlows.ComicNodes.Helpers;
//
// internal class PdfHelper
// {
// public static void Extract(NodeParameters args, string pdfFile, string destinationDirectory, string filePrefix, bool halfProgress, CancellationToken cancellation)
// {
// using var library = DocLib.Instance;
// using var docReader = library.GetDocReader(pdfFile, new PageDimensions(1080, 1920));
//
// if (args?.PartPercentageUpdate != null)
// args?.PartPercentageUpdate(halfProgress ? 50 : 0);
//
// int pageCount = docReader.GetPageCount();
// for (int i = 1; i < pageCount; i++)
// {
// using var pageReader = docReader.GetPageReader(i);
// var rawBytes = pageReader.GetImage();
//
// var file = Path.Combine(destinationDirectory,
// filePrefix + "-" + i.ToString(new string('0', pageCount.ToString().Length)));
// var result = args!.ImageHelper.SaveImage(rawBytes, file);
// if (result.Failed(out string error))
// {
// args.Logger?.WLog("Failed to save image: " + error);
// continue;
// }
//
// if (args?.PartPercentageUpdate != null)
// {
// float percent = (i / pageCount) * 100f;
// if (halfProgress)
// percent = (percent / 2);
// args?.PartPercentageUpdate(percent);
// }
// if (cancellation.IsCancellationRequested)
// return;
// }
// if (args?.PartPercentageUpdate != null)
// args?.PartPercentageUpdate(halfProgress ? 50 : 0);
// }
//
// /// <summary>
// /// Creates a PDF from images
// /// </summary>
// /// <param name="args">the NodeParameters</param>
// /// <param name="directory">the directory to of images</param>
// /// <param name="output">the output file of the pdf</param>
// /// <param name="halfProgress">if the NodePArameter.PartPercentageUpdate should start at 50%</param>
// internal static void Create(NodeParameters args, string directory, string output, bool halfProgress = true)
// {
// if (args.PartPercentageUpdate != null)
// args.PartPercentageUpdate(halfProgress ? 50 : 0);
// var rgxImages = new Regex(@"\.(jpeg|jpg|jpe|png|webp)$");
// var files = Directory.GetFiles(directory).Where(x => rgxImages.IsMatch(x)).ToArray();
//
// List<JpegImage> images = new List<JpegImage>();
// for(int i = 0; i < files.Length; i++)
// {
// var file = files[i];
// if (file.ToLowerInvariant().EndsWith(".png") || file.ToLowerInvariant().EndsWith(".webp"))
// {
// string jpegImage = Path.ChangeExtension(file, "jpg");
// args!.ImageHelper.ConvertToJpeg(file, jpegImage, null);
// file = jpegImage;
// }
//
// (int width, int height) = args!.ImageHelper.GetDimensions(file).Value;
//
// var jpeg = new JpegImage
// {
// Bytes = File.ReadAllBytes(file),
// Width = width,
// Height = height
// };
// images.Add(jpeg);
//
// if (args?.PartPercentageUpdate != null)
// {
// float percent = (i / ((float)files.Length)) * 100f;
// if (halfProgress)
// percent = 50 + (percent / 2);
// args?.PartPercentageUpdate(percent);
// }
// }
//
// var bytes = DocLib.Instance.JpegToPdf(images);
// File.WriteAllBytes(output, bytes);
//
// if (args?.PartPercentageUpdate != null)
// args?.PartPercentageUpdate(100);
// }
//
// /// <summary>
// /// Gets the number of pages in a PDF
// /// </summary>
// /// <param name="pdfFile">the PDF file</param>
// /// <returns>the number of pages in the PDF</returns>
// internal static int GetPageCount(string pdfFile)
// {
// using var library = DocLib.Instance;
// using var docReader = library.GetDocReader(pdfFile, new PageDimensions(1080, 1920));
// return docReader.GetPageCount();
// }
// }
Binary file not shown.
Binary file not shown.
+2 -2
View File
@@ -21,8 +21,8 @@ public abstract class TestBase
/// </summary>
public TestContext TestContext
{
get { return testContextInstance; }
set { testContextInstance = value; }
get => testContextInstance;
set => testContextInstance = value;
}
public string TestPath { get; private set; }