Improved support for magazines

additional output of tablet/150dpi version -  fixed parallel run.

FIXME parallel task doesn't always run smoothly.. force run single threaded   afterwards
This commit is contained in:
tomse 2024-03-04 23:45:14 +01:00
parent a314d4d1f8
commit 01387b9e4c
2 changed files with 216 additions and 182 deletions

View File

@ -145,6 +145,8 @@ namespace PDFWorkflowManager
// Path where banner pages are located // Path where banner pages are located
private string strExeFilePath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); private string strExeFilePath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
private SemaphoreSlim semaphore = new SemaphoreSlim(1);
string bannerPage = ""; string bannerPage = "";
private string workDir = Properties.Settings.Default.WorkDir; private string workDir = Properties.Settings.Default.WorkDir;
@ -153,6 +155,9 @@ namespace PDFWorkflowManager
private string tempDir = Properties.Settings.Default.TempDir; private string tempDir = Properties.Settings.Default.TempDir;
private string strPostProcessor = Properties.Settings.Default.PostProcessor; private string strPostProcessor = Properties.Settings.Default.PostProcessor;
private string strExtension = "tif"; private string strExtension = "tif";
private string bannerPageA5 = "banner_a5.pdf";
public MainForm() public MainForm()
{ {
@ -234,6 +239,7 @@ namespace PDFWorkflowManager
btnMakePDF.Enabled = true; btnMakePDF.Enabled = true;
//public string txtPostProcessor.text = ""; //public string txtPostProcessor.text = "";
} }
@ -550,7 +556,7 @@ namespace PDFWorkflowManager
Application.Exit(); Application.Exit();
} }
private string prepCopyToTempOutdir(int sourceFileCount, string[] strFiles, string sourceDir) private string prepCopyToTempOutdir(int sourceFileCount, string[] strFiles)
{ {
string tempSortDir = Path.Combine(tempDir, "sort"); string tempSortDir = Path.Combine(tempDir, "sort");
Directory.CreateDirectory(tempSortDir); Directory.CreateDirectory(tempSortDir);
@ -602,23 +608,40 @@ namespace PDFWorkflowManager
return tempSortDir; return tempSortDir;
} }
static void ConvertToJpeg(string sourceFileName, string destinationFileName, int compressionLevel, int dpi = 300) static void convertToJpeg(string sourceFileName, string destinationFileName, int compressionLevel, int dpi = 300)
{ {
try try
{ {
// Load the source image
using (Image sourceImage = Image.FromFile(sourceFileName)) using (Image sourceImage = Image.FromFile(sourceFileName))
{ {
// Calculate new dimensions based on DPI
float scaleFactor = dpi / sourceImage.HorizontalResolution;
int newWidth = (int)(sourceImage.Width * scaleFactor);
int newHeight = (int)(sourceImage.Height * scaleFactor);
using (var newImage = new Bitmap(newWidth, newHeight))
{
newImage.SetResolution(dpi, dpi);
// Draw the source image onto the new bitmap with the new dimensions
using (Graphics graphics = Graphics.FromImage(newImage))
{
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphics.DrawImage(sourceImage, 0, 0, newWidth, newHeight);
}
// Set encoding parameters for JPEG // Set encoding parameters for JPEG
EncoderParameters encoderParameters = new EncoderParameters(1); EncoderParameters encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, compressionLevel); encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, compressionLevel);
// Get the JPEG codec // Get the JPEG codec
ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg"); ImageCodecInfo jpegCodec = GetEncoderInfo(ImageFormat.Jpeg);
// Save the image in JPEG format with specified compression level // Save the image in JPEG format with specified compression level
sourceImage.Save(destinationFileName, jpegCodec, encoderParameters); newImage.Save(destinationFileName, jpegCodec, encoderParameters);
sourceImage.Dispose(); }
} }
} }
catch (Exception ex) catch (Exception ex)
@ -626,153 +649,20 @@ namespace PDFWorkflowManager
} }
} }
static ImageCodecInfo GetEncoderInfo(ImageFormat format)
static void ConvertTiffTo150DpiJpg(string inputTiffPath, string outputJpgPath)
{ {
using (var tiffImage = Image.FromFile(inputTiffPath)) foreach (ImageCodecInfo codec in ImageCodecInfo.GetImageDecoders())
{ {
var newWidth = (int)(tiffImage.Width * 150 / tiffImage.HorizontalResolution); if (codec.FormatID == format.Guid)
var newHeight = (int)(tiffImage.Height * 150 / tiffImage.VerticalResolution);
using (var newImage = new Bitmap(newWidth, newHeight))
{
newImage.SetResolution(150, 150);
using (var graphics = Graphics.FromImage(newImage))
{
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.DrawImage(tiffImage, 0, 0, newWidth, newHeight);
}
// Set JPEG compression level
var encoderParameters = new EncoderParameters(1);
var encoderParameter = new EncoderParameter(Encoder.Quality, 85L); // Set compression level here (0-100)
encoderParameters.Param[0] = encoderParameter;
// Save as JPEG with 150 DPI and specified compression level
var jpegCodecInfo = GetEncoderInfo(ImageFormat.Jpeg);
newImage.Save(outputJpgPath, jpegCodecInfo, encoderParameters);
}
}
}
static ImageCodecInfo GetEncoderInfo(string mimeType)
{
// Get image codecs for all image formats
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
// Find the correct image codec
foreach (ImageCodecInfo codec in codecs)
{
if (codec.MimeType == mimeType)
{ {
return codec; return codec;
} }
} }
// If no appropriate codec found, return null
return null; return null;
} }
private string prepConvertToTempOutdir(int sourceFileCount, string[] strFiles, string sourceDir) private async Task convertToPdf(string[] strFiles, string outputDir, string selectedLanguage)
{ {
string tempSortDir = Path.Combine(tempDir, "sort");
Directory.CreateDirectory(tempSortDir);
int downCount = sourceFileCount;
int upCount = 1;
if (radioSortMagazine.Checked == true)
{
for (int i = 0; i < sourceFileCount;)
{
ConvertToJpeg(strFiles[i], Path.Combine(tempSortDir, downCount.ToString().PadLeft(4, '0') + ".jpg"), 85);
i++;
downCount--;
ConvertToJpeg(strFiles[i], Path.Combine(tempSortDir, upCount.ToString().PadLeft(4, '0') + ".jpg"), 85);
i++;
upCount++;
ConvertToJpeg(strFiles[i], Path.Combine(tempSortDir, upCount.ToString().PadLeft(4, '0') + ".jpg"), 85);
i++;
upCount++;
ConvertToJpeg(strFiles[i], Path.Combine(tempSortDir, downCount.ToString().PadLeft(4, '0') + ".jpg"), 85);
i++;
downCount--;
}
// fixme why sleep?
Thread.Sleep(1000);
sourceDir = tempSortDir;
}
else if (radioSortFlatBed.Checked == true)
{
for (int i = 1; i < sourceFileCount;)
{
ConvertToJpeg(strFiles[i], Path.Combine(tempSortDir, upCount.ToString().PadLeft(4, '0') + ".jpg"), 85);
i++;
upCount++;
}
ConvertToJpeg(strFiles[0], Path.Combine(tempSortDir, upCount.ToString().PadLeft(4, '0') + ".jpg"), 85);
// fixme why sleep?
Thread.Sleep(1000);
}
else if (radioSortNormal.Checked == true)
{
for (int i = 0; i < sourceFileCount;)
{
ConvertToJpeg(strFiles[i], Path.Combine(tempSortDir, upCount.ToString().PadLeft(4, '0') + ".jpg"), 85);
i++;
upCount++;
}
}
return tempSortDir;
}
private async void btnConvertToPDF_Click(object sender, EventArgs e)
{
try
{
string[] strFiles = Directory.GetFiles(workOutDir, "*.tif");
int sourceFileCount = strFiles.Length;
string outputDir = Path.Combine(tempDir, "output");
Directory.CreateDirectory(outputDir);
string sourceDir = workOutDir;
var selectedLanguage = "eng";
if (checkLanguage.Checked == true)
{
var language = (dynamic)cmbLanguage.SelectedItem;
selectedLanguage = language.Value;
}
else
{
string[] langArray = txtLanguages.Text.Split(new string[] { "; " }, StringSplitOptions.RemoveEmptyEntries);
selectedLanguage = String.Join("+",
trainLanguage
.Where(kv => langArray
.Contains(kv.Key))
.Select(kv => kv.Value)
);
}
// TODO - check for magazine - finish this function
if (chkMagazines.Checked == true)
{
sourceDir = prepConvertToTempOutdir(sourceFileCount, strFiles, sourceDir);
// convert to jpg function
strExtension = "jpg";
}
else
{
sourceDir = prepCopyToTempOutdir(sourceFileCount, strFiles, sourceDir);
strExtension = "tif";
}
strFiles = Directory.GetFiles(sourceDir, "*." + strExtension);
ProcessStartInfo startInfo = new ProcessStartInfo(); ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.UseShellExecute = false; startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true; startInfo.RedirectStandardOutput = true;
@ -781,11 +671,11 @@ namespace PDFWorkflowManager
// TODO make this configurable // TODO make this configurable
startInfo.FileName = Properties.Settings.Default.TesserAct; startInfo.FileName = Properties.Settings.Default.TesserAct;
string outputFile = ""; string outputFile = "";
toolStripProgressBar1.Maximum = sourceFileCount; toolStripProgressBar1.Maximum = strFiles.Count();
toolStripProgressBar1.Value = 0; toolStripProgressBar1.Value = 0;
toolStripStatusLabel1.Text = "Converting files to pdf."; toolStripStatusLabel1.Text = "Converting files to pdf.";
await Task.Run(() => Task convertpdf = Task.Run(() =>
{ {
Parallel.ForEach(strFiles, inputFile => Parallel.ForEach(strFiles, inputFile =>
{ {
@ -809,13 +699,11 @@ namespace PDFWorkflowManager
}); });
}); });
Thread.Sleep(1000); await Task.WhenAll(convertpdf);
string[] inFiles = Directory.GetFiles(sourceDir, "*." + strExtension);
string[] outFiles = Directory.GetFiles(outputDir, "*.pdf");
txtPageCount.Text = inFiles.Length.ToString();
btnMakePDF.Enabled = true;
Thread.Sleep(1000);
// Parallel doesn't always return full result, we pick up the missing and process them again single threaded // Parallel doesn't always return full result, we pick up the missing and process them again single threaded
/*
if (Directory.GetFiles(sourceDir, "*." + strExtension).Length != outFiles.Length) if (Directory.GetFiles(sourceDir, "*." + strExtension).Length != outFiles.Length)
{ {
string[] arrayInFiles = new string[inFiles.Length]; string[] arrayInFiles = new string[inFiles.Length];
@ -847,6 +735,134 @@ namespace PDFWorkflowManager
MessageBox.Show("Not all files were converted to PDF"); MessageBox.Show("Not all files were converted to PDF");
} }
} }
*/
}
private async Task prepConvertToTempOutdir(string[] strFiles)
{
try
{
await semaphore.WaitAsync();
string tempJpg300Dir = Path.Combine(tempDir, "jpg300");
string tempJpg150Dir = Path.Combine(tempDir, "jpg150");
Directory.CreateDirectory(tempJpg300Dir);
Directory.CreateDirectory(tempJpg150Dir);
string outputFile = "";
int filecount = strFiles.Count() * 2;
toolStripProgressBar1.Maximum = filecount;
toolStripProgressBar1.Value = 0;
toolStripStatusLabel1.Text = "Converting files to jpg.";
List<Task> tasks = new List<Task>();
await Task.Run(() =>
{
Parallel.ForEach(strFiles, async inputFile =>
{
outputFile = Path.Combine(tempJpg300Dir, Path.GetFileNameWithoutExtension(inputFile) + ".jpg");
convertToJpeg(inputFile, outputFile, 85, 300);
//Interlocked.Increment(ref toolStripProgressBar1.Value);
//UpdateProgressBar();
});
});
await Task.Run(() =>
{
Parallel.ForEach(strFiles, async inputFile =>
{
outputFile = Path.Combine(tempJpg150Dir, Path.GetFileNameWithoutExtension(inputFile) + ".jpg");
convertToJpeg(inputFile, outputFile, 85, 150);
//Interlocked.Increment(ref toolStripProgressBar1.Value);
//UpdateProgressBar();
});
});
await Task.WhenAll(tasks);
}
finally
{
semaphore.Release(); // Release semaphore
}
}
private void UpdateProgressBar()
{
if (toolStripProgressBar1.Control.InvokeRequired)
{
toolStripProgressBar1.Control.Invoke((MethodInvoker)delegate
{
toolStripProgressBar1.Value++;
});
}
else
{
toolStripProgressBar1.Value++;
}
}
private async void btnConvertToPDF_Click(object sender, EventArgs e)
{
try
{
string[] strFiles = Directory.GetFiles(workOutDir, "*.tif");
int sourceFileCount = strFiles.Length;
string outputDir = Path.Combine(tempDir, "output");
Directory.CreateDirectory(outputDir);
string sourceDir = workOutDir;
var selectedLanguage = "eng";
if (checkLanguage.Checked == true)
{
var language = (dynamic)cmbLanguage.SelectedItem;
selectedLanguage = language.Value;
}
else
{
string[] langArray = txtLanguages.Text.Split(new string[] { "; " }, StringSplitOptions.RemoveEmptyEntries);
selectedLanguage = String.Join("+",
trainLanguage
.Where(kv => langArray
.Contains(kv.Key))
.Select(kv => kv.Value)
);
}
sourceDir = prepCopyToTempOutdir(sourceFileCount, strFiles);
strFiles = Directory.GetFiles(sourceDir, "*." + strExtension);
string jpg150dir = "";
if (chkMagazines.Checked == true)
{
await prepConvertToTempOutdir(strFiles);
sourceDir = Path.Combine(tempDir, "jpg300");
jpg150dir = Path.Combine(tempDir, "jpg150");
// convert to jpg function
strExtension = "jpg";
}
strFiles = Directory.GetFiles(sourceDir, "*." + strExtension);
await convertToPdf(strFiles, outputDir, selectedLanguage);
try
{
string[] strFiles150 = Directory.GetFiles(jpg150dir, "*." + strExtension);
if (strFiles.Count() == strFiles150.Count())
{
strFiles150 = Directory.GetFiles(jpg150dir, "*." + strExtension);
await convertToPdf(strFiles150, jpg150dir, selectedLanguage);
}
}
catch { }
string[] inFiles = Directory.GetFiles(sourceDir, "*." + strExtension);
string[] outFiles = Directory.GetFiles(outputDir, "*.pdf");
txtPageCount.Text = inFiles.Length.ToString();
btnMakePDF.Enabled = true;
btnMakePDF.Enabled = true; btnMakePDF.Enabled = true;
toolStripStatusLabel1.Text = "Converting files to pdf. Done!"; toolStripStatusLabel1.Text = "Converting files to pdf. Done!";
@ -884,6 +900,7 @@ namespace PDFWorkflowManager
toolStripProgressBar1.Value = 0; toolStripProgressBar1.Value = 0;
string outputDir = Path.Combine(tempDir, "output"); string outputDir = Path.Combine(tempDir, "output");
string tempFile = Path.Combine(tempDir, "_" + ".pdf"); string tempFile = Path.Combine(tempDir, "_" + ".pdf");
string tempFile150 = Path.Combine(tempDir, "_150" + ".pdf");
// PDF 1.5 -> 1.7 + Metadata (gswin64c) // PDF 1.5 -> 1.7 + Metadata (gswin64c)
if (!Directory.Exists(tempDir)) if (!Directory.Exists(tempDir))
@ -918,16 +935,29 @@ namespace PDFWorkflowManager
process.WaitForExit(); process.WaitForExit();
} }
if (Directory.Exists(Path.Combine(tempDir, "jpg150")))
{
string bannera5 = Path.Combine(strExeFilePath, bannerPageA5);
startInfo.FileName = Properties.Settings.Default.PDFtk;
startInfo.Arguments = "\"" + Path.Combine(Path.Combine(tempDir, "jpg150", "*.pdf")) + "\" \"" + bannera5 + "\" cat output " + "\"" + tempFile150 + "\"";
using (var process = Process.Start(startInfo))
{
process.WaitForExit();
}
}
// Create Thumbnail // Create Thumbnail
string[] outFiles = Directory.GetFiles(Path.Combine(tempDir, "sort"), "*." + strExtension); string[] outFiles = Directory.GetFiles(Path.Combine(tempDir, "sort"), "*.tif");
createThumbNail(outFiles[0]); createThumbNail(outFiles[0]);
textToOcrFile(outputDir); textToOcrFile(outputDir);
generatePDFMetadata(); generatePDFMetadata();
updatePDFMetaData(tempFile); updatePDFMetaData(tempFile);
if (File.Exists(tempFile150))
{
updatePDFMetaData(tempFile150, "150");
}
toolStripStatusLabel1.Text = "Creating final pdf. Done."; toolStripStatusLabel1.Text = "Creating final pdf. Done.";
toolStripProgressBar1.Value = 1; toolStripProgressBar1.Value = 1;
@ -940,8 +970,6 @@ namespace PDFWorkflowManager
File.WriteAllText(Path.Combine(txtProjectDir.Text, txtFileName.Text + ".pdf.md5"), md5string); File.WriteAllText(Path.Combine(txtProjectDir.Text, txtFileName.Text + ".pdf.md5"), md5string);
File.WriteAllText(Path.Combine(txtProjectDir.Text, txtFileName.Text + ".pdf.sha1"), sha1string); File.WriteAllText(Path.Combine(txtProjectDir.Text, txtFileName.Text + ".pdf.sha1"), sha1string);
} }
catch catch
{ {
@ -951,14 +979,20 @@ namespace PDFWorkflowManager
File.Delete(Path.Combine(tempDir, "pdfmetadata.txt")); File.Delete(Path.Combine(tempDir, "pdfmetadata.txt"));
} }
private void updatePDFMetaData(string tempFile) private void updatePDFMetaData(string tempFile, string modifier = "")
{ {
string filename = txtFileName.Text;
if (modifier != "")
{
filename = txtFileName.Text.Replace(cmbResolution.Text, modifier);
}
ProcessStartInfo updatePDF = new ProcessStartInfo(); ProcessStartInfo updatePDF = new ProcessStartInfo();
updatePDF.UseShellExecute = false; updatePDF.UseShellExecute = false;
updatePDF.RedirectStandardOutput = true; updatePDF.RedirectStandardOutput = true;
updatePDF.CreateNoWindow = true; updatePDF.CreateNoWindow = true;
updatePDF.FileName = Properties.Settings.Default.GhostScript; updatePDF.FileName = Properties.Settings.Default.GhostScript;
updatePDF.Arguments = "-dBATCH -dNOPAUSE -dAutoRotatePages=/None -sDEVICE=pdfwrite -sOutputFile=\"" + Path.Combine(txtProjectDir.Text, txtFileName.Text + ".pdf") + "\" \"" + tempFile + "\" \"" + Path.Combine(tempDir, "pdfmetadata.txt") + "\""; updatePDF.Arguments = "-dBATCH -dNOPAUSE -dAutoRotatePages=/None -sDEVICE=pdfwrite -sOutputFile=\"" + Path.Combine(txtProjectDir.Text, filename + ".pdf") + "\" \"" + tempFile + "\" \"" + Path.Combine(tempDir, "pdfmetadata.txt") + "\"";
//updatePDF.Arguments = "-dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=\"" + Path.Combine(txtProjectDir.Text, txtFileName.Text + ".pdf") + "\" \"" + tempFile + "\" -c\" " + generatePDFMetadata() + "\""; //updatePDF.Arguments = "-dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=\"" + Path.Combine(txtProjectDir.Text, txtFileName.Text + ".pdf") + "\" \"" + tempFile + "\" -c\" " + generatePDFMetadata() + "\"";
using (var process = Process.Start(updatePDF)) using (var process = Process.Start(updatePDF))
{ {
@ -1134,7 +1168,7 @@ namespace PDFWorkflowManager
private void radioSortNormal_CheckedChanged(object sender, EventArgs e) private void radioSortNormal_CheckedChanged(object sender, EventArgs e)
{ {
sortNormal = true; //sortNormal = true;
string[] strFiles = Directory.GetFiles(workOutDir, "*.tif"); string[] strFiles = Directory.GetFiles(workOutDir, "*.tif");
if (File.Exists(strFiles[0])) if (File.Exists(strFiles[0]))
@ -1145,7 +1179,7 @@ namespace PDFWorkflowManager
private void radioSortMagazine_CheckedChanged(object sender, EventArgs e) private void radioSortMagazine_CheckedChanged(object sender, EventArgs e)
{ {
sortNormal = false; //sortNormal = false;
string[] strFiles = Directory.GetFiles(workOutDir, "*.tif"); string[] strFiles = Directory.GetFiles(workOutDir, "*.tif");
@ -1157,7 +1191,7 @@ namespace PDFWorkflowManager
private void radioSortFlatBed_CheckedChanged(object sender, EventArgs e) private void radioSortFlatBed_CheckedChanged(object sender, EventArgs e)
{ {
sortNormal = false; //sortNormal = false;
string[] strFiles = Directory.GetFiles(workOutDir, "*.tif"); string[] strFiles = Directory.GetFiles(workOutDir, "*.tif");
@ -1260,7 +1294,7 @@ namespace PDFWorkflowManager
private void aboutToolStripMenuItem_Click(object sender, EventArgs e) private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{ {
MessageBox.Show("PDF Workflow Manager v0.9.1 \r\n\r\nCopyright (c) 2023-2024 https://retro-commodore.eu", "Version", MessageBoxButtons.OK, MessageBoxIcon.Information); MessageBox.Show("PDF Workflow Manager v0.9.2 \r\n\r\nCopyright (c) 2023-2024 https://retro-commodore.eu", "Version", MessageBoxButtons.OK, MessageBoxIcon.Information);
} }
private void button1_Click(object sender, EventArgs e) private void button1_Click(object sender, EventArgs e)