Commit 83fb322a authored by AP matsuo koji's avatar AP matsuo koji 😲

Merge :cli

parents d205d7b5 793957bb

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.960
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSRender", "CSRender\CSRender.csproj", "{FD99EFAA-2479-4E3B-BD1A-5B785288E3B3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FD99EFAA-2479-4E3B-BD1A-5B785288E3B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD99EFAA-2479-4E3B-BD1A-5B785288E3B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD99EFAA-2479-4E3B-BD1A-5B785288E3B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD99EFAA-2479-4E3B-BD1A-5B785288E3B3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8B1418EB-CA5D-4F34-9026-020B0B30AE79}
EndGlobalSection
EndGlobal
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
</startup>
</configuration>
{
"Head": {
"HashBaseName": "72.0_Crop_JPG_91",
"HashFilePath": "C:\\Users\\cozy\\Documents\\GitDoc\\Scripts\\WinRT\\CSRender\\CSRender\\BasehashPDF\\RenderHash_72.0_Crop_JPG_91.json",
"Dpi": "72.0",
"Box": "Crop",
"ImType": "JPG",
"JQ": "91"
},
"Files": [
{
"Key": "BaseHash.pdf",
"Value": {
"UpdateTime": "\/Date(1585355435085)\/",
"UpdateTimeStr": "2020\/03\/28 9:30:35",
"PageHashCode": [
"B7D69FA446C6C64F985AA3446C6D5C6FD0A70C4C2F1E9AB55AB10993A5A67313"
]
}
}
]
}
\ No newline at end of file
using System;
using System.IO;
using System.Collections.Generic; // List<>
using System.Linq; // for Enumration
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using System.Security.Cryptography; // for Hash
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Collections.ObjectModel;
using System.Runtime.InteropServices; // for DLL import
// PDFiumの追加
using PdfiumViewer;
// no need
//using System.Windows; // No need
//using System.Windows.Media.Imaging; // no need
// for Stream conv.
//using System.Runtime.InteropServices.WindowsRuntime;
//using Windows.Storage.Streams;
//using System.Reflection; // for Assembly.
using static CSRender.RenderPDF;
namespace CSRender {
#pragma warning disable IDE1006 // 小文字のメソッドを許可
static public class Check
{
//https://gist.github.com/retorillo/4e0c4a3cf4c7096e05ac
static public bool bDump = false;
static public bool bThDump = false;
[DllImport("user32.dll")]
extern static bool SetProcessDPIAware();
[DllImport("user32.dll")]
extern static IntPtr GetWindowDC(IntPtr hwnd);
[DllImport("gdi32.dll")]
extern static int GetDeviceCaps(IntPtr hdc, int index);
[DllImport("user32.dll")]
extern static int ReleaseDC(IntPtr hwnd, IntPtr hdc);
public static int GetDPI() {
// モニタの解像度の取得
//return 96;
SetProcessDPIAware();// もしくはdpiAwareをマニフェストで設定すればよい。
var dc = GetWindowDC(IntPtr.Zero);
var dpi = GetDeviceCaps(dc, 88/*LOGPIXELSX*/);
ReleaseDC(IntPtr.Zero, dc);
return dpi;// 96;// dpi;
}
}
public static class RenderPDF
{
/// <summary>
/// Rendering Condition
/// </summary>
[DataContract]
public class RenderConditionParams
{
[DataMember(Order = 0)]
public double Dpi = 72.0;
[DataMember(Order = 1)]
public string BoxType = "Crop";
[DataMember(Order = 2)]
public string ImageType = "JPEG";
[DataMember(Order = 3)]
public int JpegQ = 91;
// Method non
}
/*
* Console Echo関係
*/
public static bool bEcho = false;
public static void setEcho(bool b) {bEcho = b;}
public static void echo(params object[] args) {
if (!bEcho) return;
var s = "";
foreach (object a in args) {
s += a.ToString();
}
Console.WriteLine(s);
}
/// <summary>
/// PDFのレンダリング
/// </summary>
/// <param name="pdfPath"></param>
/// <param name="inDir"></param>
/// <param name="pm">レンダリングの条件</param>
/// <param name="inPageRange"></param>
/// <param name="inMode"></param>
/// <param name="bSaveImage"></param>
/// <param name="bHash">未使用,常にtrueで使用</param>
/// <param name="inHashData"></param>
/// <returns></returns>
public static int RenderPdfDoc(
string pdfPath,
string inDir = "",
RenderConditionParams pm = null,
string inPageRange = "1-*",
string inMode = "pageBitMap",
bool bSaveImage = true, //ハッシュ値のみ計算するときにfalseにする
bool bHash = false,
UtHash.HashData inHashData = null,
bool bPDFium = false,
int nPageThreadNum = 4
) {
if (pm == null) {
pm = new RenderConditionParams();
}
var otDir = inDir;
var otBaseName = Path.GetFileName(pdfPath);//*.pdf
var otExtention = pm.ImageType.ToLower();
if (bSaveImage) {
if ( otDir == "" ) {
// 出力ディレクトリが空→元PDFの同一フォルダにIMGフォルダを作成する
otDir = Path.Combine(Directory.GetParent(pdfPath).FullName, "IMG");
}
if (!Directory.Exists(otDir))
Directory.CreateDirectory(otDir);
echo("ouptput dir=",otDir);
}
// Open pdf by PDFium.
int pageCount = 0;
using(var docG = PdfiumViewer.PdfDocument.Load(pdfPath)){
pageCount = docG.PageCount;
inMode = "pageBitMap";
var taskList = new List<Task<int>>();
uint[] rNo = makePageRange(inPageRange, (uint)pageCount);
if (inHashData != null) {
echo("Create Hash");
// ハッシュ対象の最大ページ数の設定必須。
inHashData.SetFile(pdfPath, (int)pageCount);
}
echo($"Page.ParallelOptions:Thread={nPageThreadNum},Pages={rNo.Length}");
/////並行処理するスレッド数を指定(2-4ぐらいが穏便な数値)
ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = nPageThreadNum };
Parallel.ForEach(rNo, options, i => {
//Console.WriteLine($"*****{i}*****/{rNo.Length}");
var hashValue = "";
var ret = RenderPage(
docG: docG,
index: (int)i-1,
otPath: Path.Combine(otDir, $"{otBaseName}.{i}.{otExtention}"),
pm: pm,
bSaveImage: bSaveImage, // ファイル保存
bHash: bHash,
otHashCode: ref hashValue
);
if (inHashData != null) {
lock (inHashData) {
inHashData.AddHashCode(pdfPath, (int)i, hashValue);
}
}
});
echo("End Para");
docG.Dispose();
}
return pageCount;// ページ数を返却します
}
/// <summary>
/// imageをRGB3チェンネルbitmapにRenderingする
/// </summary>
/// <returns></returns>
public static System.Drawing.Bitmap RenderRgbBitMap(
PdfiumViewer.PdfDocument docG,
int index,
double dpiX,
double dpiY,
PdfRenderFlags flg
){
var bitmap = docG.Render(index, (float)dpiX, (float)dpiY, flg) as System.Drawing.Bitmap;
if (bitmap.PixelFormat == System.Drawing.Imaging.PixelFormat.Format24bppRgb)
return bitmap;
//
var cloneRect = new System.Drawing.RectangleF(0, 0, bitmap.Size.Width, bitmap.Size.Height);
var format = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
var clonebitmap = bitmap.Clone(cloneRect, format);
//
//bitmap.Dispose();
return clonebitmap;
/*
保存時にBitmapのクローンを作成し、その際のBitmapの形式に24bitRGB(PixelFormat.Format24bppRgb)を
指定し3版RGBTiffを出力します。
System.Drawing.Imaging.PixelFormat format = PixelFormat.Format24bppRgb;
clonebitmap = bitmap1.Clone(cloneRect, format);
ref:
https://maywork.net/computer/csharp_convert_to_format32bppargb/
https://www.webdevqa.jp.net/ja/c%23/c%EF%BC%83%E3%81%A7%E3%81%AE%E3%83%93%E3%83%83%E3%83%88%E3%83%9E%E3%83%83%E3%83%97pixelformats%E3%81%AE%E5%A4%89%E6%8F%9B/968763414/
https://gist.github.com/nissuk/888601/ee0943dd0d35dc9c6b47358b9e1a89af8cc9898b
https://stackoverflow.com/questions/28448474/render-pdf-page-to-bitmap-using-pdfium
https://qiita.com/Nuits/items/4a2fbc0f4e8583bd5531
PixelFormat dump https://maywork.net/computer/csharp_convert_to_format32bppargb/
*/
}
/// <summary>
/// pdfのページを画像に出力する
/// </summary>
/// <param name="doc">PdfDocument</param>
/// <param name="nPage">ページ番号</param>
/// <param name="otPath">出力ファイル名</param>
/// <returns>正常:0 </returns>
public static int RenderPage(
PdfiumViewer.PdfDocument docG,
int index,
string otPath,
ref string otHashCode,
// Optional:
RenderConditionParams pm = null,
bool bSaveImage = true,// ファイル保存有無。ハッシュ値計算のみのときにfalseにする
bool bHash = false
){
var bDump = Check.bDump;
var bThDump = Check.bThDump;
if ( pm == null )
pm = new RenderConditionParams();
using (var memStrm = new MemoryStream()) {
PdfRenderFlags flg = (PdfRenderFlags.ForPrinting | PdfRenderFlags.CorrectFromDpi);
using(var img = RenderRgbBitMap(docG, index, (float)pm.Dpi, (float)pm.Dpi, flg) ){
img.Save(memStrm, System.Drawing.Imaging.ImageFormat.Bmp);
/*
// ImageFormatJPEGの時
dpi = 350,TIFF
2691.777 = 44分51.777秒
10335ファイルで20G
ーー
ImageFormat.Bmpに変更
result=0,time=2850.955[sec]
10335ファイルで12.2G
ーー
pagePara=2
para=4
ImageFormat.Bmp
result=0,time=2824.644[sec]
10335ファイルで12.2G
ーー
pagePara=2
para=8
ImageFormat.Bmp
result=0,time=2828.631[sec] => 47分
10335ファイルで12.2G
*/
// [注意] PDFuim用Flush()必要しないとだめです
memStrm.Flush();
img.Dispose();
}
var bmp = new System.Drawing.Bitmap(memStrm);
if (bDump) {
echo($"bmp=w:{bmp.Size.Width},h:{bmp.Size.Height}");
}
//Console.WriteLine($"OrgReso({bmp.HorizontalResolution},{bmp.VerticalResolution})");
if (bHash) {
var h = GetHashValue(memStrm);
//Console.WriteLine($"HashString:{h}");
otHashCode = h;
}
var th = Thread.CurrentThread.ManagedThreadId;
if (!bSaveImage) { //ファイル保存しない.ハッシュ計算のみ
if (bThDump) {
echo($"ot[th{th},{(index + 1)}/{docG.PageCount}]=,{Path.GetFileName(otPath)},hash:{otHashCode}");
}
return 0;
}
// image encodeを作成
var imEnc = new UtImage.Enc(pm.ImageType) { JpegQuality = pm.JpegQ };// Init membrers.
bmp.SetResolution((float)pm.Dpi, (float)pm.Dpi); // imageクラスでもPropertyTagX(Y)Resolutionで設定できそう
if (bThDump) {
echo($"ot[th{th},{(index + 1)}/{docG.PageCount}]={Path.GetFileName(otPath)}({Directory.GetParent(otPath)})");
}
//
imEnc.SaveImage(bmp, otPath);
//
bmp.Dispose();
//memStrm.Seek(0);
memStrm.Dispose();
}
return 0;//success
}
// Sync version( 比較モード(/FC ) **************************************************************************************
/// <summary>
/// レンダリング(比較モード)
/// </summary>
/// <param name="pdfPath"></param>
/// <param name="refPdfPath"></param>
/// <param name="inDir"></param>
/// <param name="pm">レンダリング条件</param>
/// <param name="inPageRange"></param>
/// <param name="inMode"></param>
/// <param name="bHash">未使用常にtrueで利用する</param>
/// <param name="inHashDataTgt"></param>
/// <param name="inHashDataRef"></param>
/// <returns>一致した場合は0、不一致の場合は!0を返却する</returns>
public static int RenderPdfDocCompare(
string pdfPath,
string refPdfPath,
string resultDataPath,
string inDir = "",
RenderConditionParams pm = null,
string inPageRange = "1-*",
string inMode = "pageBitMap",
bool bHash = false,
UtHash.HashData inHashDataTgt = null,
UtHash.HashData inHashDataRef = null,
bool bPDFium = false,
int nPageThreadNum = 4,
bool bVerify = false
// 比較結果を返す ページ番号とメッセージ
) {
var bDump = Check.bDump;
var bThDump = Check.bThDump;
if(bDump)
echo("RenderPdfDocCompare & diff Image! & non Para");
if (pm == null)
pm = new RenderConditionParams();
var otDir = inDir;
var otBaseName = Path.GetFileName(pdfPath);//xxx.pdf
var otExtention = pm.ImageType.ToLower();
if (otDir == "") {
Console.WriteLine("Error:No output dir");
return -1;// error
}
if (!Directory.Exists(otDir))
Directory.CreateDirectory(otDir);
// PDFファイルを読み込む by PDFium.
var docG = PdfiumViewer.PdfDocument.Load(pdfPath);
var docGRef = PdfiumViewer.PdfDocument.Load(refPdfPath);
var pageCount = docG.PageCount;
uint[] rNo = makePageRange(inPageRange, (uint)pageCount);
int nRetAll = 0;// トータルの不一致ページ数
// ハッシュ情報の確認
/*
- 双方のハッシュ値が存在するか確認
- tgtののみなら、refのrender
- refのみなら、tgtのみrender
- とう感じ
*/
UtHash.HashFile tgtHf=null;
if (inHashDataTgt!=null) {
var f = Path.GetFileName(pdfPath);
if (inHashDataTgt.Files.ContainsKey(f)) {
tgtHf = inHashDataTgt.Files[f];
}
}
UtHash.HashFile refHf = null;
if (inHashDataRef != null) {
var f = Path.GetFileName(refPdfPath);
if ( inHashDataRef.Files.ContainsKey(f) ) {
refHf = inHashDataRef.Files[f];
}
}
Console.WriteLine($@"UsingHashFile:tgt({(tgtHf==null?0:1)}),ref({(refHf == null ? 0 : 1)})");
// tgtHf,refHfを構築完了
var fcResultMsg = new SortedDictionary<int,string>();// 比較結果を返す ページ番号とメッセージ
/////並行処理するスレッド数を指定(2-4ぐらいが穏便な数値)
ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = 4 };
Parallel.ForEach(rNo, options, i => {
MemoryStream tgtStrm = null, refStrm = null;
string tgtHash = "", refHash = "";
// ターゲット レンダラ定義
MemoryStream RendPageTGT() {
var strm = RenderPageStream(docG:docG,index:(int)i-1, pm:pm);
return strm;
}
// リファレンス レンダラ定義
MemoryStream RendPageREF() {
var strm = RenderPageStream(docG:docGRef, index:(int)i-1, pm:pm);
return strm;
}
// ターゲット処理
if (tgtHf == null) {
tgtStrm = RendPageTGT();// Render
tgtHash = GetHashValue(tgtStrm);
} else {
lock (inHashDataTgt) {
tgtHash = tgtHf.GetHashValue((int)(i - 1));
}
}
// リファレンス処理
if (refHf == null) {
refStrm = RendPageREF();// Render
refHash = GetHashValue(refStrm);
} else {
lock (inHashDataRef) {
refHash = refHf.GetHashValue((int)(i - 1));
}
}
// compare stream;
// int nRet = 1;//異なる(diff).
var dateStr = DateTime.Now.ToString();
//Console.WriteLine($@"tgt={i}:{tgtHash}");
//Console.WriteLine($@"ref={i}:{refHash}");
//bool bVerify=true;
if (bVerify){
String p=null;
p=Path.Combine( otDir,"TGT");
if (!Directory.Exists(p)) Directory.CreateDirectory(p);
p=Path.Combine( otDir,"REF");
if (!Directory.Exists(p)) Directory.CreateDirectory(p);
}
if (tgtHash != refHash) {
// no match
// nRet = 1;
nRetAll++;// = nRet;//全体の不一致設定
echo($"{i}:NotMatch:{i},tgt[{tgtHash}],ref[{refHash}]");
//2020年3月2日 15:23:55:[@Difference]:<fullpath>.diff.jpg
lock (fcResultMsg) {
fcResultMsg.Add((int)i, $@"{dateStr}:[@Difference]:{Path.GetFileName(pdfPath)}.{i}");
}
echo("***** save diff image");
// diffのjpegを書き出してみる(tgt)
if (tgtStrm == null)
tgtStrm = RendPageTGT();
var otPath = bVerify ?
Path.Combine(otDir, "TGT",$"{otBaseName}.{i}.{otExtention}")
:
Path.Combine(otDir, $"{otBaseName}.{i}.tgt.{otExtention}");
using(var bmp = new System.Drawing.Bitmap(tgtStrm)){
var imEnc = new UtImage.Enc(pm.ImageType) { JpegQuality = pm.JpegQ };// Init membrers.
bmp.SetResolution((float)pm.Dpi, (float)pm.Dpi);
imEnc.SaveImage(bmp, otPath);
bmp.Dispose();
}
// diffのjpegを書き出してみる(ref)
if (refStrm == null)
refStrm = RendPageREF();
otPath = bVerify ?
Path.Combine(otDir, "REF",$"{otBaseName}.{i}.{otExtention}")
:
Path.Combine(otDir, $"{otBaseName}.{i}.ref.{otExtention}");
using(var bmp = new System.Drawing.Bitmap(refStrm)){
var imEnc = new UtImage.Enc(pm.ImageType) { JpegQuality = pm.JpegQ };// Init membrers.
bmp.SetResolution((float)pm.Dpi, (float)pm.Dpi);
imEnc.SaveImage(bmp, otPath);
bmp.Dispose();
}
} else {
// match
//nRet = 0;
lock (fcResultMsg) {
fcResultMsg.Add((int)i, $@"{dateStr}:[OK]:{Path.GetFileName(pdfPath)}.{i}");
// Ex 2019年12月18日 19:31:38:[OK]:fname.pdf.1.png
}
}
// dispose:
if (refStrm != null) refStrm.Dispose();
if (tgtStrm != null) tgtStrm.Dispose();
});
if ( docG != null)
docG.Dispose();
if (docGRef != null)
docGRef.Dispose();
// まとめて表示
foreach ( var v in fcResultMsg){
Console.WriteLine("@CMP@"+v.Value);
}
if (resultDataPath != "") {
// まとめて書き出し
var resCont =($"{pdfPath}\n");
foreach (var v in fcResultMsg) {
resCont += ("@CMP@" + v.Value) + "\n";
}
File.AppendAllText(resultDataPath, resCont);
}
return nRetAll;// success. 不一致数を返す
}
/// <summary>
/// 比較モード
/// </summary>
/// <param name="docG">ドキュメントハンドル</param>
/// <param name="index">ページ番号(0-)</param>
/// <returns>正常:0 </returns>
public static MemoryStream RenderPageStream(
PdfiumViewer.PdfDocument docG,
int index,
// Optional:
RenderConditionParams pm = null
) {
var memStrm = new MemoryStream();
var bDump = Check.bDump;
var bThDump = Check.bThDump;
if (pm == null)
pm = new RenderConditionParams();
PdfRenderFlags flg = (PdfRenderFlags.ForPrinting | PdfRenderFlags.CorrectFromDpi);
System.Drawing.Image img =RenderRgbBitMap(docG, index, (float)pm.Dpi, (float)pm.Dpi, flg);
img.Save(memStrm, System.Drawing.Imaging.ImageFormat.Bmp);
//img.Save(memStrm, System.Drawing.Imaging.ImageFormat.Jpeg);
// [注意] PDFuim用にFlush()必要
memStrm.Flush();
img.Dispose();
return memStrm;
}
/// <summary>
/// ページ1から始まるページ範囲の配列を返す
/// </summary>
/// <param name="pageRange"></param>
/// <param name="maxPage"></param>
/// <returns></returns>
private static uint[] makePageRange(string pageRange = "1", uint endPage = 100) {
var range = new SortedSet<uint>();
var vec = pageRange.Split(',');//カンマで分割
var reRange = new Regex($@"([\d]+)[\s]*\-[\s]*([\d]*|\*)");// n-m or n- or n-*
var reOne = new Regex($@"([\d]+)"); // n
bool isRange(uint x) => (0 < x && x <= endPage); // 範囲チェック
void swap<T>(ref T a, ref T b) { T tmp = a; a = b; b = tmp; }
foreach (var s in vec) {
//範囲指定
var m = reRange.Match(s);
if (m.Success) {
uint st = uint.Parse(m.Groups[1].Value);
uint en = 0;
if (!isRange(st))
continue;//開始値が範囲外で無効
uint.TryParse(m.Groups[2].Value, out en);
if (!isRange(en))
en = endPage;// 最終値が無効なため最終ページ
if (st > en) swap(ref st, ref en);
// 範囲登録
foreach (var g in Enumerable.Range((int)st, (int)(en - st + 1)))
range.Add((uint)g);
continue;
}
//ページ指定
m = reOne.Match(s);
if (m.Success) {
var n = uint.Parse(m.Groups[1].Value);
if (isRange(n))
range.Add(n);
}
}
return range.ToArray<uint>();
}
public static string GetHashValue(MemoryStream strm) {
var alg = new SHA256CryptoServiceProvider();
strm.Seek(0, SeekOrigin.Begin);
var bin = alg.ComputeHash(strm);
alg.Clear();
// バイト配列をUTF8エンコードで文字列化
var hashedText = new StringBuilder();
foreach (var b in bin) {
hashedText.AppendFormat("{0:X2}", b);
}
return hashedText.ToString();
}
}
/// <summary>
/// ファイルのハッシュ値のIO
/// </summary>
namespace UtHash
// https://qiita.com/Akasaki/items/dee137b24aea4b7e2bcb
// http://mokake.hatenablog.com/entry/2017/09/28/234433
// https://lifetime-engineer.com/csharp-create-json-indent/
// DataMemberでOrderを指定することで順序を確定。
// JsonReaderWriterFactory.CreateJsonWriterでindent=trueにすることでjsonの可視性向上
{
[DataContract]
public class HashHead
{
public bool Dirty = false; // 書き換えられたらTrue 保存対象外
[DataMember(Order = 0)]
public string HashBaseName; // 保存時にベース名を設定する
[DataMember(Order=1)]
public string HashFilePath;
[DataMember(Order=2)]
public string Dpi;
[DataMember(Order=3)]
public string Box;
[DataMember(Order=4)]
public string ImType;
[DataMember(Order=5)]
public string JQ;
// メソッド
public HashHead() {
SetRenderInfo("0", "Bx", "IMx", "xx");
}
public HashHead SetRenderInfo(string dpi, string box, string imType, string jq) {
Dpi = dpi; Box = box; ImType = imType; JQ = jq;
return this;
}
public string GetRenderInfoStr() { return $@"{Dpi}_{Box}_{ImType}_{JQ}"; }
}
[DataContract]
public class HashFile {
[DataMember(Order=0)]
public DateTime UpdateTime; // ファイルの更新日
[DataMember(Order=1)]
public string UpdateTimeStr; // ファイルの更新日(Json目視用)
[DataMember(Order=2)]
public List<string> PageHashCode = new List<string>(); // ページ毎のハッシュ値の配列
// メソッド
public string GetHashValue(int i) {
// 範囲チェック
if ( !(0 <= i && i < PageHashCode.Count) ){
return "";
}
return PageHashCode[i];
}
}
[DataContract]
public class HashData {
[DataMember(Order=0)]
public HashHead Head = new HashHead();
[DataMember(Order=1)]
public SortedDictionary<string, HashFile> Files = new SortedDictionary<string, HashFile>();
// temp value
string loadedPath;
// メソッド
static public string GetHashFileName(string baseName, string dpi, string box, string imType, string jq) {
var h = new HashHead();
var f = baseName + "_" + h.SetRenderInfo(dpi, box, imType, jq).GetRenderInfoStr() + ".json";
return f;
}
static public HashData load(string pdfPath/*or Dir*/, string baseName, string dpi, string box, string imType, string jq, ref string otPath) {
var hashPath = "";
if (Path.GetExtension(pdfPath).ToLower() == ".pdf") {
var paPath = Directory.GetParent(Path.GetFullPath(pdfPath)).ToString();
var hashFName = GetHashFileName(baseName, dpi, box, imType, jq);
hashPath = Path.Combine(paPath, hashFName);
} else if (File.GetAttributes(pdfPath).HasFlag(FileAttributes.Directory)) {
var hashFName = GetHashFileName(baseName, dpi, box, imType, jq);
hashPath = Path.Combine(pdfPath, hashFName);
}
//Console.WriteLine($@"hashPath={hashPath}");
if (otPath != null) {
otPath = hashPath;
}
var hd = HashData.load(hashPath); //ファイルの存在はこっちに任す
return hd;
}
static public HashData load(string hashPath) {
if (!File.Exists(hashPath)) {
echo("not find load hash data file");
return null;
}
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HashData));
using (var rd = new FileStream(hashPath, FileMode.Open,FileAccess.Read,FileShare.ReadWrite)) {
var a = (HashData)serializer.ReadObject(rd);
a.Head.Dirty = false;// clear
a.loadedPath=hashPath;
return a;
}
}
static public HashData loadFromString(string s) {
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HashData));
using (var rd = new MemoryStream( Encoding.UTF8.GetBytes(s) )) {
var a = (HashData)serializer.ReadObject(rd);
a.Head.Dirty = false;// clear
return a;
}
}
public override string ToString() {
//文字列に書き出す
using (var m = new MemoryStream())
using (var writer = JsonReaderWriterFactory.CreateJsonWriter(m, Encoding.UTF8, true, true, " ")) {
var serializer = new DataContractJsonSerializer(typeof(HashData));
serializer.WriteObject(writer, this);
var x= Encoding.UTF8.GetString(m.ToArray());// 文字列に変換
return x;
}
}
public bool save(string path) {
// JSONに変換するデータを作る。
// 再保存の抑制
//this.Head.Dirtyがfalseなら更新されていないことになる。
//またかつ保存パスが同じ this.Head.HashFilePath = path;
echo($@"HashData.save:{path}");
this.Head.HashFilePath = Path.GetFullPath(path);
this.Head.HashBaseName = this.Head.GetRenderInfoStr();
try {
using (var fs = new FileStream(path, FileMode.Create))
using (var writer = JsonReaderWriterFactory.CreateJsonWriter(fs, Encoding.UTF8, true, true, " ")) {
var serializer = new DataContractJsonSerializer(typeof(HashData));
serializer.WriteObject(writer, this);
return true;
}
} catch (Exception e) {
Console.WriteLine($@"error Save json anything error:{e}");
return false;
}
}
public bool SetFile(string pathPDF, int pageNum) {
var fi = new FileInfo(pathPDF);
var fName = fi.Name;
HashFile hf;
if (!Files.ContainsKey(fName)) {
this.Head.Dirty = true;// 変更あり
hf = new HashFile() {
UpdateTime = fi.LastWriteTimeUtc,
UpdateTimeStr= fi.LastWriteTime.ToString(),
PageHashCode = new List<string>(pageNum)
};
// Console.WriteLine($@"update={hf.UpdateTime}");
for (var i = 0; i < pageNum; i++) {
hf.PageHashCode.Add("");
}
Files.Add(fName,hf);
} else {
// 既に存在、pageNumがかわらないことだけチェック
var pageNumOrg = Files[fName].PageHashCode.Count;
if (Files[fName].UpdateTime.ToString() != fi.LastWriteTimeUtc.ToString()) {
// 日付が一致しなければ更新(ToStringで比較しないとだめです
this.Head.Dirty = true;// 変更あり
Files[fName].UpdateTime = fi.LastWriteTimeUtc;
Files[fName].UpdateTimeStr = fi.LastWriteTime.ToString();
Files[fName].PageHashCode = new List<string>(pageNum);
for (var i = 0; i < pageNum; i++) {
Files[fName].PageHashCode.Add("");
}
}
// ありえないけど、同一日付でページ数が異なる
if (pageNumOrg != pageNum) {
Console.WriteLine($@"Mismatch pageNum:setP:{pageNum},DbP:{Files[fName].PageHashCode.Count}");
this.Head.Dirty = true;// 変更あり
return false; // Page数が一致しない
}
}
return true;
}
public bool AddHashCode(string pathPDF, int pageNo/*1開始*/, string hashCode) {
//Console.WriteLine("call addHashCode:" + pathPDF + ":" + pageNo);
var fi = new FileInfo(pathPDF);
var fName = fi.Name;
var n = pageNo - 1;//0始まり
if (!Files.ContainsKey(fName)) {
this.Head.Dirty = true;// 変更あり
return false;
}
if (Files[fName].PageHashCode[n] != hashCode) {
this.Head.Dirty = true;// 変更あり
Files[fName].PageHashCode[n] = hashCode;
}
return true;
}
public string GetHashCode(string pathPDF, int pageNo/*1開始*/) {
var fi = new FileInfo(pathPDF);
var fName = fi.Name;
var n = pageNo - 1;//0始まり
if (!Files.ContainsKey(fName)) {
return "";
}
var v = Files[fName].PageHashCode;
return (n < v.Count) ? v[n] : "";
}
public bool IsValidHashFile(string[] fLst){
// ハッシュファイルとPDFファイルの整合性確認。更新日付のみ確認。正常:true、異常:false
//
if (fLst.Count() != Files.Count )
return false; // pdfファイル数の不一致
foreach (var f in Files) {
var fPath=Path.Combine( Path.GetDirectoryName(loadedPath) ,f.Key);
var fi = new FileInfo(fPath);
// Console.WriteLine(fPath+": "+f.Value.UpdateTimeStr);
// Console.WriteLine(fPath+"->"+fi.LastWriteTime.ToString());
if ( f.Value.UpdateTimeStr != fi.LastWriteTime.ToString() )
return false; // 1つでも異なっていたらすべてのファイルを異常とする
}
return true;//正常
}
}
}
namespace UtImage // Image保存のユーティリティー
{
// ref:https://water2litter.net/rum/post/cs_pdf_wpf/
//using EncType = System.Drawing.Imaging.Encoder;// 別名
//using EncParamType = System.Drawing.Imaging.EncoderParameter;//別名
/// <summary>
/// BitMapのSaveに使うImage Encodeパラメータの設定値の生成と 画像保存
/// var enc = new UtImage.Enc("jpeg");
/// //enc.SetImageType("PNG"); // 後で変更できる
/// //enc.JJpegQuality = 100; JpegのQuarty変更
/// enc.SaveImage(BitMap,path);
/// // enc.SaveImage(BitMap,path,"PNG");
/// </summary>
///
public class Enc
{
// SEE:https://dobon.net/vb/dotnet/graphics/encoderparameters.html
public Enc(string imageType = "jpeg") { SetImageType(imageType); }
public long JpegQuality { get; set; } = 91;// 指定しないときの値は91と一致する
private string ImageType = "jpeg";
public Enc SetImageType(string imageType) {
imageType = imageType.ToLower();
if (imageType == "jpeg" || imageType == "jpg") {
ImageType = "jpeg";
} else if (imageType == "png") {
ImageType = "png";
} else if (imageType == "tif" || imageType == "tiff") {
ImageType = "tiff";
} else {
ImageType = imageType;// 小文字を設定
}
return this;
}
public int SaveImage(System.Drawing.Bitmap bitmap, string path, string imageType = null) {
var p = GetParams();
string imType = imageType?.ToLower();
if (p != null) {
bitmap.Save(path, GetInfo(imType), GetParams());// imageTypeがnullならSetImageType()のものが使われる
} else {// パラメータが空の場合
var imageFormat = new System.Drawing.Imaging.ImageFormat(GetInfo(imType).FormatID);
bitmap.Save(path, imageFormat);
}
return 0;
}
// Image版
public int SaveImage(System.Drawing.Image image, string path, string imageType = null)
{
var p = GetParams();
string imType = imageType?.ToLower();
if (p != null) {
image.Save(path, GetInfo(imType), GetParams());// imageTypeがnullならSetImageType()のものが使われる
}
else
{// パラメータが空の場合
var imageFormat = new System.Drawing.Imaging.ImageFormat(GetInfo(imType).FormatID);
image.Save(path, imageFormat);
}
return 0;
}
/// <summary>
/// サポートするEncodeパラメータ一覧
/// 現状Errorが発生して取得できない
/// </summary>
/// <param name="bitmap1">対象のBitMap</param>
public static void GetSupportedParameters(System.Drawing.Bitmap bitmap1 = null) {
// https://docs.microsoft.com/ja-jp/dotnet/framework/winforms/advanced/how-to-determine-the-parameters-supported-by-an-encoder
try {
if (bitmap1 == null) {
bitmap1 = new System.Drawing.Bitmap(100, 100);
var destBitmapData = bitmap1.LockBits(
new System.Drawing.Rectangle(0, 0, 100, 100),
System.Drawing.Imaging.ImageLockMode.ReadOnly,
bitmap1.PixelFormat
);
bitmap1.UnlockBits(destBitmapData);
}
var jpgEncoder = GetEncoderInfo(System.Drawing.Imaging.ImageFormat.Tiff);
var paramList = bitmap1.GetEncoderParameterList(jpgEncoder.Clsid);
var encParams = paramList.Param;
for (int i = 0; i < encParams.Length; i++) {
Console.WriteLine("Param " + i + " holds " + encParams[i].NumberOfValues +
" items of type " +
encParams[i].ValueType + "\r\n" + "Guid category: " + encParams[i].Encoder.Guid + "\r\n");
}
} catch (Exception e) {
Console.WriteLine($"Ignore error ={e.ToString()}");
}
}
// inner method.
private System.Drawing.Imaging.EncoderParameters GetParams() {
var encList = new List<System.Drawing.Imaging.EncoderParameter>();
//encList.Clear();
// 今はJPEGパラメータだけ
encList.Add(new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, JpegQuality));
//...
// 結合
var eps = new System.Drawing.Imaging.EncoderParameters(encList.Count);
for (var i = 0; i < encList.Count; i++)
eps.Param[i] = encList[i];
return eps;
}
private System.Drawing.Imaging.ImageCodecInfo GetInfo(string it = null) {
if (it == null) {// SetImageType()で指定したものを使う
it = ImageType;
}
return GetEncoderInfo($"image/{it}");
}
//ImageFormatで指定されたImageCodecInfoを探して返す
private static System.Drawing.Imaging.ImageCodecInfo GetEncoderInfo(System.Drawing.Imaging.ImageFormat f) {
var encs = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
foreach (var enc in encs) {
if (enc.FormatID == f.Guid)
return enc;
}
return null;
}
private static System.Drawing.Imaging.ImageCodecInfo GetEncoderInfo(string mineType) {
var encs = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
//指定されたMimeTypeを探して見つかれば返す
foreach (System.Drawing.Imaging.ImageCodecInfo enc in encs) {
if (enc.MimeType == mineType)
return enc;
}
return null;
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\PdfiumViewer.Native.x86_64.v8-xfa.2018.4.8.256\build\PdfiumViewer.Native.x86_64.v8-xfa.props" Condition="Exists('..\packages\PdfiumViewer.Native.x86_64.v8-xfa.2018.4.8.256\build\PdfiumViewer.Native.x86_64.v8-xfa.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{FD99EFAA-2479-4E3B-BD1A-5B785288E3B3}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>CSRender</RootNamespace>
<AssemblyName>CSRender</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<DocumentationFile>
</DocumentationFile>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<Reference Include="PdfiumViewer, Version=2.13.0.0, Culture=neutral, PublicKeyToken=91e4789cfb0609e0, processorArchitecture=MSIL">
<HintPath>..\packages\PdfiumViewer.2.13.0.0\lib\net20\PdfiumViewer.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Management" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Runtime.WindowsRuntime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5\System.Runtime.WindowsRuntime.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.ServiceModel" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" />
<Reference Include="Windows, Version=255.255.255.255, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Windows Kits\8.1\References\CommonConfiguration\Neutral\Annotated\Windows.winmd</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="CSRender.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="app.manifest">
<SubType>Designer</SubType>
</None>
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<EmbeddedResource Include="RES\BaseHash.pdf" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Content Include="CSRender_ReadMe.txt" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>このプロジェクトは、このコンピューター上にない NuGet パッケージを参照しています。それらのパッケージをダウンロードするには、[NuGet パッケージの復元] を使用します。詳細については、http://go.microsoft.com/fwlink/?LinkID=322105 を参照してください。見つからないファイルは {0} です。</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\PdfiumViewer.Native.x86_64.v8-xfa.2018.4.8.256\build\PdfiumViewer.Native.x86_64.v8-xfa.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\PdfiumViewer.Native.x86_64.v8-xfa.2018.4.8.256\build\PdfiumViewer.Native.x86_64.v8-xfa.props'))" />
</Target>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{FD99EFAA-2479-4E3B-BD1A-5B785288E3B3}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>CSRender</RootNamespace>
<AssemblyName>CSRender</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<DocumentationFile>
</DocumentationFile>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<Reference Include="PresentationCore" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Management" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Windows" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="CSRender.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="app.manifest">
<SubType>Designer</SubType>
</None>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<EmbeddedResource Include="RES\BaseHash.pdf" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Content Include="CSRender_ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.SDK.Contracts">
<Version>10.0.19041.1</Version>
</PackageReference>
<PackageReference Include="PdfiumViewer">
<Version>2.13.0</Version>
</PackageReference>
<PackageReference Include="PdfiumViewer.Native.x86_64.v8-xfa">
<Version>2018.4.8.256</Version>
</PackageReference>
<PackageReference Include="System.Runtime.WindowsRuntime.UI.Xaml">
<Version>5.0.0-preview.5.20278.1</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
\ No newline at end of file
/*--------------------------------------------------------------------------
* DynamicJson
* ver 1.2.0.0 (May. 21th, 2010)
*
* created and maintained by neuecc <ils@neue.cc>
* licensed under Microsoft Public License(Ms-PL)
* http://neue.cc/
* http://dynamicjson.codeplex.com/
*--------------------------------------------------------------------------*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace Codeplex.Data
{
public class DynamicJson : DynamicObject
{
private enum JsonType
{
@string, number, boolean, @object, array, @null
}
// public static methods
/// <summary>from JsonSring to DynamicJson</summary>
public static dynamic Parse(string json)
{
return Parse(json, Encoding.Unicode);
}
/// <summary>from JsonSring to DynamicJson</summary>
public static dynamic Parse(string json, Encoding encoding)
{
using (var reader = JsonReaderWriterFactory.CreateJsonReader(encoding.GetBytes(json), XmlDictionaryReaderQuotas.Max))
{
return ToValue(XElement.Load(reader));
}
}
/// <summary>from JsonSringStream to DynamicJson</summary>
public static dynamic Parse(Stream stream)
{
using (var reader = JsonReaderWriterFactory.CreateJsonReader(stream, XmlDictionaryReaderQuotas.Max))
{
return ToValue(XElement.Load(reader));
}
}
/// <summary>from JsonSringStream to DynamicJson</summary>
public static dynamic Parse(Stream stream, Encoding encoding)
{
using (var reader = JsonReaderWriterFactory.CreateJsonReader(stream, encoding, XmlDictionaryReaderQuotas.Max, _ => { }))
{
return ToValue(XElement.Load(reader));
}
}
/// <summary>create JsonSring from primitive or IEnumerable or Object({public property name:property value})</summary>
public static string Serialize(object obj)
{
return CreateJsonString(new XStreamingElement("root", CreateTypeAttr(GetJsonType(obj)), CreateJsonNode(obj)));
}
// private static methods
private static dynamic ToValue(XElement element)
{
var type = (JsonType)Enum.Parse(typeof(JsonType), element.Attribute("type").Value);
switch (type)
{
case JsonType.boolean:
return (bool)element;
case JsonType.number:
return (double)element;
case JsonType.@string:
return (string)element;
case JsonType.@object:
case JsonType.array:
return new DynamicJson(element, type);
case JsonType.@null:
default:
return null;
}
}
private static JsonType GetJsonType(object obj)
{
if (obj == null) return JsonType.@null;
switch (Type.GetTypeCode(obj.GetType()))
{
case TypeCode.Boolean:
return JsonType.boolean;
case TypeCode.String:
case TypeCode.Char:
case TypeCode.DateTime:
return JsonType.@string;
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
case TypeCode.SByte:
case TypeCode.Byte:
return JsonType.number;
case TypeCode.Object:
return (obj is IEnumerable) ? JsonType.array : JsonType.@object;
case TypeCode.DBNull:
case TypeCode.Empty:
default:
return JsonType.@null;
}
}
private static XAttribute CreateTypeAttr(JsonType type)
{
return new XAttribute("type", type.ToString());
}
private static object CreateJsonNode(object obj)
{
var type = GetJsonType(obj);
switch (type)
{
case JsonType.@string:
case JsonType.number:
return obj;
case JsonType.boolean:
return obj.ToString().ToLower();
case JsonType.@object:
return CreateXObject(obj);
case JsonType.array:
return CreateXArray(obj as IEnumerable);
case JsonType.@null:
default:
return null;
}
}
private static IEnumerable<XStreamingElement> CreateXArray<T>(T obj) where T : IEnumerable
{
return obj.Cast<object>()
.Select(o => new XStreamingElement("item", CreateTypeAttr(GetJsonType(o)), CreateJsonNode(o)));
}
private static IEnumerable<XStreamingElement> CreateXObject(object obj)
{
return obj.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Select(pi => new { Name = pi.Name, Value = pi.GetValue(obj, null) })
.Select(a => new XStreamingElement(a.Name, CreateTypeAttr(GetJsonType(a.Value)), CreateJsonNode(a.Value)));
}
private static string CreateJsonString(XStreamingElement element)
{
using (var ms = new MemoryStream())
using (var writer = JsonReaderWriterFactory.CreateJsonWriter(ms, Encoding.Unicode))
{
element.WriteTo(writer);
writer.Flush();
return Encoding.Unicode.GetString(ms.ToArray());
}
}
// dynamic structure represents JavaScript Object/Array
readonly XElement xml;
readonly JsonType jsonType;
/// <summary>create blank JSObject</summary>
public DynamicJson()
{
xml = new XElement("root", CreateTypeAttr(JsonType.@object));
jsonType = JsonType.@object;
}
private DynamicJson(XElement element, JsonType type)
{
Debug.Assert(type == JsonType.array || type == JsonType.@object);
xml = element;
jsonType = type;
}
public bool IsObject { get { return jsonType == JsonType.@object; } }
public bool IsArray { get { return jsonType == JsonType.array; } }
/// <summary>has property or not</summary>
public bool IsDefined(string name)
{
return IsObject && (xml.Element(name) != null);
}
/// <summary>has property or not</summary>
public bool IsDefined(int index)
{
return IsArray && (xml.Elements().ElementAtOrDefault(index) != null);
}
/// <summary>delete property</summary>
public bool Delete(string name)
{
var elem = xml.Element(name);
if (elem != null)
{
elem.Remove();
return true;
}
else return false;
}
/// <summary>delete property</summary>
public bool Delete(int index)
{
var elem = xml.Elements().ElementAtOrDefault(index);
if (elem != null)
{
elem.Remove();
return true;
}
else return false;
}
/// <summary>mapping to Array or Class by Public PropertyName</summary>
public T Deserialize<T>()
{
return (T)Deserialize(typeof(T));
}
private object Deserialize(Type type)
{
return (IsArray) ? DeserializeArray(type) : DeserializeObject(type);
}
private dynamic DeserializeValue(XElement element, Type elementType)
{
var value = ToValue(element);
if (value is DynamicJson)
{
value = ((DynamicJson)value).Deserialize(elementType);
}
return Convert.ChangeType(value, elementType);
}
private object DeserializeObject(Type targetType)
{
var result = Activator.CreateInstance(targetType);
var dict = targetType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.CanWrite)
.ToDictionary(pi => pi.Name, pi => pi);
foreach (var item in xml.Elements())
{
PropertyInfo propertyInfo;
if (!dict.TryGetValue(item.Name.LocalName, out propertyInfo)) continue;
var value = DeserializeValue(item, propertyInfo.PropertyType);
propertyInfo.SetValue(result, value, null);
}
return result;
}
private object DeserializeArray(Type targetType)
{
if (targetType.IsArray) // Foo[]
{
var elemType = targetType.GetElementType();
dynamic array = Array.CreateInstance(elemType, xml.Elements().Count());
var index = 0;
foreach (var item in xml.Elements())
{
array[index++] = DeserializeValue(item, elemType);
}
return array;
}
else // List<Foo>
{
var elemType = targetType.GetGenericArguments()[0];
dynamic list = Activator.CreateInstance(targetType);
foreach (var item in xml.Elements())
{
list.Add(DeserializeValue(item, elemType));
}
return list;
}
}
// Delete
public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
{
result = (IsArray)
? Delete((int)args[0])
: Delete((string)args[0]);
return true;
}
// IsDefined, if has args then TryGetMember
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
if (args.Length > 0)
{
result = null;
return false;
}
result = IsDefined(binder.Name);
return true;
}
// Deserialize or foreach(IEnumerable)
public override bool TryConvert(ConvertBinder binder, out object result)
{
if (binder.Type == typeof(IEnumerable) || binder.Type == typeof(object[]))
{
var ie = (IsArray)
? xml.Elements().Select(x => ToValue(x))
: xml.Elements().Select(x => (dynamic)new KeyValuePair<string, object>(x.Name.LocalName, ToValue(x)));
result = (binder.Type == typeof(object[])) ? ie.ToArray() : ie;
}
else
{
result = Deserialize(binder.Type);
}
return true;
}
private bool TryGet(XElement element, out object result)
{
if (element == null)
{
result = null;
return false;
}
result = ToValue(element);
return true;
}
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
return (IsArray)
? TryGet(xml.Elements().ElementAtOrDefault((int)indexes[0]), out result)
: TryGet(xml.Element((string)indexes[0]), out result);
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
return (IsArray)
? TryGet(xml.Elements().ElementAtOrDefault(int.Parse(binder.Name)), out result)
: TryGet(xml.Element(binder.Name), out result);
}
private bool TrySet(string name, object value)
{
var type = GetJsonType(value);
var element = xml.Element(name);
if (element == null)
{
xml.Add(new XElement(name, CreateTypeAttr(type), CreateJsonNode(value)));
}
else
{
element.Attribute("type").Value = type.ToString();
element.ReplaceNodes(CreateJsonNode(value));
}
return true;
}
private bool TrySet(int index, object value)
{
var type = GetJsonType(value);
var e = xml.Elements().ElementAtOrDefault(index);
if (e == null)
{
xml.Add(new XElement("item", CreateTypeAttr(type), CreateJsonNode(value)));
}
else
{
e.Attribute("type").Value = type.ToString();
e.ReplaceNodes(CreateJsonNode(value));
}
return true;
}
public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
{
return (IsArray)
? TrySet((int)indexes[0], value)
: TrySet((string)indexes[0], value);
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
return (IsArray)
? TrySet(int.Parse(binder.Name), value)
: TrySet(binder.Name, value);
}
public override IEnumerable<string> GetDynamicMemberNames()
{
return (IsArray)
? xml.Elements().Select((x, i) => i.ToString())
: xml.Elements().Select(x => x.Name.LocalName);
}
/// <summary>Serialize to JsonString</summary>
public override string ToString()
{
// <foo type="null"></foo> is can't serialize. replace to <foo type="null" />
foreach (var elem in xml.Descendants().Where(x => x.Attribute("type").Value == "null"))
{
elem.RemoveNodes();
}
return CreateJsonString(new XStreamingElement("root", CreateTypeAttr(jsonType), xml.Elements()));
}
}
}
\ No newline at end of file
== 引数のクラス化
RenderDoc() :メインの呼び出し
RenderPage() :ページ毎の処理。画像やHashも作成(選択)
RenderDocCompare(): メインの比較モード
RenderPageStream() : Compare時に呼び出す。Streamのみで、画像作成、Hash値は上位で実装するようにした。
→ RenderPage()もRenderPageStreamにして、RenderDoc()側で画像生成もあり
→ 複数PDFの処理は更にプログラムメインでPallarelで処理
→ asyncのスレッド処理はRenderDoc/RenderDocCompareでページの並行処理で使う
== 引数クラス
* スレッドを考えると書き換える情報はクラスに含めてはいけない
pegeN,Hashを除くべき
. まとめたクラスパラメータ
→ 結論:Render条件パラメータのみクラス化すべき→Hashでできているのかな?
class RenderParams {
// 基本操作パラメータ
string inPdfPath;//="" 対象PDF,ディレクトリはProgram側で対処
string inRefPdfPath; 比較モードのみ。そのPDFパス
string inOutputDir; //= "", 画像やハッシュの出力先が必要な場合
// Doc処理の操作パラメータ
string inPageRange;// = "1-*",
bool bSaveImage;// = true, //画像出力を伴う場合のみ
bool bHash;// = false, //ハッシュ値が必要な場合のみ
UtHash.HashDataxk inHashData=null //出力ハッシュコンテナ
string inMode;// = "pageBitMap", // デバッグ用
// Render条件パラメータ(すべてにほぼ必要)
{
double inDpi; //= 9.0,
string inImageType; //= "JPG",
int inJpegQ; = //0,
string inBoxType;// = "Crop",
}
}
class RenderParams {
string inPdfPath;//=""
string inOutputDir; //= "",
double inDpi; //= 9.0,
string inImageType; //= "JPG",
int inJpegQ; = //0,
string inBoxType;// = "Crop",
string inPageRange;// = "1-*",
string inMode;// = "pageBitMap",
bool bSaveImage;// = true,
bool bHash;// = false,
UtHash.HashDataxk inHashData=null
}
// RenderPdfDocCompare
string inPdfPath, // pdfもしくはディレクトリの場合あり→無い!pdfのみで、program側のループでディレクトリ展開
string inRefPdfPath,
string inDir = "", // 結果の出力先 未使用。diff画像が生成が未達成なのでその時の出力先とすべき
double inDpi = 9.0,
string inImageType = "JPG",
int inJpegQ = 0,
string inBoxType = "Crop",
string inPageRange = "1-*",
string inMode = "pageBitMap",
bool bHash = false,
UtHash.HashDatax inHashDataTgt=null,
UtHash.HashDatax inHashDataRef=null
// RenderPage
// Need:
PdfDocument inPdfDoc, // Need GetPage() only. (Total page number);
// 総ページ数のためだけに必要。あってもいいでしょう
PdfPage inPdfPage, // Target Page Data(page.index:0-x)
string inOutputPath,// Imageのパス
string inOutputDir = "",// これ必要?→不要が確定
ref string inOutputHashCode, // ページハッシュコード出力の受け取り
// Optional:
double inDpi = 72.0,
string inEncName = "JPG", //画像フォーマット、Saveのときのみ
int inJpegQ = 91,
string inBoxType = "Crop",
bool bSaveImage = true,// ファイル保存有無。ハッシュ値計算のみのときにfalseにする
bool bHash = false
// RenderPageStream
// Need:
PdfDocument inPdfDoc, // Need GetPage() only. (Total page number);
PdfPage inPdfPage, // Target Page Data(page.index:0-x)
string otPath, // 不要確定
// Optional:
double inDpi = 72.0,
string inBoxType = "Crop"
// 出力画像であるJpeg,EncNameが不要
//
== 排他制御関係
#if COMMNET
http://espresso3389.hatenablog.com/entry/20080827/1219787248
安全なMutex
ということで、次のようなラッパークラスを作った。
class SessionLock : IDisposable
{
public SessionLock(string mutexName)
{
m_mutex = new Mutex(false, mutexName);
m_mutex.WaitOne();
}
public void Dispose()
{
try
{
m_mutex.ReleaseMutex();
m_mutex.Close();
}
catch { }
}
Mutex m_mutex;
}
これならば、
using System;
using System.Threading;
namespace MutexTest
{
...
public class MutexTest
{
public static void Main()
{
using (new SessionLock("Hello, world"))
{
Console.WriteLine("Hey, I'm in the protected world!");
Thread.Sleep(10000);
Console.WriteLine("...");
}
}
}
}
#endif
== 2020/5/31
WCF+SortedDictionaryで一旦動作した。
残件::
* Compare
* help
* 共通化
* 強制終了
* BaseHashの調整
* 標準出力
* WCFのデータ整理
* WCFのジェネリック化
* namespace
* vim
\ No newline at end of file
using System;
using System.IO;
using System.Collections.Generic; // For List<>
using System.Linq; // For Enumration
using System.Reflection; // Assembly.
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.Serialization;
using System.ServiceModel; // for WCF
using System.Diagnostics; // for Process
// no need
//using System.Runtime.InteropServices;
// 作成クラス
using CSRender;
using CSRender.UtHash;
using static CSRender.RenderPDF;
// *重要* デスクトップアプリで UWP Api を呼び出す プロジェクトの設定方法が記載されている
// https://docs.microsoft.com/ja-jp/windows/apps/desktop/modernize/desktop-to-uwp-enhance
// 参照はwindows. winmd :C:\Program Files (x86) \Windows Kits\10\UnionMetadata\<sdk バージョン>/ファサード
namespace CSRenderMain {
[DataContract]
//[Serializable()]
public class ParamData {
[DataMember]
public string pdfPath = ""; //対象ファイル
[DataMember]
public string pdfPathRef = ""; //比較ファイル
[DataMember]
public string outputImageDir = ""; // /O
[DataMember]
public string dpi = "72.0"; // /D
[DataMember]
public int para = 4; // 並行数(プロセス数)
[DataMember]
public int paraPage = 4; // 並行数(page処理スレッド)
[DataMember]
public string boxSelect = "Crop"; // /B<x>
[DataMember]
public string pageRange = "1-*"; // /P
[DataMember]
public string mode = "page"; // /MODE
[DataMember]
public string imageType = "JPG"; // /JPG or /PNG
[DataMember]
public string jpegQ = "91"; // JPEGQ
[DataMember]
public bool bHash = false; // ハッシュ値を生成する
[DataMember]
public bool bMkHash = false; // ハッシュファイルを作成する
[DataMember]
public bool bFC = false;
[DataMember]
public string resultPath = "";
[DataMember]
public bool bPDFium = true;
//
[DataMember]
public bool bExeSepa = true;// 実行分離
[DataMember]
public string subExe = null;// "Sub"が指定されたら、処理をExe分離する。内部コマンド
// データはWCFの通信データを使う。引数はPipeName:PortAddressNameとする
[DataMember]
public bool bVerbose = false;// 詳細デバッグ
[DataMember]
public bool bVerify = false;// 詳細デバッグ
public ParamData Clone() {
return (ParamData)MemberwiseClone();
}
}
public class Program {
static void DispHelpNoArg() {
var asmName = Assembly.GetExecutingAssembly().GetName();
var pgName = asmName.Name;// "アセンブリ名"
var v1 = asmName.Version; // "1.0.0.0"
// 逐語的文字列リテラル $@, ダブルクウォートは2つでエスケープされる
// HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
Console.Write( $@"
Version={ v1}
{pgName} [/<Opts>] <PDFPath or PDFDir> :Rendering(to JPEG,TIFF,...)
{pgName} /MkHash [/<Opts>] <PDFPath or PDFDir> :Make Imaged hash keys
{pgName} /FC [/<Opts>] <TgtPDF Dir> <RefPDF Dir>:Compare files
Render of PDF file.available 3 command mode:[Basic Rendering] [Make Hash command] [Compare command], and[Render Options]
PDFの画像化は[Basic Rendering]。
比較は/MkHash([Make Hash command]) 後に/FC([Compare command]) で高速実行できます。
For more information,see /H /? or /?
");
// HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
}
static void DispHelpDetail() {
var asmName = Assembly.GetExecutingAssembly().GetName();
var pgName = asmName.Name;// "アセンブリ名"
var v1 = asmName.Version; // "1.0.0.0"
DispHelpNoArg();
// 逐語的文字列リテラル $@, ダブルクウォートは2つでエスケープされる
// HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
Console.Write($@"
[Basic Rendering] 基本的なレンダリング
{pgName} [/<Render Options>] <PDFPath|PDFDir>
/F <pdfPath|pdfDir> : pdfPath(pdfファイル名|ディレクトリ) /Fは省略可能
/O|Output <output directory> : 出力ディレクトリ。
省略時はPDF指定の場合は同一階層の"".IMG""フォルダ。
ディレクトリ指定の場合は""<ディレクトリ名>.IMG""、差分画像は""<ディレクトリ名>.DiffImage""。
[Render Options] レンダリングオプション
/D|Dpi <解像度> : 解像度指定 9 - 300dpi(default=72dpi)
/JPG,/JPEG,/PNG,/TIF,/TIFF,/GIF,/BMP: Select one output format.(default=/JPG)
/JPEGQ <quality>: Jpegの品質指定1-100(default=91)
/P|Page <PageRange> : ページの範囲を指定する(省略時は全ページ)
連続した範囲を指定する場合は、ハイフン('-')を用いる。終了側を省略すると最終pageまで。
複数のページを指定する場合は、カンマ(',')を用いる
Ex. /P ""1,2,30-100"" //1,2pages and 30-100pages.
[Unsupport] 未対応↓
/L <input List text> : 入力PDFファイルリスト(*unsupport)
/T <tempPath> : テンポラリフォルダを指定(省略時は出力先フォルダと同じ(*unsupport no need)
/OP <0|1> : オーバープリントのOn/Off (省略時は1)(*unsupport allways on[1])
/U <0|1> : 同名上書き設定 0:上書きしない 1:上書き(*unsupport allways overwrite[1])
/OFFSET <X> <Y> : ミリ単位でオフセットを指定する(省略時は共に0mm)(*unsupport)
[Obs]/PDFium <0or1>: GoogoleのPDFiumViewerエンジンを使用する(default=1>
[未]/BM,/BT,/BA,/BA,/BC: Select one box.(default=/BC:CrobBox): Boxies:MediaBox/BleedBox/TrimBox/ArtBox/CropBox
[Make Hash command] /MkHash 比較用ハッシュ値作成コマンド
{pgName} /MkHash ...<Render Options>... <PDF|PDF dir>
/MKHash : ハッシュ値を出力する。前記の[Render Options]を指定すること
[Compare command] /Fc比較コマンド
{pgName} /Fc ...<Render Options>... [/Tgt|Target] <Target PDF|PDF dir> [/Ref|Refernce] <Reference PDF|PDF dir>
/FC : 2つのPDFを比較する。前記の[Render Options]を指定すること。無名引数が2つ必要です
事前に/MkHashを実行しておくことで高速に処理できる
/Tgt|Target <<Target PDF|PDF dir>> : ターゲットファイル指定
/Ref|Reference <<Reference PDF|PDF dir>> : リファレンスファイル指定(比較先)
/Verify : PureVerify mode. Diff画像をTGTとREFのサブ階層に出力する
/Result <result file> : 比較結果を格納するファイルパス
/FCコマンドを指定すると一致したら0,不一致なら1を返却するようになる
<result file>は、<pageNum(1始まり)>,<[OK] or [@Difference]>の行で構成される
[ELSE] その他のオプション
/Para : <プロセス並行数>:本Exeの並行数を指定(デフォルト4)
/ParaPage : <ページ処理スレッド数>:ページ処理のスレッド数を指定(デフォルト4)
/Verbose [True|1] : 詳細表示
[obs]/NoExeSepa :実行分離しない(遅い)
/H or /? : This help");
// HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
}
/// <summary>
/// PDF render main
/// </summary>
/// <param name="args"></param>
/// <returns>0 正常終了</returns>
static int Main(string[] args) {
var argsStr = String.Join(@" ", args);
var pm = new ParamData(); // 引数の保持
bool bDirMode = false; // ディレクト指定の場合
string[] pdfPathLst = null;
string[] pdfPathLst2 = null;
var pdfPathLstBoth = new List<string>();
var pdfPathLstNoBoth = new List<string>();
//ハッシュ関係
string hashBaseName = "RenderHash";
// No CSRender.Check.GetDPI();
// 未使用
//{// ベースハッシュ値の計算テスト
// var streamPDF = ResData.GetBaseHashPDF();
// RenderPDF.RenderPdfInitCheck(streamPDF);
//}
var logicalProcessNum = Environment.ProcessorCount;
if ( logicalProcessNum >= 10 ) {// 元々 4(exe)+4(page)なので+2 = プロセス数が10以上の時にexe数を増やす
pm.para = logicalProcessNum - pm.paraPage;
}
/*
* ↓引数解析
* */
var qu = new Queue<string>(args); // 引数をQueに登録 (qu.Enqueue(a)でも可能)
while (qu.Count > 0) {
// 引数のパース
var wd = qu.Dequeue(); // 取り出しqu.Dequeue()で次の要素を取得する
if (wd.First() == '-') {
// 先頭-(ハイフンもオプション扱いにする)→"/"に置換
wd = Regex.Replace(wd, @"^\-", "/");
}
//大文字小文字無視でオプションチェック
var eIgnoreCase = StringComparer.OrdinalIgnoreCase;
// ローカル関数:オプションチェック
bool isOpt(params string[] opts) => opts.Contains<string>(wd, eIgnoreCase);
// ローカル関数:オプションの値を取得
string getValue(string defaultValue = "" ) {
if ( qu.Count == 0 )
return defaultValue;
if ( Regex.Match( qu.Peek(), $@"^[\/\-]" ).Success )
return defaultValue; // 次のオプションキー -> 初期値を返す
return qu.Dequeue(); //値をキューから取り出す
}
// ボックスオプション辞書
var BoxSelOptDic = new Dictionary<string, string>(eIgnoreCase) { ["/BM"] = "Media", ["/BT"] = "Trim",
["/BB"] = "Bleed", ["/BC"] = "Crop",
["/BA"] = "Art"
};
if (isOpt("/?", "/H","/Help")) {
DispHelpDetail();
return -1;
} else if (isOpt("/F","/Tgt","/Target")) {
pm.pdfPath = getValue(); // next value.
} else if (isOpt("/Ref","/Reference")) {
pm.pdfPathRef = getValue(); // next value.
} else if (isOpt("/O","/Output")) {
pm.outputImageDir = getValue(); // next value.
} else if (isOpt("/D","/DPI")) {
pm.dpi = getValue(); // next value.
if (!double.TryParse(pm.dpi, out double dmy)) {
Console.WriteLine($"解像度が不正です:/D {pm.dpi}");
DispHelpNoArg();
return -1;
}
} else if (isOpt("/Para")) {
string paraNum = getValue(); // next value.
if (!int.TryParse(paraNum, out pm.para)) {
Console.WriteLine($"並行数が不正です:/para {paraNum}");
DispHelpNoArg();
return -1;
}
} else if (isOpt("/ParaPage")) {
string paraNum = getValue(); // next value.
if (!int.TryParse(paraNum, out pm.paraPage)){
Console.WriteLine($"並行数(ページスレッド数が不正です:/ParaPage {paraNum}");
DispHelpNoArg();
return -1;
}
} else if (isOpt("/P","/Page")) {
pm.pageRange = getValue(); // next value.
} else if (isOpt("/JPG", "/JPEG")) {
pm.imageType = "JPG";
} else if (isOpt("/PNG")) {
pm.imageType = "PNG";
} else if (isOpt("/TIF", "/TIFF")) {
pm.imageType = "TIFF";
} else if (isOpt("/GIF", "/GIFF")) {
pm.imageType = "GIF";
} else if (isOpt("/BMP")) {
pm.imageType = "BMP";
} else if (isOpt("/JPEGQ")) {
pm.jpegQ = getValue(); // next value.
if (!int.TryParse(pm.jpegQ, out int dmy)) {
Console.WriteLine($"JPEG Qualityが不正です:/JPEGQ {pm.jpegQ}");
DispHelpNoArg();
return -1;
}
if (!(0 < dmy && dmy <= 100)) {
Console.WriteLine($"JPEG Qualityが不正です(not 1-100):/JPEGQ {dmy}");
return -1;
}
} else if (isOpt("/M")) {
pm.mode = getValue(); // next value.
} else if (BoxSelOptDic.ContainsKey(wd)) {
pm.boxSelect = BoxSelOptDic[wd];// "/BT" -> "Trim",...
} else if (isOpt("/HASH")) {
pm.bHash = true;
} else if (isOpt("/MKHASH")) {
pm.bMkHash = true;
pm.bHash = true;
} else if (isOpt("/FC")) {
pm.bFC = true;
} else if (isOpt("/PDFium")) {
pm.bPDFium = true;
var flgStr = getValue(); // next value.
if (!int.TryParse(flgStr, out int dmy)) {
Console.WriteLine($"PDFiumフラグが不正です:/PDFium {flgStr}");
return -1;
}
if (dmy == 0) {
pm.bPDFium = false;
} else if (dmy == 1) {
pm.bPDFium = true;
} else {
Console.WriteLine($"PDFiumフラグが不正です:/PDFium {flgStr}");
return -1;
}
} else if (isOpt("/Verbose")) {
var arg = getValue("True"); // next value.
string[] sel = {"True","1","ON"};
pm.bVerbose = sel.Contains(arg, eIgnoreCase);
} else if (isOpt("/SubExe")) {
pm.subExe = getValue(null); // next value.
var sp = pm.subExe.Split(':');
if (sp.Length < 2 ) {
Console.WriteLine($"SubExe指定は\":\"区切りが必要: {pm.subExe}");
return -1;
}
} else if (isOpt("/NoExeSepa")) {
pm.bExeSepa = false;
} else if (isOpt("/RESULT")) {
pm.resultPath = getValue(""); // next value.
} else if (isOpt("/Verify")) {
pm.bVerify = true;
} else if (wd.First() == '/') {
// 処理の無いオプションを明示的に無視する
Console.WriteLine($"Warning::Ignore opt:{wd}");
} else {
// 引数をファイル名として取得する
if (pm.pdfPath == "") {
pm.pdfPath = wd;
continue;
}
if (pm.bFC && (pm.pdfPathRef == "")) {
pm.pdfPathRef = wd;// 比較時のみ取得
continue;
}
}
}
// ↑引数解析終わり
setEcho(pm.bVerbose);
if (pm.bVerbose)
echo("Varbose Mode!");
//
bool bSubExe = (pm.subExe != null);// SubExeで起動されている場合。
xChangeWCFPipe.IXData cltSrv = null;
if (!bSubExe) {
/// サーバー側
echo("++MainProcess start");
Console.WriteLine($"LogicalProcNum={logicalProcessNum},ProcessParallelTasks={pm.para},PageParallelTasks={pm.paraPage}");
} else {
// SubExe側の動作に差し替える
var sp = pm.subExe.Split(':');
var pipeName = sp[0]; var pipeAddr = sp[1];
cltSrv = xChangeWCFPipeGEN.CLT_T.makeCLT<xChangeWCFPipe.IXData>(pipeName:pipeName,pipeAddress:pipeAddr);
Ut.Ut.SetAutoSelfKillByMainProcEnd(); // 起動元が終了した場合に自身を終了させる
pm = cltSrv.GetParam(); // パラメータを書き換える
setEcho(pm.bVerbose);
echo("++SubProcess start:" + pm.subExe);
}
if (pm.pdfPath == "") {
Console.WriteLine("pdfファイルが指定されてません");
DispHelpNoArg();
return -1;
}
if (!(File.Exists(pm.pdfPath) || Directory.Exists(pm.pdfPath))) {
// ファイルもしくはディレクトも見つからない場合
Console.WriteLine($"ファイルが存在しません:{pm.pdfPath}");
return -1;
}
var rdCond = new RenderPDF.RenderConditionParams {
Dpi = double.Parse(pm.dpi),
ImageType = pm.imageType,
BoxType = pm.boxSelect,
JpegQ = int.Parse(pm.jpegQ)
};
bool bDir = File.GetAttributes(pm.pdfPath).HasFlag(FileAttributes.Directory);
if (bDir) {
// Directoryが指定されたのでファイルリストアップ
bDirMode = true;
pdfPathLst = System.IO.Directory.GetFiles(pm.pdfPath, "*.pdf"/*, System.IO.SearchOption.AllDirectories*/);
pdfPathLst = Array.ConvertAll(pdfPathLst, f => Path.GetFileName(f));
// 配列書き換え(ファイル名のみにする)
// var enumLst = pdfPathLst.Select(f => Path.GetFileName(f)); LINQ式に置き換えることも可能(返り値は配列ではない)
//foreach ( var f in pdfPathLst) {
// Console.WriteLine($@"path1={f}");
//}
//Console.WriteLine($@"path1.Len={pdfPathLst.Count()}");
}
var resultData = new SortedDictionary<int, string>();
if ((!pm.bFC) && bDir) {
// 単純レンダリング時 かつ ディレクト時に 対象リストに追加
foreach (var f in pdfPathLst) {
pdfPathLstBoth.Add(f);
}
}
if (pm.bFC) {// 比較モード時
if (pm.pdfPathRef == "") {
Console.WriteLine("比較モードで2つ目のpdfファイルが指定されてません");
return -1;
}
if (!(File.Exists(pm.pdfPathRef) || Directory.Exists(pm.pdfPathRef))) {
Console.WriteLine($"比較ファイルが存在しません:{pm.pdfPathRef}");
return -1;
}
// 同一フォルダorファイルの禁止
if (Path.GetFullPath(pm.pdfPath).Equals(Path.GetFullPath(pm.pdfPathRef),StringComparison.OrdinalIgnoreCase) ){
Console.WriteLine("ターゲットとリファレンスが同一です");
return -1;
}
bool bDir2 = File.GetAttributes(pm.pdfPathRef).HasFlag(FileAttributes.Directory);
if (bDir2) {
if (!bDir) {
Console.WriteLine($"比較対象はファイルパスでないといけません:{pm.pdfPathRef}");
return -1;
}
// 2つ目のファイルリストアップ
pdfPathLst2 = System.IO.Directory.GetFiles(pm.pdfPathRef, "*.pdf"/*, System.IO.SearchOption.AllDirectories*/);
pdfPathLst2 = Array.ConvertAll(pdfPathLst2, f => Path.GetFileName(f));// 配列の書き換え
// 共通のファイルを見つける。Lstの要素がLst2に含まれているかどうか
foreach (var f in pdfPathLst) {
if (pdfPathLst2.Contains(f)) {
pdfPathLstBoth.Add(f);
} else {
pdfPathLstNoBoth.Add("tgt:"+f);// LstがLst2に含まれていない
}
}
// Lst2のみファイルをNoBothに登録
foreach (var f in pdfPathLst2) {
if (!pdfPathLstBoth.Contains(f)) {
pdfPathLstNoBoth.Add("ref:"+f);
}
}
// pdfPathBoth,pdfPathNoBothが作成済み
if (pdfPathLstNoBoth.Count() != 0) {
Console.WriteLine($@"不一致のファイル={pdfPathLstNoBoth.Count()}");
foreach (var f in pdfPathLstNoBoth) {
Console.WriteLine($@"warning [no match]={f}");
}
}
}
}
var watch = System.Diagnostics.Stopwatch.StartNew(); // 時間の生成と計測開始を同時に行う
var otDir = pm.outputImageDir;
if (otDir == "") {
if ( bDir ) {
var suffix = pm.bFC ? ".DiffImage": ".IMG";
otDir = Path.Combine( Directory.GetParent(pm.pdfPath).FullName, Path.GetFileName( pm.pdfPath )+suffix);
echo($"****Output dir={otDir} ******\n");
if (!Directory.Exists(otDir) && (!pm.bMkHash) ) { //
Directory.CreateDirectory(otDir);
}
} else {
// 出力ディレクトリの作成 // 元PDFの同一フォルダにIMGフォルダを作成する
otDir = Path.Combine(Directory.GetParent(pm.pdfPath).FullName, "IMG");
}
pm.outputImageDir = otDir;// pmに戻す
}
var otHashPath = "";
var otHashPath2 = "";
int ret = -1;
//Console.WriteLine($@"Use bPDFium={pm.bPDFium}");
if (!bDirMode) {
if (pm.bFC) {
//比較モード
// ハッシュデータの読み込み
echo($@"pre pdfPath={pm.pdfPath}");
echo($@"pre pdfPathRef={pm.pdfPathRef}");
var hashDataTgt = HashData.load(pm.pdfPath, hashBaseName, pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ, ref otHashPath);
var hashDataRef = HashData.load(pm.pdfPathRef, hashBaseName, pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ, ref otHashPath2);
//Console.WriteLine("<Compare Sync(Paralles) Version!>");
if (pm.resultPath != "") {// 初期化
File.WriteAllText(Path.GetFullPath(pm.resultPath), "");
}
ret = RenderPDF.RenderPdfDocCompare(
pdfPath: Path.GetFullPath(pm.pdfPath),
refPdfPath: Path.GetFullPath(pm.pdfPathRef),
resultDataPath: pm.resultPath,
inDir : otDir,
pm : rdCond,
inPageRange : pm.pageRange,
inHashDataTgt: hashDataTgt,
inHashDataRef: hashDataRef,
bPDFium : pm.bPDFium,
nPageThreadNum: pm.paraPage,
bVerify : pm.bVerify
);
} else {
// Sync version.
// Console.WriteLine("<Render Sync(Paralles) Version!>");
// シングル指定では既存のハッシュファイルを読みださない → 単独名のハッシュファイル<pdfFName+".hash")
// 空のハッシュデータを作成
var hashDataTgt = new HashData();
hashDataTgt.Head.SetRenderInfo(pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ);
//retはページ数
// rdCond
ret = RenderPDF.RenderPdfDoc(
pdfPath : Path.GetFullPath(pm.pdfPath),
inDir : otDir,
pm : rdCond,
inPageRange : pm.pageRange,
bSaveImage : pm.bMkHash ? false : true,// ハッシュ値生成ではイメージ保存しない。
bHash : pm.bHash,
inHashData : pm.bMkHash ? hashDataTgt : null, //ハッシュコマンドモードのみDataを渡す
bPDFium : pm.bPDFium,
nPageThreadNum : pm.paraPage
);
if (pm.bMkHash) {
/// ここでMain側に通信データを返せばよい
if (bSubExe) {
cltSrv.SetHashData(hashDataTgt);
} else {
// 個別のファイル名+"hash"拡張子で保存します。
var othashPath = Path.Combine(otDir, Path.GetFileName(pm.pdfPath) + ".hash");
hashDataTgt.save(othashPath);//ハッシュモードで保存する(Dutyチェックもいるでしょう
//不要:hashDataTgt.save(otHashPath);//比較モード,MakeHashに限定すること
//表示のみ まだやめておく:
}
}
// retはページ数を返す
}
} else {
// 対象がディレクトリの場合
echo("For Directory mode");
HashData hashDataTgt = null, hashDataRef = null;
hashDataTgt = HashData.load(pm.pdfPath, hashBaseName, pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ, ref otHashPath);
if (pm.bMkHash) {
hashDataTgt = null;// MKHashの時にはLoadしない → 一旦nullで除去して、otHashPathを利用する
}
if (hashDataTgt == null) {
// 空のハッシュデータを作成
hashDataTgt = new HashData();
hashDataTgt.Head.SetRenderInfo(pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ);
}
if (pm.bFC) {
// リファレンス側のハッシュの読み込み
hashDataRef = HashData.load(pm.pdfPathRef, hashBaseName, pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ, ref otHashPath2);
if (hashDataRef == null) {
// 空のハッシュデータを作成
hashDataRef = new HashData();
hashDataRef.Head.SetRenderInfo(pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ);
}
}
echo($@"Start render:Count={pdfPathLstBoth.Count}");
//Console.WriteLine("<Render Sync(Paralles) Version!>");[
var count = pdfPathLstBoth.Count;
if (pm.bExeSepa &&(!pm.bFC)) { // FCモードは除外します。
var tokenSource = new CancellationTokenSource();
ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = pm.para };
ret = 0;//Success
var loopResult = Parallel.For(0,pdfPathLstBoth.Count, options, (index,lpState) => {
//for (var index = 0; index < pdfPathLstBoth.Count; index++) {
var tgt = Path.Combine(pm.pdfPath, pdfPathLstBoth[index]);
var tgtID = $@"{index+1}/{pdfPathLstBoth.Count}";
Console.WriteLine($@"**Remain({count})****tgt({tgtID})={tgt}");
if (pm.bFC) {
//比較モード
var reff = Path.Combine(pm.pdfPathRef, pdfPathLstBoth[index]);
} else { // Sync version(Paralles).
var svrData = new xChangeWCFPipe.XData();
var pmClone = pm.Clone();
pmClone.pdfPath = tgt;// 引数のターゲットのみを書き換える
svrData.SetParam(pmClone);
string guidStr = Guid.NewGuid().ToString("N");
string pipeName = $"PN_{guidStr}";
string pipeAddress = $"P_{index}_{guidStr}";
var svrHost = xChangeWCFPipeGEN.SVR_T.makeSVR(
baseIf : typeof(xChangeWCFPipe.IXData),
obj : svrData,
pipeName : pipeName,
pipeAddress : pipeAddress
);
if ( svrHost == null) {
Console.WriteLine("WCF cannot make");
//tokenSource.Cancel();// 処理のキャンセル( throwされる)
lpState.Stop();
return;
}
var myExePath = Assembly.GetExecutingAssembly().Location;
var proc = Ut.Ut.DoCmd(
cmdAndArgs: new string[] { myExePath, "/SubExe",$"{pipeName}:{pipeAddress}" }
, bEcho: false
, bSameConsole: true
);
proc.WaitForExit();
var retProc = proc.ExitCode;
echo($@"retProc={retProc}");
if ( retProc < 1 ) {
//PDFページ数以外が返った時
ret = -1;
Console.WriteLine( $@"Warning ::Cannot get PDFPage:{retProc},tgt={tgt},{argsStr}");
} else {
;// 初期値 ret=0;
}
//while (!proc.HasExited) {
// System.Threading.Thread.Sleep(2 * 1000);
//}
var tmpH = svrData.GetHashData();
if (tmpH == null) {
echo("tmpH is null");
}
if ( (hashDataTgt!=null)&&(tmpH!=null)) {
lock(hashDataTgt) {
//hashDataTgt.Files += tmpH.Files;
if ( tmpH.Files.Count() < 1 ) {// 中身が空なら警告
Console.WriteLine($@"Warning tempF.Count={tmpH.Files.Count()}");
}
var merged = hashDataTgt.Files
.Concat(tmpH.Files.Where(pair =>
!hashDataTgt.Files.ContainsKey(pair.Key))
).ToDictionary(
pair => pair.Key,
pair => pair.Value
);
hashDataTgt.Files = new SortedDictionary<string, HashFile>(merged);// hashを合成した。
}
}
proc.Dispose();
svrHost.Close();
svrData = null;
echo($@"End tgt({tgtID})");
}
//GC.Collect();// これでメモリリークが解決した Paraの中ではやめておく
count--;
});
if ( !loopResult.IsCompleted ) {
Console.WriteLine("Abort!");
pm.bMkHash = false;// Hash値保存抑制
ret=-1;
}
////tokenSource.Cancel();// 処理のキャンセル
//if ( tokenSource.IsCancellationRequested ) {
// pm.bMkHash = false;// Hash値保存抑制
//}
//}; // Non Para Block
echo($"********** コマンド終了*****{argsStr} ");
} else if (pm.bExeSepa &&(pm.bFC)) { // セパのFCモード
/*
refのハッシュが存在しなければWCFで作成
tgtのハッシュは強制的にWCFで作成->refと同様に存在しなければ作成
*/
echo($"****************セパのFCモード******{argsStr}************");
// リファレンス側のハッシュチェック
hashDataRef = HashData.load(pm.pdfPathRef, hashBaseName, pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ, ref otHashPath2);
// ハッシュファイルとファイルとの日付を比較する
Console.WriteLine(otHashPath2);
if ( (hashDataRef != null) && !hashDataRef.IsValidHashFile(pdfPathLst2)) {
// ハッシュファイルが異常→ファイルを削除
File.Delete(otHashPath2);
hashDataRef=null;
}
if ( hashDataRef == null ) {
var myExePath = Assembly.GetExecutingAssembly().Location;
var proc = Ut.Ut.DoCmd(
cmdAndArgs: new string[] { myExePath, "/MkHash",pm.pdfPathRef,"/D",pm.dpi,$"/{pm.imageType }",$"/JPEGQ",pm.jpegQ }
, bEcho: true
, bSameConsole: true
);
proc.WaitForExit();
hashDataRef = HashData.load(pm.pdfPathRef, hashBaseName, pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ, ref otHashPath2);
if ( hashDataRef != null ) {
echo($" OK hash ref");
}
} else {
echo($" OK hash ref(already exist)");
}
// ターゲット側のハッシュチェック
hashDataTgt = HashData.load(pm.pdfPath, hashBaseName, pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ, ref otHashPath);
if ( (hashDataTgt != null) && !hashDataTgt.IsValidHashFile(pdfPathLst)) {
// ハッシュファイルが異常→ファイルを削除
File.Delete(otHashPath);
hashDataTgt=null;
}
if ( hashDataTgt == null ) {
// ターゲット側のハッシュ計算
var myExePath = Assembly.GetExecutingAssembly().Location;
var proc = Ut.Ut.DoCmd(
cmdAndArgs: new string[] { myExePath, "/MkHash",pm.pdfPath,"/D",pm.dpi, $"/{pm.imageType }",$"/JPEGQ",pm.jpegQ }
, bEcho: true
, bSameConsole: true
);
proc.WaitForExit();
hashDataTgt = HashData.load(pm.pdfPath, hashBaseName, pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ, ref otHashPath);
if ( hashDataTgt != null ) {
echo($" OK hash tgt");
}
}
//if (false/*true*/){// 2022.5.7 なぜ常に作成していたか? K.Matsuo
// // ターゲット側のハッシュ計算
// var myExePath = Assembly.GetExecutingAssembly().Location;
// var proc = Ut.Ut.DoCmd(
// cmdAndArgs: new string[] { myExePath, "/MkHash",pm.pdfPath,"/D",pm.dpi, $"/{pm.imageType }",$"/JPEGQ",pm.jpegQ }
// , bEcho: true
// , bSameConsole: true
// );
// proc.WaitForExit();
// hashDataTgt = HashData.load(pm.pdfPath, hashBaseName, pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ, ref otHashPath);
// if ( hashDataTgt != null ) {
// echo($" OK hash tgt");
// }
//}
echo($@"****************FC開始*****{argsStr}**************");
if (pm.resultPath != "") {// 初期化
File.WriteAllText(Path.GetFullPath(pm.resultPath), "");
}
int noMatchPageNum=0;
int noMatchFileNum=0;
for (var index = 0; index < pdfPathLstBoth.Count; index++) {
var tgt = Path.Combine(pm.pdfPath, pdfPathLstBoth[index]);
Console.WriteLine($@"tgt={index+1}/{pdfPathLstBoth.Count}:{tgt}");
var reff = Path.Combine(pm.pdfPathRef, pdfPathLstBoth[index]);
ret = RenderPDF.RenderPdfDocCompare(
pdfPath: Path.GetFullPath(tgt),
refPdfPath: Path.GetFullPath(reff),
resultDataPath: pm.resultPath,
inDir: otDir,
pm: rdCond,
inPageRange: pm.pageRange,
inHashDataTgt: hashDataTgt,
inHashDataRef: hashDataRef,
bPDFium: pm.bPDFium,
nPageThreadNum:pm.paraPage,
bVerify : pm.bVerify
);
if ( ret > 0 ) {
// retは不一致ページ数
noMatchFileNum++;
noMatchPageNum+= ret;
}
};
watch.Stop();
var SummaryResult = $"\n[結果]\n";
SummaryResult += $"Args ={argsStr}\n";
SummaryResult += $"Target ={pm.pdfPath}\n";
SummaryResult += $"Reference={pm.pdfPathRef}\n";
SummaryResult += $"不整合ファイル群={pdfPathLstNoBoth.Count()}\n";
foreach (var f in pdfPathLstNoBoth) {
SummaryResult += $"\tWarning [no match]={f}\n";
}
SummaryResult += $"NGファイル数={noMatchFileNum}\n";
SummaryResult += $"NGページ数 ={noMatchPageNum}\n";
SummaryResult += $"Result={ret},time={ watch.ElapsedMilliseconds / 1000.0 }[sec]";
Console.WriteLine(SummaryResult);// 結果標準出力
if (pm.resultPath != "") {// ファイル出力の先頭に追記
var rData = File.ReadAllText(pm.resultPath);
SummaryResult += "\n[詳細] *find @Difference\n";
File.WriteAllText(Path.GetFullPath(pm.resultPath), (SummaryResult + rData));
}
echo($"****************[終了]セパのFCモード***{argsStr}***************");
ret = noMatchPageNum;// 返値 0:OK,!0=不一致Page数
} else { // NoExeSepa -> Obsolate
echo($@"****************NoExeSepa*****{argsStr}**************");
if (pm.resultPath != "") {// 初期化
File.WriteAllText(Path.GetFullPath(pm.resultPath), "");
}
for (var index = 0; index < pdfPathLstBoth.Count; index++) {
var tgt = Path.Combine(pm.pdfPath, pdfPathLstBoth[index]);
Console.WriteLine($@"tgt={index+1}/{pdfPathLstBoth.Count}:{tgt}");
if (pm.bFC) {
//比較モード
var reff = Path.Combine(pm.pdfPathRef, pdfPathLstBoth[index]);
//Console.WriteLine("<Compare Sync(Paralles) Version!>");
ret = RenderPDF.RenderPdfDocCompare(
pdfPath: Path.GetFullPath(tgt),
refPdfPath: Path.GetFullPath(reff),
resultDataPath: pm.resultPath,
inDir: otDir,
pm: rdCond,
inPageRange: pm.pageRange,
inHashDataTgt: hashDataTgt,
inHashDataRef: hashDataRef,
bPDFium: pm.bPDFium,
nPageThreadNum:pm.paraPage,
bVerify : pm.bVerify
);
} else { // Sync version(Paralles).
ret = RenderPDF.RenderPdfDoc(
pdfPath: Path.GetFullPath(tgt),
inDir: otDir,
pm: rdCond,
inPageRange: pm.pageRange,
bSaveImage: pm.bMkHash ? false : true,// ハッシュ値生成ではイメージ保存しない。
bHash: pm.bHash,// bHash,dumy
inHashData: pm.bMkHash ? hashDataTgt : null, //ハッシュコマンドモードのみDataを渡す
bPDFium: pm.bPDFium,
nPageThreadNum: pm.paraPage
);
}
count--;
GC.Collect();// これでメモリリークが解決した
};
}
if (pm.bMkHash) {
hashDataTgt.save(otHashPath);//ハッシュモードで保存する(Dutyチェックもいるでしょう
}
}
watch.Stop();
Console.WriteLine($"result={ret},time={ watch.ElapsedMilliseconds / 1000.0 }[sec]");
return ret;//success. // 返値 0:OK,!0=不一致Page数
}
// リソースからの取得
public static class ResData {
public static Stream GetBaseHashPDF(string resName = "CSRender.RES.BaseHash.pdf") {
System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
var sel = from x in asm.GetManifestResourceNames() select resName;
if (sel.Count() == 1) {
return asm.GetManifestResourceStream(sel.First());
}
return null;
}
}
}
}
/// <summary>
/// WCF通信モジュールのラッパクラス。
/// 2つのExe間をWCFパイプモードで通信を行う
/// </summary>
namespace xChangeWCFPipe
{
/// シリアライズ可能にすること
/// </summary>
[ServiceContract]
public interface IXData {
[OperationContract(IsOneWay = true)]
void Execute();
[OperationContract]
bool SetMessage(string msg);
[OperationContract]
bool SetProgress(int per);//0-100.
[OperationContract]
HashData GetHashData();
[OperationContract]
void SetHashData(HashData d);
[OperationContract]
CSRenderMain.ParamData GetParam();
//CSRenderMain.Program.ParamData GetParam();
}
// ServiceContract https://tnakamura.hatenablog.com/entry/20080606/1220023868
// https://devlights.hatenablog.com/entry/20111023/p2
/// <summary>
/// 通信用複雑データ。スカラー型(int,double,,,.)以外は[DataCOntract]属性を
/// つけて、通知用Interfaceの引数や、返値で利用する
/// </summary>
[DataContract]
public class DataContainer
{
[DataMember]
public CSRenderMain.ParamData pm;
[DataMember]
public HashData hdata;
}
}
namespace xChangeWCFPipe
{
/// <summary>
/// Main(サーバー)側 データ定義
/// </summary>
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
public class XData : IXData
{
private readonly Object LockObj = new object();// 排他制御用
public delegate void callFunc();
public callFunc callDelegate;
public XData() {
_dc.pm = new CSRenderMain.ParamData();
}
public void Execute() {
lock (LockObj) {
callDelegate(); // 実装はデリゲートします
}
}
public bool SetMessage(string msg) {
lock (LockObj) {
Console.WriteLine($"SVR:called setMessage({msg}) from CLT");
_msg = msg;
}
return true;
}
public bool SetProgress(int per) {//0-100.
lock (LockObj) {
Console.WriteLine($"SVR:called setProgress({per}) from CLT");
_progress = per;
}
return true;
}
public void SetHashData(HashData h) {
lock (LockObj) {
_dc.hdata = h;
}
}
public HashData GetHashData() {
lock (LockObj) {
return _dc.hdata;
}
}
public CSRenderMain.ParamData GetParam() {
lock (LockObj) {
return _dc.pm;
}
}
// クライアントに公開しなくてもよいI/F
public void SetParam(CSRenderMain.ParamData pm) {
lock (LockObj) {
_dc.pm = pm;
}
}
// private data
private string _msg = "init msg";
private int _progress = 0;// 0-100
private DataContainer _dc = new DataContainer();
}
}
namespace xChangeWCFPipeGEN
{
/// <summary>
/// Main(サーバー)側 データ定義
/// </summary>
//[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
//public class XData : IXData
//{
// ...
//}
/// <summary>
/// Main(サーバー)側クラス
/// </summary>
///
public class SVR_T
{
// - static -
/// <summary>
///
/// </summary>
/// <param name="baseIf"> 公開するインターフェースクラス </param>
/// <param name="x">実装インスタンス(baseIfを含むこと)</param>
/// <param name="pipeName"></param>
/// <param name="pipeAddress"></param>
/// <returns></returns>
static public SVR_T makeSVR(Type baseIf, object obj/*XData*/ , string pipeName = "PDFormstudioESorGS", string pipeAddress = "SubModuleAddress") {
Type oType = obj.GetType();
bool hasBaseIf = oType.GetInterfaces().Any(t => (t == baseIf) );
if ( !hasBaseIf) {
Console.WriteLine($@"Error:'{oType.FullName}' have not the interface '{baseIf.FullName}'");//A have not the interface B.
return null;
}
return (new SVR_T(baseIf, obj, pipeName, pipeAddress));
}
// - public I/F -
public void Close() {
echo($"Close Service:{_service != null},{_serviceHost != null}");
_service = null;
_serviceHost.Close();
}
// - private -
private object _service = null;// 要らないかも
private Type _baseIf = null;
private ServiceHost _serviceHost = null;
private SVR_T() { }
private SVR_T(Type baseIf, object oInstance, string pipeName, string pipeAddress) {
const string pipeBase = "net.pipe://localhost";
var uri = pipeBase + "/" + pipeName;
_baseIf = baseIf;
_service = oInstance;
// デリゲート登録
//callDelegate = () => { Console.WriteLine("svr:Delegate func called"); }
_serviceHost = new ServiceHost(_service, new Uri(uri));
try {
_serviceHost.AddServiceEndpoint(_baseIf/*typeof(Ti)*/, new NetNamedPipeBinding(), pipeAddress);
_serviceHost.Open();
} catch (AddressAlreadyInUseException) {
Console.WriteLine("既にサービスは起動しています。");
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
}
/// <summary>
/// Sub(クライアント)側クラス
/// </summary>
public class CLT_T
{
/// <summary>
/// Sub側の初期化処理。Main側とpipeName,pipeAddressを同じにすること
/// </summary>
/// <param name="pipeName"></param>
/// <param name="pipeAddress"></param>
/// <returns></returns>
static public Ti makeCLT<Ti>(string pipeName = "PDFormstudioESorGS", string pipeAddress = "SubModuleAddress") {
const string pipeBase = "net.pipe://localhost";
var address = pipeBase + "/" + pipeName + "/" + pipeAddress;
var factory = (new ChannelFactory<Ti>(new NetNamedPipeBinding(), new EndpointAddress(address)));
Ti toMain = factory.CreateChannel();
return toMain;
}
}
}
namespace Ut
{
public class Ut
{
// Util
// --------------------------------------------------------------
/// <summary>
/// 親プロセスが終了したら、自身を終了させる
/// </summary>
/// <param name="bEnable"></param>
public static void SetAutoSelfKillByMainProcEnd(bool bEnable = true) {
if (_SingletonProc != null)
return;//一度しか呼び出せない
if (bEnable == false)
return;
const string fname = "SetAutoSelfKillByMainProcEnd";
// 自動的に親のプロセスがいなくなったら自動的にキルモードを設定する
// メインプロセスの終了チェック
// 親プロセスIDでProcessハンドルを取得、そのExitedイベントに自身の終了関数を設定(Environment.Exit())
int paProcID = GetParentProcessId();
var paProc = Process.GetProcessById(paProcID);
paProc.EnableRaisingEvents = true;
//Console.WriteLine($@"{fname}:ParrentProcessName ={paProc.ProcessName}({paProcID})");
paProc.Exited += new EventHandler(
(object s, EventArgs a) => {
Console.WriteLine($@"{fname}:Exited Event!!!!");
var ss = s as Process;
Console.WriteLine($@"Sure ProcName is {ss.ProcessName}({ss.Id}) {ss.StartInfo.Arguments}"); ;
System.Threading.Thread.Sleep(10 * 1000);
ss.Close();
ss.Dispose();
Console.WriteLine($@"{fname}:Exited Event!!!!(afer10sec)");
//Environment.Exit(-1);
});
//
_SingletonProc = paProc;
}
private static System.Diagnostics.Process _SingletonProc = null;
/// <summary>
/// コマンドライン引数複数個をエンコードして、スペースで結合
/// </summary>
/// <param name="values">string[] コマンドライン引数</param>
/// <returns>コマンドライン文字列(Escaped)</returns>
public static string makeCmdLine(IEnumerable<string> args) {
if (args == null)
throw new ArgumentNullException("args");
string EscapeCmdLineArg(string v) {
if (string.IsNullOrEmpty(v)) return "";
var containsSpace = v.IndexOfAny(new[] { ' ', '\t' }) != -1;
v = ReCommandLineEscapePattern.Replace(v, @"$1\$&");//「\…\"」をエスケープ.「"」直前の「\」の数を 2倍+1
if (containsSpace) {
v = "\"" + ReLastBackSlashPattern.Replace(v, "$1$1") + "\"";
}
return v;
}
return string.Join(" ", args.Select(v => EscapeCmdLineArg(v)));
}
private static Regex ReCommandLineEscapePattern = new Regex("(\\\\*)\"");
private static Regex ReLastBackSlashPattern = new Regex(@"(\\+)$");
/// <summary>
/// 親のプロセスIDを取得する
/// </summary>
/// <returns>親ProcessID</returns>
static int GetParentProcessId() {
var myProcId = GetCurrentProcessId();
var query = string.Format($@"SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = {myProcId}");
//クエリから結果を取得
using (var search = new System.Management.ManagementObjectSearcher(@"root\CIMV2", query))
using (var results = search.Get().GetEnumerator()) {
if (!results.MoveNext())
throw new ApplicationException("Couldn't Get ParrentProcessId.");
var queryResult = results.Current;
//親プロセスのPIDを取得
uint pa = (uint)(queryResult["ParentProcessId"]);
return (int)(pa);
}
}
/// <summary>
/// 自身のプロセスIDを取得する
/// </summary>
/// <returns>ProcessID</returns>
static int GetCurrentProcessId() { return Process.GetCurrentProcess().Id; }
/// <summary>
/// 外部プログラムを起動する
/// </summary>
/// <param name="cmdAndArgs">引数文字列の配列</param>
/// <param name="bSameConsole">true:コンソールを呼び出しと共有 false:別Console Windows</param>
/// <param name="bEcho">標準出力(未実装)</param>
/// <param name="bWait">コマンドが終了するまで待つ(false:未実装,常に待つ)</param>
/// <param name="nWaitLimitMSec">タイムアウト時間ms(未実装)</param>
/// <returns></returns>
public static Process DoCmd(IEnumerable<string> cmdAndArgs, bool bSameConsole = true, bool bEcho = true, bool bWait = false, int nWaitLimitMSec = -1) {
var cmdName = cmdAndArgs.First();//[0];
var argStr = makeCmdLine(cmdAndArgs.Skip(1));
// 先頭を除外してコピー new ArraySegment<string>(cmdAndArgs.ToArray(), 1, cmdAndArgs.Count()-1)
//Console.WriteLine($@"DoCmd:{cmdName}:args[{argStr}]");
//using (var p = new Process()) {
var p = new Process();
{
var info = p.StartInfo;
p.StartInfo.FileName = cmdName;
p.StartInfo.Arguments = argStr;
if (bSameConsole) {
//Console.WriteLine("Same windows mode");
p.StartInfo.UseShellExecute = false; // Shell経由で実行しない(必須) true: 別ウインドウ。false:コンソールを共有
p.StartInfo.CreateNoWindow = false; // ウィンドウを作成しない
} else {
//Console.WriteLine("New windows mode");
p.StartInfo.UseShellExecute = true;
p.StartInfo.CreateNoWindow = true;
}
p.Start();// 実行
if (bWait == false) {
return p;
}
if (nWaitLimitMSec == -1) {
p.WaitForExit();// タイムアウト無し
} else {
bool bExit = p.WaitForExit(nWaitLimitMSec);
if (!bExit) {// 処理の終了を待つ
Console.WriteLine("処理が終了しないので強制終了");
p.Kill(); // 強制終了する
return p;
}
}
return p;
}
}
}
}
\ No newline at end of file
using System.Resources;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。
// アセンブリに関連付けられている情報を変更するには、
// これらの属性値を変更してください。
[assembly: AssemblyTitle("CSRender")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CSRender")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// ComVisible を false に設定すると、このアセンブリ内の型は COM コンポーネントから
// 参照できなくなります。COM からこのアセンブリ内の型にアクセスする必要がある場合は、
// その型の ComVisible 属性を true に設定してください。
[assembly: ComVisible(false)]
// このプロジェクトが COM に公開される場合、次の GUID が typelib の ID になります
[assembly: Guid("fd99efaa-2479-4e3b-bd1a-5b785288e3b3")]
// アセンブリのバージョン情報は次の 4 つの値で構成されています:
//
// メジャー バージョン
// マイナー バージョン
// ビルド番号
// Revision
//
// すべての値を指定するか、次を使用してビルド番号とリビジョン番号を既定に設定できます
// 既定値にすることができます:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.3.2.0")]
[assembly: AssemblyFileVersion("1.3.2.0")]
[assembly: NeutralResourcesLanguage("ja")]
// rev:1.3.2.0:2021/12/20 :aRGB4チャンネル保存からRGB3チャンネルに変更
// rev:1.3.1.0:2021/10/05 :不要コード削除(Windows.Data.pdf)
// rev:1.3.0.5:2021/09/14 :/Paraで並行プロセス最大値の設定追加
// rev:1.3.0.4:2021/04/29 :Helpの記述抜け "/Result"の対応
// rev:1.3.0.3:2020/11/22 :/Result <比較結果> を実装。diff画像を出力
// rev:1.3.0.2: streamのフラッシュミス 比較時に差異があるとクラッシュしていた。
//------------------------------------------------------------------------------
// <auto-generated>
// このコードはツールによって生成されました。
// ランタイム バージョン:4.0.30319.42000
//
// このファイルへの変更は、以下の状況下で不正な動作の原因になったり、
// コードが再生成されるときに損失したりします。
// </auto-generated>
//------------------------------------------------------------------------------
namespace CSRender.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
</SettingsFile>
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using Windows.Data.Pdf;
// https://water2litter.net/rum/post/cs_pdf_wpf/
namespace CSRender {
class Program {
static void Main(string[] args) {
//static async Task Main(string[] args) {// おまじない awaitが書けるようになる C# 7.1からじゃないと書けない
Task<uint> t = pdfcall("abc");
uint t2 = t.Result;// スレッドの終了まで「待つ」
// asyncメソッド内では await呼び出しができる。ここはasyncではない。
Task<int> task = Task.Run<int>(new Func<int>(Calculate));
int result = task.Result; // スレッドの終了まで「待つ」
Console.WriteLine("result="+t2);
}
public static async Task<uint> pdfcall (string args) {
var path = @"C:\UserData\GIT_JSH\WinRT\CSRender\CSRender\DMFixS.pdf";
var pathOT = @"C:\UserData\GIT_JSH\WinRT\CSRender\CSRender\DMFixS.jpg";
// int result2 = await Task.Run<int>(new Func<int>(Calculate)); // awaitはasyncメソッド内からかける
var file = await Windows.Storage.StorageFile.GetFileFromPathAsync(path);
//Windows.Data.Pdf.PdfDocument pdfDocument;
// PDFファイルを読み込む
var pdfDoc = await Windows.Data.Pdf.PdfDocument.LoadFromFileAsync(file);
var n = pdfDoc.PageCount;
Console.WriteLine("PageNum="+ n);
if (pdfDoc != null) {
// 1ページ目を読み込む
for ( uint i = 0; i < n; i++ ) {
using (Windows.Data.Pdf.PdfPage page = pdfDoc.GetPage(i)) {
BitmapImage image = new BitmapImage();
using (var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream()) {
await page.RenderToStreamAsync(stream);
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.StreamSource = stream.AsStream();
image.EndInit();
// xamlへの返却 imgPdf.Source = image;
// 画像BitmapImageの画像への保存 https://yoshiiz.blog.fc2.com/blog-entry-818.html
// JPEG Q https://docs.microsoft.com/ja-jp/dotnet/framework/winforms/advanced/how-to-set-jpeg-compression-level
// https://water2litter.net/gin/?p=979
BitmapEncoder enc = new JpegBitmapEncoder();
if (enc != null) {
enc.Frames.Add(BitmapFrame.Create(image));
var p = pathOT + "."+ i + ".jpeg";
using (FileStream fs =
new FileStream(p, System.IO.FileMode.Create)) {
enc.Save(fs);
}
}
}
}
}
}
return 0;
}
private static int Calculate() {
int total = 0;
for (int i = 1; i <= 100; ++i)
total += i;
Thread.Sleep(4560); // 何か重い処理をしている...
return total;
}
}
}
/*
- c# acync await
https://qiita.com/rawr/items/5d49960a4e4d3823722f
https://qiita.com/4_mio_11/items/f9b19c04509328b1e5c1
https://tech-lab.sios.jp/archives/15711
http://www.ifelse.jp/blog/csharp-01
async定義内で重い処理を直接記載せずに
await Task<string>.Run(() => {} で呼び出す。重い通常関数を呼び出すとメインスレッドで動いてしまう(だめなわけじゃない)
*/
/*
csc
/r:C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Runtime.WindowsRuntime\v4.0_4.0.0.0__b77a5c561934e089\system.runtime.windowsruntime.dll
/r:C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Runtime.InteropServices.WindowsRuntime\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Runtime.InteropServices.WindowsRuntime.dll
/r:C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Runtime\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Runtime.dll
/r:C:\Program Files (x86)\Windows Kits\8.1\References\CommonConfiguration\Neutral\Annotated\Windows.winmd"
*/
/*
*
C:\Program Files (x86)\Common Files\Microsoft Shared\Phone Tools\12.0\Debugger\target\armv4i\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Common Files\Microsoft Shared\Phone Tools\12.0\Debugger\target\x64\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Common Files\Microsoft Shared\Phone Tools\12.0\Debugger\target\x86\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\System.Runtime.WindowsRuntime\4.0.0\ref\dotnet\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\System.Runtime.WindowsRuntime\4.0.0\ref\netcore50\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\System.Runtime.WindowsRuntime\4.0.10\lib\netcore50\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\System.Runtime.WindowsRuntime\4.0.10\ref\dotnet\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\System.Runtime.WindowsRuntime\4.0.10\ref\netcore50\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\System.Runtime.WindowsRuntime\4.0.10\runtimes\win8-aot\lib\netcore50\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\System.Runtime.WindowsRuntime\4.0.11\ref\netcore50\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\System.Runtime.WindowsRuntime\4.0.11\ref\netstandard1.0\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\System.Runtime.WindowsRuntime\4.0.11\ref\netstandard1.2\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\System.Runtime.WindowsRuntime\4.0.11\runtimes\win8\lib\netstandard1.3\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\System.Runtime.WindowsRuntime\4.0.11\runtimes\win8-aot\lib\netcore50\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\UWPNuGetPackages\microsoft.netcore.universalwindowsplatform\6.2.8\ref\uap10.0.15138\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\UWPNuGetPackages\runtime.win10-arm-aot.microsoft.netcore.universalwindowsplatform\6.2.8\runtimes\win10-arm-aot\lib\uap10.0.15138\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\UWPNuGetPackages\runtime.win10-arm.microsoft.netcore.universalwindowsplatform\6.2.8\runtimes\win10-arm\lib\uap10.0.15138\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\UWPNuGetPackages\runtime.win10-arm64-aot.microsoft.netcore.universalwindowsplatform\6.2.8\runtimes\win10-arm64-aot\lib\uap10.0.15138\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\UWPNuGetPackages\runtime.win10-x64-aot.microsoft.netcore.universalwindowsplatform\6.2.8\runtimes\win10-x64-aot\lib\uap10.0.15138\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\UWPNuGetPackages\runtime.win10-x64.microsoft.netcore.universalwindowsplatform\6.2.8\runtimes\win10-x64\lib\uap10.0.15138\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\UWPNuGetPackages\runtime.win10-x86-aot.microsoft.netcore.universalwindowsplatform\6.2.8\runtimes\win10-x86-aot\lib\uap10.0.15138\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\UWPNuGetPackages\runtime.win10-x86.microsoft.netcore.universalwindowsplatform\6.2.8\runtimes\win10-x86\lib\uap10.0.15138\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\UWPNuGetPackages\system.runtime.windowsruntime\4.0.11\ref\netcore50\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\UWPNuGetPackages\system.runtime.windowsruntime\4.0.11\ref\netstandard1.0\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\UWPNuGetPackages\system.runtime.windowsruntime\4.0.11\ref\netstandard1.2\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\UWPNuGetPackages\system.runtime.windowsruntime\4.0.11\runtimes\win8\lib\netstandard1.3\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\UWPNuGetPackages\system.runtime.windowsruntime\4.0.11\runtimes\win8-aot\lib\netcore50\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\CoreCon\Binaries\Phone Tools\Debugger\CoreClr\arm\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\CoreCon\Binaries\Phone Tools\Debugger\CoreClr\x64\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\CoreCon\Binaries\Phone Tools\Debugger\CoreClr\x86\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\MSBuild\15.0\.Net\.NetNative\15.0.24211\arm\ilc\lib\IL\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\MSBuild\15.0\.Net\.NetNative\15.0.24211\x64\ilc\lib\IL\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\MSBuild\15.0\.Net\.NetNative\15.0.24211\x86\ilc\lib\IL\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.6\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.6\Profile\Profile157\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.6\Profile\Profile31\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.6\Profile\Profile32\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.6\Profile\Profile84\System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Microsoft SDKs\Portable\v15.0\0A8F3DD1C770E53724F799E57E75D39F\Windows.winmd
C:\Program Files (x86)\Microsoft SDKs\Portable\v15.0\0FE9E5AACA0873FDBCECE822A2135C3F\Windows.winmd
C:\Program Files (x86)\Microsoft SDKs\Portable\v15.0\110C4FEFF2BA61C0746933A9ED6E248D\Windows.winmd
C:\Program Files (x86)\Microsoft SDKs\Portable\v15.0\4F245765A3BC2FFB2FCA74D0A384EE09\Windows.winmd
C:\Program Files (x86)\Microsoft SDKs\Portable\v15.0\98FF9529F88911B8A9EFFCFD680FB5E2\Windows.winmd
C:\Program Files (x86)\Microsoft SDKs\Portable\v15.0\995C822CECFC2DAF9C422F1163AC0C56\Windows.winmd
C:\Program Files (x86)\Microsoft SDKs\Portable\v15.0\B727BC5D12E82EC7B31D15CAA5DDCD7F\Windows.winmd
C:\Program Files (x86)\Microsoft SDKs\Portable\v15.0\C708A3C25FEC55584D6D5DE2005C5D87\Windows.winmd
C:\Program Files (x86)\Microsoft SDKs\Portable\v15.0\DE67B807C1D6DC71A27759244863737D\Windows.winmd
C:\Program Files (x86)\Microsoft SDKs\Portable\v15.0\E1E06A90F331A0C3A74EA7B17B6060F8\Windows.winmd
C:\Program Files (x86)\Microsoft SDKs\Portable\v15.0\E938E5A54A55B05FF73E5364149CF7CC\Windows.winmd
C:\Program Files (x86)\Microsoft SDKs\Windows Kits\10\ExtensionSDKs\CppUnitTestFramework.Universal\15.0\Redist\CommonConfiguration\neutral\CppUnitTestFramework_Executor_WindowsPhone.winmd
C:\Program Files (x86)\Microsoft SDKs\Windows Kits\10\ExtensionSDKs\CppUnitTestFramework.Universal\15.0\References\CommonConfiguration\neutral\Microsoft.VisualStudio.TestPlatform.TestExecutor.WinRTCore.winmd
C:\Program Files (x86)\Microsoft SDKs\Windows Kits\10\ExtensionSDKs\CppUnitTestFramework.Universal\15.5\Redist\CommonConfiguration\neutral\CppUnitTestFramework_Executor_WindowsPhone.winmd
C:\Program Files (x86)\Microsoft SDKs\Windows Kits\10\ExtensionSDKs\CppUnitTestFramework.Universal\15.5\References\CommonConfiguration\neutral\Microsoft.VisualStudio.TestPlatform.TestExecutor.WinRTCore.winmd
C:\Program Files (x86)\Microsoft SDKs\Windows Kits\10\ExtensionSDKs\TestPlatform.Universal\15.0\Redist\CommonConfiguration\neutral\vstest_executionengine_platformbridge.winmd
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\VC\vcpackages\platform.winmd
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023\lib\x86\store\references\platform.winmd
C:\Program Files (x86)\Windows Kits\10\App Certification Kit\winmds\windows8\Windows.winmd
C:\Program Files (x86)\Windows Kits\10\App Certification Kit\winmds\windows81\Windows.winmd
C:\Program Files (x86)\Windows Kits\10\App Certification Kit\winmds\windowsKinect2\WindowsPreview.Data.winmd
C:\Program Files (x86)\Windows Kits\10\App Certification Kit\winmds\windowsKinect2\WindowsPreview.Kinect.winmd
C:\Program Files (x86)\Windows Kits\10\App Certification Kit\winmds\windowsPlayready8\Microsoft.Media.PlayReadyClient.winmd
C:\Program Files (x86)\Windows Kits\10\App Certification Kit\winmds\windowsPlayready81\Microsoft.Media.PlayReadyClient.winmd
C:\Program Files (x86)\Windows Kits\10\App Certification Kit\winmds\winphone81\Windows.winmd
C:\Program Files (x86)\Windows Kits\10\App Certification Kit\winmds\winphonePlayready81\Microsoft.Media.PlayReadyClient.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.15063.0\arm\AppAnalysis\Microsoft.Diagnostics.AppAnalysis.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.15063.0\arm64\AppAnalysis\Microsoft.Diagnostics.AppAnalysis.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.15063.0\x64\AppAnalysis\Microsoft.Diagnostics.AppAnalysis.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.15063.0\x86\AppAnalysis\Microsoft.Diagnostics.AppAnalysis.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.16299.0\arm\AppAnalysis\Microsoft.Diagnostics.AppAnalysis.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.16299.0\arm64\AppAnalysis\Microsoft.Diagnostics.AppAnalysis.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.16299.0\x64\AppAnalysis\Microsoft.Diagnostics.AppAnalysis.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.16299.0\x86\AppAnalysis\Microsoft.Diagnostics.AppAnalysis.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\arm\AppAnalysis\Microsoft.Diagnostics.AppAnalysis.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\arm64\AppAnalysis\Microsoft.Diagnostics.AppAnalysis.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x64\AppAnalysis\Microsoft.Diagnostics.AppAnalysis.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x86\AppAnalysis\Microsoft.Diagnostics.AppAnalysis.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\XamlCompiler\Microsoft.UI.Xaml.Markup.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\arm\AppAnalysis\Microsoft.Diagnostics.AppAnalysis.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\arm64\AppAnalysis\Microsoft.Diagnostics.AppAnalysis.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64\AppAnalysis\Microsoft.Diagnostics.AppAnalysis.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x86\AppAnalysis\Microsoft.Diagnostics.AppAnalysis.winmd
C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\XamlCompiler\Microsoft.UI.Xaml.Markup.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.Activation.ActivatedEventsContract\1.0.0.0\Windows.ApplicationModel.Activation.ActivatedEventsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.Activation.ActivationCameraSettingsContract\1.0.0.0\Windows.ApplicationModel.Activation.ActivationCameraSettingsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.Activation.ContactActivatedEventsContract\1.0.0.0\Windows.ApplicationModel.Activation.ContactActivatedEventsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.Activation.WebUISearchActivatedEventsContract\1.0.0.0\Windows.ApplicationModel.Activation.WebUISearchActivatedEventsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.Background.BackgroundAlarmApplicationContract\1.0.0.0\Windows.ApplicationModel.Background.BackgroundAlarmApplicationContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.Calls.Background.CallsBackgroundContract\1.0.0.0\Windows.ApplicationModel.Calls.Background.CallsBackgroundContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.Calls.CallsPhoneContract\3.0.0.0\Windows.ApplicationModel.Calls.CallsPhoneContract.WinMD
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.Calls.CallsVoipContract\1.0.0.0\Windows.ApplicationModel.Calls.CallsVoipContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.Calls.LockScreenCallContract\1.0.0.0\Windows.ApplicationModel.Calls.LockScreenCallContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.CommunicationBlocking.CommunicationBlockingContract\2.0.0.0\Windows.ApplicationModel.CommunicationBlocking.CommunicationBlockingContract.WinMD
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.FullTrustAppContract\1.0.0.0\Windows.ApplicationModel.FullTrustAppContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.Preview.InkWorkspace.PreviewInkWorkspaceContract\1.0.0.0\Windows.ApplicationModel.Preview.InkWorkspace.PreviewInkWorkspaceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.Preview.Notes.PreviewNotesContract\2.0.0.0\Windows.ApplicationModel.Preview.Notes.PreviewNotesContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.Resources.Management.ResourceIndexerContract\1.0.0.0\Windows.ApplicationModel.Resources.Management.ResourceIndexerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.Search.Core.SearchCoreContract\1.0.0.0\Windows.ApplicationModel.Search.Core.SearchCoreContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.Search.SearchContract\1.0.0.0\Windows.ApplicationModel.Search.SearchContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.SocialInfo.SocialInfoContract\2.0.0.0\Windows.ApplicationModel.SocialInfo.SocialInfoContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.StartupTaskContract\1.0.0.0\Windows.ApplicationModel.StartupTaskContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.ApplicationModel.Wallet.WalletContract\1.0.0.0\Windows.ApplicationModel.Wallet.WalletContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Devices.Custom.CustomDeviceContract\1.0.0.0\Windows.Devices.Custom.CustomDeviceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Devices.DevicesLowLevelContract\3.0.0.0\Windows.Devices.DevicesLowLevelContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Devices.Portable.PortableDeviceContract\1.0.0.0\Windows.Devices.Portable.PortableDeviceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Devices.Printers.Extensions.ExtensionsContract\2.0.0.0\Windows.Devices.Printers.Extensions.ExtensionsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Devices.Printers.PrintersContract\1.0.0.0\Windows.Devices.Printers.PrintersContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Devices.Scanners.ScannerDeviceContract\1.0.0.0\Windows.Devices.Scanners.ScannerDeviceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Devices.SmartCards.SmartCardBackgroundTriggerContract\3.0.0.0\Windows.Devices.SmartCards.SmartCardBackgroundTriggerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Devices.SmartCards.SmartCardEmulatorContract\4.0.0.0\Windows.Devices.SmartCards.SmartCardEmulatorContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Devices.Sms.LegacySmsApiContract\1.0.0.0\Windows.Devices.Sms.LegacySmsApiContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Embedded.DeviceLockdown.DeviceLockdownContract\1.0.0.0\Windows.Embedded.DeviceLockdown.DeviceLockdownContract.WinMD
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Foundation.UniversalApiContract\4.0.0.0\Windows.Foundation.UniversalApiContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Gaming.Input.GamingInputPreviewContract\1.0.0.0\Windows.Gaming.Input.GamingInputPreviewContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Gaming.Preview.GamesEnumerationContract\1.0.0.0\Windows.Gaming.Preview.GamesEnumerationContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Gaming.UI.GameChatOverlayContract\1.0.0.0\Windows.Gaming.UI.GameChatOverlayContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Globalization.GlobalizationJapanesePhoneticAnalyzerContract\1.0.0.0\Windows.Globalization.GlobalizationJapanesePhoneticAnalyzerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Graphics.Printing3D.Printing3DContract\3.0.0.0\Windows.Graphics.Printing3D.Printing3DContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Management.Deployment.Preview.DeploymentPreviewContract\1.0.0.0\Windows.Management.Deployment.Preview.DeploymentPreviewContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Management.Workplace.WorkplaceSettingsContract\1.0.0.0\Windows.Management.Workplace.WorkplaceSettingsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Media.Capture.AppBroadcastContract\1.0.0.0\Windows.Media.Capture.AppBroadcastContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Media.Capture.AppCaptureContract\4.0.0.0\Windows.Media.Capture.AppCaptureContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Media.Capture.CameraCaptureUIContract\1.0.0.0\Windows.Media.Capture.CameraCaptureUIContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Media.Capture.GameBarContract\1.0.0.0\Windows.Media.Capture.GameBarContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Media.Devices.CallControlContract\1.0.0.0\Windows.Media.Devices.CallControlContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Media.MediaControlContract\1.0.0.0\Windows.Media.MediaControlContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Media.Playlists.PlaylistsContract\1.0.0.0\Windows.Media.Playlists.PlaylistsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Media.Protection.ProtectionRenewalContract\1.0.0.0\Windows.Media.Protection.ProtectionRenewalContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Networking.Connectivity.WwanContract\1.0.0.0\Windows.Networking.Connectivity.WwanContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Networking.NetworkOperators.LegacyNetworkOperatorsContract\1.0.0.0\Windows.Networking.NetworkOperators.LegacyNetworkOperatorsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Networking.NetworkOperators.NetworkOperatorsFdnContract\1.0.0.0\Windows.Networking.NetworkOperators.NetworkOperatorsFdnContract.WinMD
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Networking.Sockets.ControlChannelTriggerContract\2.0.0.0\Windows.Networking.Sockets.ControlChannelTriggerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Perception.Automation.Core.PerceptionAutomationCoreContract\1.0.0.0\Windows.Perception.Automation.Core.PerceptionAutomationCoreContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Phone.PhoneContract\1.0.0.0\Windows.Phone.PhoneContract.WinMD
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Phone.StartScreen.DualSimTileContract\1.0.0.0\Windows.Phone.StartScreen.DualSimTileContract.WinMD
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Security.EnterpriseData.EnterpriseDataContract\4.0.0.0\Windows.Security.EnterpriseData.EnterpriseDataContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Security.ExchangeActiveSyncProvisioning.EasContract\1.0.0.0\Windows.Security.ExchangeActiveSyncProvisioning.EasContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Services.Maps.GuidanceContract\2.0.0.0\Windows.Services.Maps.GuidanceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Services.Maps.LocalSearchContract\3.0.0.0\Windows.Services.Maps.LocalSearchContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Services.Store.StoreContract\2.0.0.0\Windows.Services.Store.StoreContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Services.TargetedContent.TargetedContentContract\1.0.0.0\Windows.Services.TargetedContent.TargetedContentContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.System.Profile.ProfileHardwareTokenContract\1.0.0.0\Windows.System.Profile.ProfileHardwareTokenContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.System.Profile.ProfileRetailInfoContract\1.0.0.0\Windows.System.Profile.ProfileRetailInfoContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.System.Profile.ProfileSharedModeContract\2.0.0.0\Windows.System.Profile.ProfileSharedModeContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.System.Profile.SystemManufacturers.SystemManufacturersContract\1.0.0.0\Windows.System.Profile.SystemManufacturers.SystemManufacturersContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.System.SystemManagementContract\3.0.0.0\Windows.System.SystemManagementContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.System.UserProfile.UserProfileContract\1.0.0.0\Windows.System.UserProfile.UserProfileContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.System.UserProfile.UserProfileLockScreenContract\1.0.0.0\Windows.System.UserProfile.UserProfileLockScreenContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.UI.ApplicationSettings.ApplicationsSettingsContract\1.0.0.0\Windows.UI.ApplicationSettings.ApplicationsSettingsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.UI.Core.AnimationMetrics.AnimationMetricsContract\1.0.0.0\Windows.UI.Core.AnimationMetrics.AnimationMetricsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.UI.Core.CoreWindowDialogsContract\1.0.0.0\Windows.UI.Core.CoreWindowDialogsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.UI.ViewManagement.ViewManagementViewScalingContract\1.0.0.0\Windows.UI.ViewManagement.ViewManagementViewScalingContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.UI.WebUI.Core.WebUICommandBarContract\1.0.0.0\Windows.UI.WebUI.Core.WebUICommandBarContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.UI.Xaml.Hosting.HostingContract\1.0.0.0\Windows.UI.Xaml.Hosting.HostingContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Web.Http.Diagnostics.HttpDiagnosticsContract\2.0.0.0\Windows.Web.Http.Diagnostics.HttpDiagnosticsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.Activation.ActivatedEventsContract\1.0.0.0\Windows.ApplicationModel.Activation.ActivatedEventsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.Activation.ActivationCameraSettingsContract\1.0.0.0\Windows.ApplicationModel.Activation.ActivationCameraSettingsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.Activation.ContactActivatedEventsContract\1.0.0.0\Windows.ApplicationModel.Activation.ContactActivatedEventsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.Activation.WebUISearchActivatedEventsContract\1.0.0.0\Windows.ApplicationModel.Activation.WebUISearchActivatedEventsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.Background.BackgroundAlarmApplicationContract\1.0.0.0\Windows.ApplicationModel.Background.BackgroundAlarmApplicationContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.Calls.Background.CallsBackgroundContract\1.0.0.0\Windows.ApplicationModel.Calls.Background.CallsBackgroundContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.Calls.CallsPhoneContract\3.0.0.0\Windows.ApplicationModel.Calls.CallsPhoneContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.Calls.CallsVoipContract\2.0.0.0\Windows.ApplicationModel.Calls.CallsVoipContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.Calls.LockScreenCallContract\1.0.0.0\Windows.ApplicationModel.Calls.LockScreenCallContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.CommunicationBlocking.CommunicationBlockingContract\2.0.0.0\Windows.ApplicationModel.CommunicationBlocking.CommunicationBlockingContract.WinMD
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.FullTrustAppContract\1.0.0.0\Windows.ApplicationModel.FullTrustAppContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.Preview.InkWorkspace.PreviewInkWorkspaceContract\1.0.0.0\Windows.ApplicationModel.Preview.InkWorkspace.PreviewInkWorkspaceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.Preview.Notes.PreviewNotesContract\2.0.0.0\Windows.ApplicationModel.Preview.Notes.PreviewNotesContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.Resources.Management.ResourceIndexerContract\1.0.0.0\Windows.ApplicationModel.Resources.Management.ResourceIndexerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.Search.Core.SearchCoreContract\1.0.0.0\Windows.ApplicationModel.Search.Core.SearchCoreContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.Search.SearchContract\1.0.0.0\Windows.ApplicationModel.Search.SearchContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.SocialInfo.SocialInfoContract\2.0.0.0\Windows.ApplicationModel.SocialInfo.SocialInfoContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.StartupTaskContract\2.0.0.0\Windows.ApplicationModel.StartupTaskContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.Wallet.WalletContract\1.0.0.0\Windows.ApplicationModel.Wallet.WalletContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Devices.Custom.CustomDeviceContract\1.0.0.0\Windows.Devices.Custom.CustomDeviceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Devices.DevicesLowLevelContract\3.0.0.0\Windows.Devices.DevicesLowLevelContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Devices.Portable.PortableDeviceContract\1.0.0.0\Windows.Devices.Portable.PortableDeviceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Devices.Printers.Extensions.ExtensionsContract\2.0.0.0\Windows.Devices.Printers.Extensions.ExtensionsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Devices.Printers.PrintersContract\1.0.0.0\Windows.Devices.Printers.PrintersContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Devices.Scanners.ScannerDeviceContract\1.0.0.0\Windows.Devices.Scanners.ScannerDeviceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Devices.SmartCards.SmartCardBackgroundTriggerContract\3.0.0.0\Windows.Devices.SmartCards.SmartCardBackgroundTriggerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Devices.SmartCards.SmartCardEmulatorContract\5.0.0.0\Windows.Devices.SmartCards.SmartCardEmulatorContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Devices.Sms.LegacySmsApiContract\1.0.0.0\Windows.Devices.Sms.LegacySmsApiContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Embedded.DeviceLockdown.DeviceLockdownContract\1.0.0.0\Windows.Embedded.DeviceLockdown.DeviceLockdownContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Foundation.UniversalApiContract\5.0.0.0\Windows.Foundation.UniversalApiContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Gaming.Input.GamingInputPreviewContract\1.0.0.0\Windows.Gaming.Input.GamingInputPreviewContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Gaming.Preview.GamesEnumerationContract\2.0.0.0\Windows.Gaming.Preview.GamesEnumerationContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Gaming.UI.GameChatOverlayContract\1.0.0.0\Windows.Gaming.UI.GameChatOverlayContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Gaming.UI.GamingUIProviderContract\1.0.0.0\Windows.Gaming.UI.GamingUIProviderContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Gaming.XboxLive.StorageApiContract\1.0.0.0\Windows.Gaming.XboxLive.StorageApiContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Globalization.GlobalizationJapanesePhoneticAnalyzerContract\1.0.0.0\Windows.Globalization.GlobalizationJapanesePhoneticAnalyzerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Graphics.Printing3D.Printing3DContract\4.0.0.0\Windows.Graphics.Printing3D.Printing3DContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Management.Deployment.Preview.DeploymentPreviewContract\1.0.0.0\Windows.Management.Deployment.Preview.DeploymentPreviewContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Management.Workplace.WorkplaceSettingsContract\1.0.0.0\Windows.Management.Workplace.WorkplaceSettingsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Media.AppBroadcasting.AppBroadcastingContract\1.0.0.0\Windows.Media.AppBroadcasting.AppBroadcastingContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Media.AppRecording.AppRecordingContract\1.0.0.0\Windows.Media.AppRecording.AppRecordingContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Media.Capture.AppBroadcastContract\2.0.0.0\Windows.Media.Capture.AppBroadcastContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Media.Capture.AppCaptureContract\4.0.0.0\Windows.Media.Capture.AppCaptureContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Media.Capture.AppCaptureMetadataContract\1.0.0.0\Windows.Media.Capture.AppCaptureMetadataContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Media.Capture.CameraCaptureUIContract\1.0.0.0\Windows.Media.Capture.CameraCaptureUIContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Media.Capture.GameBarContract\1.0.0.0\Windows.Media.Capture.GameBarContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Media.Devices.CallControlContract\1.0.0.0\Windows.Media.Devices.CallControlContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Media.MediaControlContract\1.0.0.0\Windows.Media.MediaControlContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Media.Playlists.PlaylistsContract\1.0.0.0\Windows.Media.Playlists.PlaylistsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Media.Protection.ProtectionRenewalContract\1.0.0.0\Windows.Media.Protection.ProtectionRenewalContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Networking.Connectivity.WwanContract\1.0.0.0\Windows.Networking.Connectivity.WwanContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Networking.NetworkOperators.LegacyNetworkOperatorsContract\1.0.0.0\Windows.Networking.NetworkOperators.LegacyNetworkOperatorsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Networking.NetworkOperators.NetworkOperatorsFdnContract\1.0.0.0\Windows.Networking.NetworkOperators.NetworkOperatorsFdnContract.WinMD
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Networking.Sockets.ControlChannelTriggerContract\2.0.0.0\Windows.Networking.Sockets.ControlChannelTriggerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Networking.XboxLive.XboxLiveSecureSocketsContract\1.0.0.0\Windows.Networking.XboxLive.XboxLiveSecureSocketsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Perception.Automation.Core.PerceptionAutomationCoreContract\1.0.0.0\Windows.Perception.Automation.Core.PerceptionAutomationCoreContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Phone.PhoneContract\1.0.0.0\Windows.Phone.PhoneContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Phone.StartScreen.DualSimTileContract\1.0.0.0\Windows.Phone.StartScreen.DualSimTileContract.WinMD
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Security.EnterpriseData.EnterpriseDataContract\5.0.0.0\Windows.Security.EnterpriseData.EnterpriseDataContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Security.ExchangeActiveSyncProvisioning.EasContract\1.0.0.0\Windows.Security.ExchangeActiveSyncProvisioning.EasContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Services.Maps.GuidanceContract\3.0.0.0\Windows.Services.Maps.GuidanceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Services.Maps.LocalSearchContract\4.0.0.0\Windows.Services.Maps.LocalSearchContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Services.Store.StoreContract\2.0.0.0\Windows.Services.Store.StoreContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Services.TargetedContent.TargetedContentContract\1.0.0.0\Windows.Services.TargetedContent.TargetedContentContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Storage.Provider.CloudFilesContract\1.0.0.0\Windows.Storage.Provider.CloudFilesContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.System.Profile.ProfileHardwareTokenContract\1.0.0.0\Windows.System.Profile.ProfileHardwareTokenContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.System.Profile.ProfileRetailInfoContract\1.0.0.0\Windows.System.Profile.ProfileRetailInfoContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.System.Profile.ProfileSharedModeContract\2.0.0.0\Windows.System.Profile.ProfileSharedModeContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.System.Profile.SystemManufacturers.SystemManufacturersContract\2.0.0.0\Windows.System.Profile.SystemManufacturers.SystemManufacturersContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.System.SystemManagementContract\4.0.0.0\Windows.System.SystemManagementContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.System.UserProfile.UserProfileContract\1.0.0.0\Windows.System.UserProfile.UserProfileContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.System.UserProfile.UserProfileLockScreenContract\1.0.0.0\Windows.System.UserProfile.UserProfileLockScreenContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.UI.ApplicationSettings.ApplicationsSettingsContract\1.0.0.0\Windows.UI.ApplicationSettings.ApplicationsSettingsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.UI.Core.AnimationMetrics.AnimationMetricsContract\1.0.0.0\Windows.UI.Core.AnimationMetrics.AnimationMetricsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.UI.Core.CoreWindowDialogsContract\1.0.0.0\Windows.UI.Core.CoreWindowDialogsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.UI.ViewManagement.ViewManagementViewScalingContract\1.0.0.0\Windows.UI.ViewManagement.ViewManagementViewScalingContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.UI.WebUI.Core.WebUICommandBarContract\1.0.0.0\Windows.UI.WebUI.Core.WebUICommandBarContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.UI.Xaml.Hosting.HostingContract\2.0.0.0\Windows.UI.Xaml.Hosting.HostingContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Web.Http.Diagnostics.HttpDiagnosticsContract\2.0.0.0\Windows.Web.Http.Diagnostics.HttpDiagnosticsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.AI.MachineLearning.MachineLearningContract\1.0.0.0\Windows.AI.MachineLearning.MachineLearningContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.AI.MachineLearning.Preview.MachineLearningPreviewContract\2.0.0.0\Windows.AI.MachineLearning.Preview.MachineLearningPreviewContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.Activation.ActivatedEventsContract\1.0.0.0\Windows.ApplicationModel.Activation.ActivatedEventsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.Activation.ActivationCameraSettingsContract\1.0.0.0\Windows.ApplicationModel.Activation.ActivationCameraSettingsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.Activation.ContactActivatedEventsContract\1.0.0.0\Windows.ApplicationModel.Activation.ContactActivatedEventsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.Activation.WebUISearchActivatedEventsContract\1.0.0.0\Windows.ApplicationModel.Activation.WebUISearchActivatedEventsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.Background.BackgroundAlarmApplicationContract\1.0.0.0\Windows.ApplicationModel.Background.BackgroundAlarmApplicationContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.Calls.Background.CallsBackgroundContract\1.0.0.0\Windows.ApplicationModel.Calls.Background.CallsBackgroundContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.Calls.CallsPhoneContract\4.0.0.0\Windows.ApplicationModel.Calls.CallsPhoneContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.Calls.CallsVoipContract\4.0.0.0\Windows.ApplicationModel.Calls.CallsVoipContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.Calls.LockScreenCallContract\1.0.0.0\Windows.ApplicationModel.Calls.LockScreenCallContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.CommunicationBlocking.CommunicationBlockingContract\2.0.0.0\Windows.ApplicationModel.CommunicationBlocking.CommunicationBlockingContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.FullTrustAppContract\1.0.0.0\Windows.ApplicationModel.FullTrustAppContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.Preview.InkWorkspace.PreviewInkWorkspaceContract\1.0.0.0\Windows.ApplicationModel.Preview.InkWorkspace.PreviewInkWorkspaceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.Preview.Notes.PreviewNotesContract\2.0.0.0\Windows.ApplicationModel.Preview.Notes.PreviewNotesContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.Resources.Management.ResourceIndexerContract\2.0.0.0\Windows.ApplicationModel.Resources.Management.ResourceIndexerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.Search.Core.SearchCoreContract\1.0.0.0\Windows.ApplicationModel.Search.Core.SearchCoreContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.Search.SearchContract\1.0.0.0\Windows.ApplicationModel.Search.SearchContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.SocialInfo.SocialInfoContract\2.0.0.0\Windows.ApplicationModel.SocialInfo.SocialInfoContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.StartupTaskContract\3.0.0.0\Windows.ApplicationModel.StartupTaskContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.ApplicationModel.Wallet.WalletContract\1.0.0.0\Windows.ApplicationModel.Wallet.WalletContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Devices.Custom.CustomDeviceContract\1.0.0.0\Windows.Devices.Custom.CustomDeviceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Devices.DevicesLowLevelContract\3.0.0.0\Windows.Devices.DevicesLowLevelContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Devices.Portable.PortableDeviceContract\1.0.0.0\Windows.Devices.Portable.PortableDeviceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Devices.Printers.Extensions.ExtensionsContract\2.0.0.0\Windows.Devices.Printers.Extensions.ExtensionsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Devices.Printers.PrintersContract\1.0.0.0\Windows.Devices.Printers.PrintersContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Devices.Scanners.ScannerDeviceContract\1.0.0.0\Windows.Devices.Scanners.ScannerDeviceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Devices.SmartCards.SmartCardBackgroundTriggerContract\3.0.0.0\Windows.Devices.SmartCards.SmartCardBackgroundTriggerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Devices.SmartCards.SmartCardEmulatorContract\6.0.0.0\Windows.Devices.SmartCards.SmartCardEmulatorContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Devices.Sms.LegacySmsApiContract\1.0.0.0\Windows.Devices.Sms.LegacySmsApiContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Embedded.DeviceLockdown.DeviceLockdownContract\1.0.0.0\Windows.Embedded.DeviceLockdown.DeviceLockdownContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Foundation.UniversalApiContract\7.0.0.0\Windows.Foundation.UniversalApiContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Gaming.Input.GamingInputPreviewContract\1.0.0.0\Windows.Gaming.Input.GamingInputPreviewContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Gaming.Preview.GamesEnumerationContract\2.0.0.0\Windows.Gaming.Preview.GamesEnumerationContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Gaming.UI.GameChatOverlayContract\1.0.0.0\Windows.Gaming.UI.GameChatOverlayContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Gaming.UI.GamingUIProviderContract\1.0.0.0\Windows.Gaming.UI.GamingUIProviderContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Gaming.XboxLive.StorageApiContract\1.0.0.0\Windows.Gaming.XboxLive.StorageApiContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Globalization.GlobalizationJapanesePhoneticAnalyzerContract\1.0.0.0\Windows.Globalization.GlobalizationJapanesePhoneticAnalyzerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Graphics.Printing3D.Printing3DContract\4.0.0.0\Windows.Graphics.Printing3D.Printing3DContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Management.Deployment.Preview.DeploymentPreviewContract\1.0.0.0\Windows.Management.Deployment.Preview.DeploymentPreviewContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Management.Workplace.WorkplaceSettingsContract\1.0.0.0\Windows.Management.Workplace.WorkplaceSettingsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Media.AppBroadcasting.AppBroadcastingContract\1.0.0.0\Windows.Media.AppBroadcasting.AppBroadcastingContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Media.AppRecording.AppRecordingContract\1.0.0.0\Windows.Media.AppRecording.AppRecordingContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Media.Capture.AppBroadcastContract\2.0.0.0\Windows.Media.Capture.AppBroadcastContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Media.Capture.AppCaptureContract\4.0.0.0\Windows.Media.Capture.AppCaptureContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Media.Capture.AppCaptureMetadataContract\1.0.0.0\Windows.Media.Capture.AppCaptureMetadataContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Media.Capture.CameraCaptureUIContract\1.0.0.0\Windows.Media.Capture.CameraCaptureUIContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Media.Capture.GameBarContract\1.0.0.0\Windows.Media.Capture.GameBarContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Media.Devices.CallControlContract\1.0.0.0\Windows.Media.Devices.CallControlContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Media.MediaControlContract\1.0.0.0\Windows.Media.MediaControlContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Media.Playlists.PlaylistsContract\1.0.0.0\Windows.Media.Playlists.PlaylistsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Media.Protection.ProtectionRenewalContract\1.0.0.0\Windows.Media.Protection.ProtectionRenewalContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Networking.Connectivity.WwanContract\2.0.0.0\Windows.Networking.Connectivity.WwanContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Networking.NetworkOperators.LegacyNetworkOperatorsContract\1.0.0.0\Windows.Networking.NetworkOperators.LegacyNetworkOperatorsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Networking.NetworkOperators.NetworkOperatorsFdnContract\1.0.0.0\Windows.Networking.NetworkOperators.NetworkOperatorsFdnContract.WinMD
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Networking.Sockets.ControlChannelTriggerContract\3.0.0.0\Windows.Networking.Sockets.ControlChannelTriggerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Networking.XboxLive.XboxLiveSecureSocketsContract\1.0.0.0\Windows.Networking.XboxLive.XboxLiveSecureSocketsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Perception.Automation.Core.PerceptionAutomationCoreContract\1.0.0.0\Windows.Perception.Automation.Core.PerceptionAutomationCoreContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Phone.PhoneContract\1.0.0.0\Windows.Phone.PhoneContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Phone.StartScreen.DualSimTileContract\1.0.0.0\Windows.Phone.StartScreen.DualSimTileContract.WinMD
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Security.EnterpriseData.EnterpriseDataContract\5.0.0.0\Windows.Security.EnterpriseData.EnterpriseDataContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Security.ExchangeActiveSyncProvisioning.EasContract\1.0.0.0\Windows.Security.ExchangeActiveSyncProvisioning.EasContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Services.Maps.GuidanceContract\3.0.0.0\Windows.Services.Maps.GuidanceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Services.Maps.LocalSearchContract\4.0.0.0\Windows.Services.Maps.LocalSearchContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Services.Store.StoreContract\4.0.0.0\Windows.Services.Store.StoreContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Services.TargetedContent.TargetedContentContract\1.0.0.0\Windows.Services.TargetedContent.TargetedContentContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Storage.Provider.CloudFilesContract\3.0.0.0\Windows.Storage.Provider.CloudFilesContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.System.Profile.ProfileHardwareTokenContract\1.0.0.0\Windows.System.Profile.ProfileHardwareTokenContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.System.Profile.ProfileRetailInfoContract\1.0.0.0\Windows.System.Profile.ProfileRetailInfoContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.System.Profile.ProfileSharedModeContract\2.0.0.0\Windows.System.Profile.ProfileSharedModeContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.System.Profile.SystemManufacturers.SystemManufacturersContract\3.0.0.0\Windows.System.Profile.SystemManufacturers.SystemManufacturersContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.System.SystemManagementContract\6.0.0.0\Windows.System.SystemManagementContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.System.UserProfile.UserProfileContract\2.0.0.0\Windows.System.UserProfile.UserProfileContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.System.UserProfile.UserProfileLockScreenContract\1.0.0.0\Windows.System.UserProfile.UserProfileLockScreenContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.UI.ApplicationSettings.ApplicationsSettingsContract\1.0.0.0\Windows.UI.ApplicationSettings.ApplicationsSettingsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.UI.Core.AnimationMetrics.AnimationMetricsContract\1.0.0.0\Windows.UI.Core.AnimationMetrics.AnimationMetricsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.UI.Core.CoreWindowDialogsContract\1.0.0.0\Windows.UI.Core.CoreWindowDialogsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.UI.Shell.SecurityAppManagerContract\1.0.0.0\Windows.UI.Shell.SecurityAppManagerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.UI.ViewManagement.ViewManagementViewScalingContract\1.0.0.0\Windows.UI.ViewManagement.ViewManagementViewScalingContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.UI.WebUI.Core.WebUICommandBarContract\1.0.0.0\Windows.UI.WebUI.Core.WebUICommandBarContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.UI.Xaml.Core.Direct.XamlDirectContract\1.0.0.0\Windows.UI.Xaml.Core.Direct.XamlDirectContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.UI.Xaml.Hosting.HostingContract\3.0.0.0\Windows.UI.Xaml.Hosting.HostingContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Web.Http.Diagnostics.HttpDiagnosticsContract\2.0.0.0\Windows.Web.Http.Diagnostics.HttpDiagnosticsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.AI.MachineLearning.MachineLearningContract\2.0.0.0\Windows.AI.MachineLearning.MachineLearningContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.AI.MachineLearning.Preview.MachineLearningPreviewContract\2.0.0.0\Windows.AI.MachineLearning.Preview.MachineLearningPreviewContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.Activation.ActivatedEventsContract\1.0.0.0\Windows.ApplicationModel.Activation.ActivatedEventsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.Activation.ActivationCameraSettingsContract\1.0.0.0\Windows.ApplicationModel.Activation.ActivationCameraSettingsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.Activation.ContactActivatedEventsContract\1.0.0.0\Windows.ApplicationModel.Activation.ContactActivatedEventsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.Activation.WebUISearchActivatedEventsContract\1.0.0.0\Windows.ApplicationModel.Activation.WebUISearchActivatedEventsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.Background.BackgroundAlarmApplicationContract\1.0.0.0\Windows.ApplicationModel.Background.BackgroundAlarmApplicationContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.Calls.Background.CallsBackgroundContract\2.0.0.0\Windows.ApplicationModel.Calls.Background.CallsBackgroundContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.Calls.CallsPhoneContract\5.0.0.0\Windows.ApplicationModel.Calls.CallsPhoneContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.Calls.CallsVoipContract\4.0.0.0\Windows.ApplicationModel.Calls.CallsVoipContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.Calls.LockScreenCallContract\1.0.0.0\Windows.ApplicationModel.Calls.LockScreenCallContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.CommunicationBlocking.CommunicationBlockingContract\2.0.0.0\Windows.ApplicationModel.CommunicationBlocking.CommunicationBlockingContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.FullTrustAppContract\1.0.0.0\Windows.ApplicationModel.FullTrustAppContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.Preview.InkWorkspace.PreviewInkWorkspaceContract\1.0.0.0\Windows.ApplicationModel.Preview.InkWorkspace.PreviewInkWorkspaceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.Preview.Notes.PreviewNotesContract\2.0.0.0\Windows.ApplicationModel.Preview.Notes.PreviewNotesContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.Resources.Management.ResourceIndexerContract\2.0.0.0\Windows.ApplicationModel.Resources.Management.ResourceIndexerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.Search.Core.SearchCoreContract\1.0.0.0\Windows.ApplicationModel.Search.Core.SearchCoreContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.Search.SearchContract\1.0.0.0\Windows.ApplicationModel.Search.SearchContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.SocialInfo.SocialInfoContract\2.0.0.0\Windows.ApplicationModel.SocialInfo.SocialInfoContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.StartupTaskContract\3.0.0.0\Windows.ApplicationModel.StartupTaskContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.ApplicationModel.Wallet.WalletContract\1.0.0.0\Windows.ApplicationModel.Wallet.WalletContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Devices.Custom.CustomDeviceContract\1.0.0.0\Windows.Devices.Custom.CustomDeviceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Devices.DevicesLowLevelContract\3.0.0.0\Windows.Devices.DevicesLowLevelContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Devices.Portable.PortableDeviceContract\1.0.0.0\Windows.Devices.Portable.PortableDeviceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Devices.Printers.Extensions.ExtensionsContract\2.0.0.0\Windows.Devices.Printers.Extensions.ExtensionsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Devices.Printers.PrintersContract\1.0.0.0\Windows.Devices.Printers.PrintersContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Devices.Scanners.ScannerDeviceContract\1.0.0.0\Windows.Devices.Scanners.ScannerDeviceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Devices.SmartCards.SmartCardBackgroundTriggerContract\3.0.0.0\Windows.Devices.SmartCards.SmartCardBackgroundTriggerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Devices.SmartCards.SmartCardEmulatorContract\6.0.0.0\Windows.Devices.SmartCards.SmartCardEmulatorContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Devices.Sms.LegacySmsApiContract\1.0.0.0\Windows.Devices.Sms.LegacySmsApiContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Embedded.DeviceLockdown.DeviceLockdownContract\1.0.0.0\Windows.Embedded.DeviceLockdown.DeviceLockdownContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.UniversalApiContract\8.0.0.0\Windows.Foundation.UniversalApiContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Gaming.Input.GamingInputPreviewContract\1.0.0.0\Windows.Gaming.Input.GamingInputPreviewContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Gaming.Preview.GamesEnumerationContract\2.0.0.0\Windows.Gaming.Preview.GamesEnumerationContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Gaming.UI.GameChatOverlayContract\1.0.0.0\Windows.Gaming.UI.GameChatOverlayContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Gaming.UI.GamingUIProviderContract\1.0.0.0\Windows.Gaming.UI.GamingUIProviderContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Gaming.XboxLive.StorageApiContract\1.0.0.0\Windows.Gaming.XboxLive.StorageApiContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Globalization.GlobalizationJapanesePhoneticAnalyzerContract\1.0.0.0\Windows.Globalization.GlobalizationJapanesePhoneticAnalyzerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Graphics.Printing3D.Printing3DContract\4.0.0.0\Windows.Graphics.Printing3D.Printing3DContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Management.Deployment.Preview.DeploymentPreviewContract\1.0.0.0\Windows.Management.Deployment.Preview.DeploymentPreviewContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Management.Workplace.WorkplaceSettingsContract\1.0.0.0\Windows.Management.Workplace.WorkplaceSettingsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Media.AppBroadcasting.AppBroadcastingContract\1.0.0.0\Windows.Media.AppBroadcasting.AppBroadcastingContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Media.AppRecording.AppRecordingContract\1.0.0.0\Windows.Media.AppRecording.AppRecordingContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Media.Capture.AppBroadcastContract\2.0.0.0\Windows.Media.Capture.AppBroadcastContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Media.Capture.AppCaptureContract\4.0.0.0\Windows.Media.Capture.AppCaptureContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Media.Capture.AppCaptureMetadataContract\1.0.0.0\Windows.Media.Capture.AppCaptureMetadataContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Media.Capture.CameraCaptureUIContract\1.0.0.0\Windows.Media.Capture.CameraCaptureUIContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Media.Capture.GameBarContract\1.0.0.0\Windows.Media.Capture.GameBarContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Media.Devices.CallControlContract\1.0.0.0\Windows.Media.Devices.CallControlContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Media.MediaControlContract\1.0.0.0\Windows.Media.MediaControlContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Media.Playlists.PlaylistsContract\1.0.0.0\Windows.Media.Playlists.PlaylistsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Media.Protection.ProtectionRenewalContract\1.0.0.0\Windows.Media.Protection.ProtectionRenewalContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Networking.Connectivity.WwanContract\2.0.0.0\Windows.Networking.Connectivity.WwanContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Networking.NetworkOperators.LegacyNetworkOperatorsContract\1.0.0.0\Windows.Networking.NetworkOperators.LegacyNetworkOperatorsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Networking.NetworkOperators.NetworkOperatorsFdnContract\1.0.0.0\Windows.Networking.NetworkOperators.NetworkOperatorsFdnContract.WinMD
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Networking.Sockets.ControlChannelTriggerContract\3.0.0.0\Windows.Networking.Sockets.ControlChannelTriggerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Networking.XboxLive.XboxLiveSecureSocketsContract\1.0.0.0\Windows.Networking.XboxLive.XboxLiveSecureSocketsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Perception.Automation.Core.PerceptionAutomationCoreContract\1.0.0.0\Windows.Perception.Automation.Core.PerceptionAutomationCoreContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Phone.PhoneContract\1.0.0.0\Windows.Phone.PhoneContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Phone.StartScreen.DualSimTileContract\1.0.0.0\Windows.Phone.StartScreen.DualSimTileContract.WinMD
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Security.EnterpriseData.EnterpriseDataContract\5.0.0.0\Windows.Security.EnterpriseData.EnterpriseDataContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Security.ExchangeActiveSyncProvisioning.EasContract\1.0.0.0\Windows.Security.ExchangeActiveSyncProvisioning.EasContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Services.Maps.GuidanceContract\3.0.0.0\Windows.Services.Maps.GuidanceContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Services.Maps.LocalSearchContract\4.0.0.0\Windows.Services.Maps.LocalSearchContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Services.Store.StoreContract\4.0.0.0\Windows.Services.Store.StoreContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Services.TargetedContent.TargetedContentContract\1.0.0.0\Windows.Services.TargetedContent.TargetedContentContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Storage.Provider.CloudFilesContract\3.0.0.0\Windows.Storage.Provider.CloudFilesContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.System.Profile.ProfileHardwareTokenContract\1.0.0.0\Windows.System.Profile.ProfileHardwareTokenContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.System.Profile.ProfileRetailInfoContract\1.0.0.0\Windows.System.Profile.ProfileRetailInfoContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.System.Profile.ProfileSharedModeContract\2.0.0.0\Windows.System.Profile.ProfileSharedModeContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.System.Profile.SystemManufacturers.SystemManufacturersContract\3.0.0.0\Windows.System.Profile.SystemManufacturers.SystemManufacturersContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.System.SystemManagementContract\6.0.0.0\Windows.System.SystemManagementContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.System.UserProfile.UserProfileContract\2.0.0.0\Windows.System.UserProfile.UserProfileContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.System.UserProfile.UserProfileLockScreenContract\1.0.0.0\Windows.System.UserProfile.UserProfileLockScreenContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.UI.ApplicationSettings.ApplicationsSettingsContract\1.0.0.0\Windows.UI.ApplicationSettings.ApplicationsSettingsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.UI.Core.AnimationMetrics.AnimationMetricsContract\1.0.0.0\Windows.UI.Core.AnimationMetrics.AnimationMetricsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.UI.Core.CoreWindowDialogsContract\1.0.0.0\Windows.UI.Core.CoreWindowDialogsContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.UI.Shell.SecurityAppManagerContract\1.0.0.0\Windows.UI.Shell.SecurityAppManagerContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.UI.ViewManagement.ViewManagementViewScalingContract\1.0.0.0\Windows.UI.ViewManagement.ViewManagementViewScalingContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.UI.WebUI.Core.WebUICommandBarContract\1.0.0.0\Windows.UI.WebUI.Core.WebUICommandBarContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.UI.Xaml.Core.Direct.XamlDirectContract\2.0.0.0\Windows.UI.Xaml.Core.Direct.XamlDirectContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.UI.Xaml.Hosting.HostingContract\4.0.0.0\Windows.UI.Xaml.Hosting.HostingContract.winmd
C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Web.Http.Diagnostics.HttpDiagnosticsContract\2.0.0.0\Windows.Web.Http.Diagnostics.HttpDiagnosticsContract.winmd
C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.15063.0\Windows.winmd
C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.15063.0\Facade\windows.winmd
C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.16299.0\Windows.winmd
C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.16299.0\Facade\windows.winmd
C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.17763.0\Windows.winmd
C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.17763.0\Facade\windows.winmd
C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.18362.0\Windows.winmd
C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.18362.0\Facade\windows.winmd
C:\Program Files (x86)\Windows Kits\10\UnionMetadata\Facade\Windows.WinMD
C:\Program Files (x86)\Windows Kits\8.1\References\CommonConfiguration\Neutral\Annotated\Windows.winmd
C:\Program Files (x86)\Windows Phone Kits\8.1\References\CommonConfiguration\Neutral\Annotated\Windows.winmd
*/
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using Windows.Data.Pdf;
using System.Reflection; // Assembly.
#if COMMENT
重要: デスクトップやコンソールアプリで、UWP APIを使う(PDF関連を含む)
https://codezine.jp/article/detail/10654
■追補:Windows 10 1803以降の場合
  以降で説明しているUwpDesktopではなく、Windows 10 WinRT API Packを使います。
これは20199月にリリースされたものです。
■セットアップ
15063以降では、最小限必要なファイルは以下の2つです。
System.Runtime.WindowsRuntime.dll
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\{.NETバージョン}\
Windows.WinMD
C:\Program Files (x86)\Windows Kits\10\UnionMetadata\{SDKバージョン}\
WinMDファイルをビルドに含めないようにする
#endif
// ref:https://water2litter.net/rum/post/cs_pdf_wpf/
namespace CSRender {
class Program {
static void dispHelp() {
var pgName = Path.GetFileName(Path.GetFileName(Assembly.GetExecutingAssembly().Location));// プログラム名
string msg =
$"{pgName} /<Opts> <PDFPath>\n"
+$"* Render of PDF file\n"
+$" /F <pdfPath> ; pdfファイル名。/Fは省略可能。明示的な指定"
+"\n";
Console.Write(msg);
}
static int Main(string[] args) {
var pdfPath="";
//static async Task Main(string[] args) {// おまじない awaitが書けるようになる C# 7.1からじゃないと書けない
var qu = new Queue<string>(args); // 引数をQueに登録 (qu.Enqueue(a)でも可能)
while (qu.Count > 0) {
// 引数のパース qu.Dequeue()で次の要素を取得する
var wd = qu.Dequeue(); // 取り出し
var wdi = wd.ToUpper(); // 大文字で比較
if (wdi == "/?" || wdi == "/H") {
dispHelp();
return -1;
} else if (wdi == "/F") {
pdfPath = qu.Dequeue();// next word.
} else if (wdi == "/M") {
mode = qu.Dequeue();// next word.
} else {
// 引数をファイル名として取得する
if (pdfPath == "") {
pdfPath = wd;
}
}
}
if (pdfPath=="") {
Console.WriteLine("pdfファイルが指定されてません");
dispHelp();
return -1;
}
if ( !File.Exists(pdfPath) ) {
Console.WriteLine($"ファイルが存在しません:{pdfPath}");
return -1;
}
var watch = System.Diagnostics.Stopwatch.StartNew(); // 生成と計測開始を同時に行う
Task<int> t = renderPDF(Path.GetFullPath(pdfPath));
int ret = t.Result;// スレッドの終了まで「待つ」
// asyncメソッド内では await呼び出しができる。ここはasyncではない。
watch.Stop();
Console.WriteLine( $"main end result={ret},time={ watch.ElapsedMilliseconds / 1000.0 } sec,ret={ret}");
//Console.WriteLine("stop");
//Console.ReadLine();
return ret;//sucess.
}
//https://csharp.hotexamples.com/examples/-/PdfPageRenderOptions/-/php-pdfpagerenderoptions-class-examples.html#0x66958305801896177d9d64dbfb6e64ebd307d702f05b801316d258b19a8d91d6-70,,84,
private static async Task<string> RenderPage(Windows.Data.Pdf.PdfPage page, string otPath, Windows.Storage.StorageFolder output) {
var pagePath = string.Format("{0}.png", page.Index);
//var pageFile = await output.CreateFileAsync(pagePath, Windows.Storage.CreationCollisionOption.ReplaceExisting);
var dir = await Windows.Storage.StorageFolder.GetFolderFromPathAsync(Directory.GetParent(otPath).FullName);
// var imgFile = await dir.CreateFileAsync(Path.GetFileName(otPath), Windows.Storage.CreationCollisionOption.ReplaceExisting);
Console.WriteLine($"task PageNum={page.Index},Tread={Thread.CurrentThread.ManagedThreadId}");
var th = Thread.CurrentThread.ManagedThreadId;
//using (var imageStream = await pageFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite))
using (var memStrm = new Windows.Storage.Streams.InMemoryRandomAccessStream())
{
//var imageStream = await pageFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
//var memStrm = new Windows.Storage.Streams.InMemoryRandomAccessStream();
//Console.WriteLine($"[start render{th}]");
//await page.RenderToStreamAsync(imageStream);
//await imageStream.FlushAsync();
await page.RenderToStreamAsync(memStrm);
await memStrm.FlushAsync();
//Console.WriteLine($"[end render:{th}]");
{
BitmapImage image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
//Console.Write("[AsStrem ST]");
image.StreamSource = memStrm.AsStream();
//Console.Write("[AsStrem ED]");
image.EndInit();
BitmapEncoder enc = new JpegBitmapEncoder();
if (enc == null) {
Console.WriteLine("encode取得失敗"); return "NG";
}
enc.Frames.Add(BitmapFrame.Create(image));
//var p = Path.Combine(otDir, $"{otBaseName}.{nPage + 1}.jpg");
//var p = Path.ChangeExtension(pageFile.Path,"jpg");// otPath;
Console.WriteLine("ot=" + otPath);
using (FileStream fs = new FileStream(otPath, System.IO.FileMode.Create)) {
enc.Save(fs);
}
}
//imageStream.Dispose();
memStrm.Dispose();
}
Console.WriteLine($"save end:{pagePath}");
return output.Path + pagePath;
}
// これが並列がだめなもの
public static async Task<string> renderPageNG(PdfPage page, string otPath) {
Console.WriteLine($"task PageNum={page.Index},Tread={Thread.CurrentThread.ManagedThreadId}");
//PdfPage page = doc.GetPage((uint)nPage);// using しない
/*using (PdfPage page = doc.GetPage( (uint)nPage) )*/
{
BitmapImage image = new BitmapImage();
using (var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream()) {
Console.Write("[start stream}");
//Console.Write("[GetPage ST]");
//PdfPage page = doc.GetPage((uint)nPage);
//Console.Write("[GetPage EN]");
Console.Write("[Rendersync ST]");
await page.RenderToStreamAsync(stream);
Console.Write("[Rendersync EN]");
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
Console.Write("[AsStrem ST]");
image.StreamSource = stream.AsStream();
Console.Write("[AsStrem ED]");
image.EndInit();
// xamlへの返却 imgPdf.Source = image;
// 画像BitmapImageの画像への保存 https://yoshiiz.blog.fc2.com/blog-entry-818.html
// JPEG Q https://docs.microsoft.com/ja-jp/dotnet/framework/winforms/advanced/how-to-set-jpeg-compression-level
// https://water2litter.net/gin/?p=979
BitmapEncoder enc = new JpegBitmapEncoder();
if (enc == null) {
Console.WriteLine("encode取得失敗"); return "NG";
}
enc.Frames.Add(BitmapFrame.Create(image));
//var p = Path.Combine(otDir, $"{otBaseName}.{nPage + 1}.jpg");
var p = otPath;
Console.WriteLine("ot=" + p);
using (FileStream fs = new FileStream(p, System.IO.FileMode.Create)) {
enc.Save(fs);
}
}
}
return "SUCCESS";
}
private static async Task<string> RenderPageOrg(Windows.Data.Pdf.PdfPage page, Windows.Storage.StorageFolder output) {
var pagePath = string.Format("{0}.jpeg", page.Index);
var pageFile = await output.CreateFileAsync(pagePath, Windows.Storage.CreationCollisionOption.ReplaceExisting);
Console.WriteLine($"task PageNum={page.Index},Tread={Thread.CurrentThread.ManagedThreadId}");
using (var imageStream = await pageFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite))
{
await page.RenderToStreamAsync(imageStream);
PdfPageRenderOptions pdfPageRenderOptions = new PdfPageRenderOptions();
pdfPageRenderOptions.BitmapEncoderId = Windows.Graphics.Imaging.BitmapEncoder.JpegEncoderId;// JPEG
pdfPageRenderOptions.IsIgnoringHighContrast = false;
await page.RenderToStreamAsync(imageStream, pdfPageRenderOptions);
await imageStream.FlushAsync();
}
Console.WriteLine("save end" + pagePath);
return output.Path + pagePath;
}
public static string mode = "";
public static async Task<int> renderPDF (string pdfPath) {
var file = await Windows.Storage.StorageFile.GetFileFromPathAsync(pdfPath);
var otDir = "";
var otBaseName=Path.GetFileName(pdfPath);//*.pdf
{ // 出力ディレクトリの作成 // 元PDFの同一フォルダにIMGフォルダを作成する
otDir = Path.Combine(Directory.GetParent(pdfPath).FullName,"IMG");
if ( !Directory.Exists(otDir)) {
Directory.CreateDirectory(otDir);
};
}
// PDFファイルを読み込む
var pdfDoc = await Windows.Data.Pdf.PdfDocument.LoadFromFileAsync(file);
if (pdfDoc == null) {
Console.WriteLine("pdfDoc取得失敗"); return -1;
}
var n = pdfDoc.PageCount;
if ( mode == "file" ) {
Console.WriteLine("mode=file");
var taskList = new List<Task<int>>();
for ( int i = 0; i < n; i++ ) {
taskList.Add( renderFILE(pdfPath, i,Path.Combine(otDir, $"{otBaseName}.{i + 1}.jpg")) );
//renderPage(pdfDoc, i, Path.Combine(otDir, $"{otBaseName}.{i + 1}.jpg"));
//var ret = await renderPage(pdfDoc, i,Path.Combine(otDir, $"{otBaseName}.{i + 1}.jpg"));
}
//int[] arrayInt =
await Task.WhenAll(taskList);// すべてのタスクを待つ。
} else if ( mode == "page" ) {
Console.WriteLine("mode=page");
var taskList = new List<Task<int>>();
for (int i = 0; i < n; i++) {
taskList.Add(renderPage(pdfDoc, pdfDoc.GetPage((uint)i),i, Path.Combine(otDir, $"{otBaseName}.{i + 1}.jpg"))); // docを渡す
}
//int[] arrayInt =
await Task.WhenAll(taskList);// すべてのタスクを待つ。
} else if (mode == "spl") {
var dir = await Windows.Storage.StorageFolder.GetFolderFromPathAsync(otDir);
//private static async Task<string> RenderPage(Windows.Data.Pdf.PdfPage page, Windows.Storage.StorageFolder output)
Console.WriteLine("mode=spl");
var taskList = new List<Task<string>>();
for (int i = 0; i < n; i++) {
taskList.Add(RenderPage(pdfDoc.GetPage((uint)i), Path.Combine(otDir, $"{otBaseName}.{i + 1}.jpg"), dir)); // docを渡す
}
//int[] arrayInt =
await Task.WhenAll(taskList);// すべてのタスクを待つ。
} else if (mode == "org") {
// 並列で動くユイツのもの
var dir = await Windows.Storage.StorageFolder.GetFolderFromPathAsync(otDir);
//private static async Task<string> RenderPage(Windows.Data.Pdf.PdfPage page, Windows.Storage.StorageFolder output)
Console.WriteLine("mode=org");
var taskList = new List<Task<string>>();
for (int i = 0; i < n; i++) {
taskList.Add(RenderPageOrg(pdfDoc.GetPage((uint)i), dir)); // docを渡す
}
//int[] arrayInt =
await Task.WhenAll(taskList);// すべてのタスクを待つ。
} else {
Console.WriteLine("mode=none");
// スレッド無し
for (int i = 0; i < n; i++) {// 1ページ目を読み込む
using (Windows.Data.Pdf.PdfPage page = pdfDoc.GetPage((uint)i)) {
BitmapImage image = new BitmapImage();
using (var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream()) {
await page.RenderToStreamAsync(stream);
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.StreamSource = stream.AsStream();
image.EndInit();
BitmapEncoder enc = new JpegBitmapEncoder();
if (enc == null) {
Console.WriteLine("encode取得失敗"); return -2;
}
enc.Frames.Add(BitmapFrame.Create(image));
var p = Path.Combine(otDir, $"{otBaseName}.{i + 1}.jpg");
Console.WriteLine("ot=" + p);
using (FileStream fs = new FileStream(p, System.IO.FileMode.Create)) {
enc.Save(fs);
}
}
}
}
}
/*
readner option sample:
https://csharp.hotexamples.com/examples/-/PdfPageRenderOptions/-/php-pdfpagerenderoptions-class-examples.html
for ( int i = 0; i < n; i++ ) {// 1ページ目を読み込む
using (Windows.Data.Pdf.PdfPage page = pdfDoc.GetPage((uint)i)) {
BitmapImage image = new BitmapImage();
using (var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream()) {
await page.RenderToStreamAsync(stream);
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.StreamSource = stream.AsStream();
image.EndInit();
// xamlへの返却 imgPdf.Source = image;
// 画像BitmapImageの画像への保存 https://yoshiiz.blog.fc2.com/blog-entry-818.html
// JPEG Q https://docs.microsoft.com/ja-jp/dotnet/framework/winforms/advanced/how-to-set-jpeg-compression-level
// https://water2litter.net/gin/?p=979
// このソースじゃないかな? https://gogowaten.hatenablog.com/entry/2020/01/02/125352
BitmapEncoder enc = new JpegBitmapEncoder();
if ( enc == null ) {
Console.WriteLine("encode取得失敗");return -2;
}
enc.Frames.Add(BitmapFrame.Create(image));
var p = Path.Combine(otDir, $"{otBaseName}.{i+1}.jpg");
Console.WriteLine("ot="+p);
using (FileStream fs = new FileStream(p, System.IO.FileMode.Create)) {
enc.Save(fs);
}
}
}
}
*/
return 0;// success.
}
/// <summary>
/// pdfのページを画像に出力する
/// </summary>
/// <param name="doc">PdfDocument</param>
/// <param name="nPage">ページ番号</param>
/// <param name="otPath">出力ファイル名</param>
/// <returns>正常:0 </returns>
public static async Task<int> renderPage(PdfDocument doc, PdfPage page,int nPage, string otPath ) {
//おまじない このダミーのawait入れないとスレッドにならない
var dir = await Windows.Storage.StorageFolder.GetFolderFromPathAsync(Directory.GetParent(otPath).FullName);
//Console.WriteLine("これをかくとスレッド1 " + Thread.CurrentThread.ManagedThreadId);
//Console.WriteLine($"task PageNum={nPage},Tread={Thread.CurrentThread.ManagedThreadId}");
var th = Thread.CurrentThread.ManagedThreadId;
//
//PdfPage page = doc.GetPage((uint)nPage);// using しない
/*using (PdfPage page = doc.GetPage( (uint)nPage) )*/
{
using (var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream()) {
//Console.Write("[start stream}");
//Console.Write("[GetPage ST]");
//PdfPage page = doc.GetPage((uint)nPage);
//Console.Write("[GetPage EN]");
//Console.Write("[Rendersync ST]");
await page.RenderToStreamAsync(stream);
//Console.Write("[Rendersync EN]");
{
BitmapImage image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
//Console.Write("[AsStrem ST]");
image.StreamSource = stream.AsStream();
//Console.Write("[AsStrem ED]");
image.EndInit();
// xamlへの返却 imgPdf.Source = image;
// 画像BitmapImageの画像への保存 https://yoshiiz.blog.fc2.com/blog-entry-818.html
// JPEG Q https://docs.microsoft.com/ja-jp/dotnet/framework/winforms/advanced/how-to-set-jpeg-compression-level
// https://water2litter.net/gin/?p=979
BitmapEncoder enc = new JpegBitmapEncoder();
if (enc == null) {
Console.WriteLine("encode取得失敗"); return -2;
}
enc.Frames.Add(BitmapFrame.Create(image));
//var p = Path.Combine(otDir, $"{otBaseName}.{nPage + 1}.jpg");
var p = otPath;
Console.WriteLine($"ot[{Thread.CurrentThread.ManagedThreadId}]=" + p );
using (FileStream fs = new FileStream(p, System.IO.FileMode.Create)) {
enc.Save(fs);
}
}
}
}
return 0;//success
}
public static async Task<int> renderFILE(string inPath, int nPage, string otPath) {
// ファイルから開いてみる
var file = await Windows.Storage.StorageFile.GetFileFromPathAsync(inPath);
var doc = await Windows.Data.Pdf.PdfDocument.LoadFromFileAsync(file);
if (doc == null) {
Console.WriteLine("pdfDoc取得失敗 in renderFile"); return -1;
}
Console.WriteLine($"task PageNum={nPage},Tread={Thread.CurrentThread.ManagedThreadId}");
using (PdfPage page = doc.GetPage((uint)nPage)) {
BitmapImage image = new BitmapImage();
using (var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream()) {
await page.RenderToStreamAsync(stream);
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.StreamSource = stream.AsStream();
image.EndInit();
// xamlへの返却 imgPdf.Source = image;
// 画像BitmapImageの画像への保存 https://yoshiiz.blog.fc2.com/blog-entry-818.html
// JPEG Q https://docs.microsoft.com/ja-jp/dotnet/framework/winforms/advanced/how-to-set-jpeg-compression-level
// https://water2litter.net/gin/?p=979
BitmapEncoder enc = new JpegBitmapEncoder();
if (enc == null) {
Console.WriteLine("encode取得失敗"); return -2;
}
enc.Frames.Add(BitmapFrame.Create(image));
//var p = Path.Combine(otDir, $"{otBaseName}.{nPage + 1}.jpg");
var p = otPath;
Console.WriteLine("ot=" + p);
using (FileStream fs = new FileStream(p, System.IO.FileMode.Create)) {
enc.Save(fs);
}
}
}
return 0;//success
}
}
}
/* Tips:
スレッド内のSleep Thread.Sleep(4560); // 何か重い処理をしている...
await Task....
*/
/*
- メモ c# acync await
https://qiita.com/rawr/items/5d49960a4e4d3823722f
https://qiita.com/4_mio_11/items/f9b19c04509328b1e5c1
https://tech-lab.sios.jp/archives/15711
http://www.ifelse.jp/blog/csharp-01
async定義内で重い処理を直接記載せずに
await Task<string>.Run(() => {} で呼び出す。重い通常関数を呼び出すとメインスレッドで動いてしまう(だめなわけじゃない)
*/
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Reflection; // Assembly.
// UWP-APIの使用
using Windows.Data.Pdf;
// ref:https://water2litter.net/rum/post/cs_pdf_wpf/
using EncType = System.Drawing.Imaging.Encoder;// 別名
using EncParamType = System.Drawing.Imaging.EncoderParameter;//別名
namespace ImageParams
{
using EncType = System.Drawing.Imaging.Encoder;// 別名
using EncParamType = System.Drawing.Imaging.EncoderParameter;//別名
/// <summary>
/// BitMapのSaveに使うImage Encodeパラメータの設定値の生成.
/// var enc = new ImageParams.EncData("jpeg");
/// //enc.SetImageType("PNG");
/// bitmap.Save(xxx, enc.GetInfo(),enc.GetParams());
///
/// </summary>
public class EncData {
// SEE:https://dobon.net/vb/dotnet/graphics/encoderparameters.html
private string ImageType = "jpeg";
public EncData(string imageType = "jpeg") {
SetImageType(imageType);
}
public long JpegQuality { get; set; } = 91;// 指定しないときの値は91と一致する
/// <summary>
/// イメージパラメータを設定する こんな感じで
/// </summary>
/// <param name="enc"></param>
///
public EncData SetImageType(string imageType) {
imageType = imageType.ToLower();
if (imageType == "jpeg" || imageType == "jpg") {
ImageType = "jpeg";
} else if (imageType == "png") {
ImageType = "png";
} else if (imageType == "tif" || imageType == "tiff") {
ImageType = "tiff";
} else {
ImageType = imageType;// 小文字を設定
}
return this;
}
public int SaveImage(System.Drawing.Bitmap bitmap, string path, string imageType = null) {
var p = GetParams();
string imType = imageType?.ToLower();
if (p != null) {
bitmap.Save(path, GetInfo(imType), GetParams());// imageTypeがnullならSetImageType()のものが使われる
} else {
// パラメータが空の場合
var imageFormat = new System.Drawing.Imaging.ImageFormat(GetInfo(imType).FormatID);
bitmap.Save(path, imageFormat);
}
return 0;
}
public System.Drawing.Imaging.EncoderParameters GetParams() {
var encList = new List<System.Drawing.Imaging.EncoderParameter>();
//encList.Clear();
// 今はJPEGパラメータだけ
encList.Add(new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, JpegQuality));
//...
// 結合
var eps = new System.Drawing.Imaging.EncoderParameters(encList.Count);
for (var i = 0; i < encList.Count; i++)
eps.Param[i] = encList[i];
return eps;
}
public System.Drawing.Imaging.ImageCodecInfo GetInfo(string it=null) {
if ( it != null) {
var ici = GetEncoderInfo($"image/{it}");
return ici;
} else {
var ici = GetEncoderInfo($"image/{ImageType}");
return ici;
}
}
public static void GetSupportedParameters(System.Drawing.Bitmap bitmap1=null) {
// https://docs.microsoft.com/ja-jp/dotnet/framework/winforms/advanced/how-to-determine-the-parameters-supported-by-an-encoder
// 現状Errorが発生して取得できない
try {
if (bitmap1 == null) {
bitmap1 = new System.Drawing.Bitmap(100, 100);
var destBitmapData = bitmap1.LockBits(
new System.Drawing.Rectangle(0, 0, 100, 100),
System.Drawing.Imaging.ImageLockMode.ReadOnly,
bitmap1.PixelFormat
);
bitmap1.UnlockBits(destBitmapData);
}
var jpgEncoder = GetEncoderInfo(System.Drawing.Imaging.ImageFormat.Tiff);
var paramList = bitmap1.GetEncoderParameterList(jpgEncoder.Clsid);
var encParams = paramList.Param;
for (int i = 0; i < encParams.Length; i++) {
Console.WriteLine("Param " + i + " holds " + encParams[i].NumberOfValues +
" items of type " +
encParams[i].ValueType + "\r\n" + "Guid category: " + encParams[i].Encoder.Guid + "\r\n");
}
} catch (Exception e) {
Console.WriteLine($"Ignore error ={e.ToString()}");
}
}
// inner method.
//ImageFormatで指定されたImageCodecInfoを探して返す
private static System.Drawing.Imaging.ImageCodecInfo GetEncoderInfo(System.Drawing.Imaging.ImageFormat f) {
var encs = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
foreach (var enc in encs) {
if (enc.FormatID == f.Guid) {
return enc;
}
}
return null;
}
private static System.Drawing.Imaging.ImageCodecInfo GetEncoderInfo(string mineType) {
//GDI+ に組み込まれたイメージ エンコーダに関する情報をすべて取得
System.Drawing.Imaging.ImageCodecInfo[] encs = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
//指定されたMimeTypeを探して見つかれば返す
foreach (System.Drawing.Imaging.ImageCodecInfo enc in encs) {
if (enc.MimeType == mineType) {
return enc;
}
}
return null;
}
}
}
namespace CSRender {
class Program {
static string outuptImageDir = "";// /O
static string dpi = "72.0";// /D
#if non
static string boxSelect = "C"; //B<x>
static string pageRange = ""; //P
static string inputList = ""; //L
static string offset = ""; //OFFSET
static string overprint = ""; //OP
static string tempDir = ""; //T
static string fileUpdate = ""; //U
#endif
static string mode = "page"; //MODE
static string imageType = "JPG"; //JPG or /PNG
static string jpegQ = "91"; //JPEGQ
static void DispHelp() {
var pgName = Path.GetFileName(Path.GetFileName(Assembly.GetExecutingAssembly().Location));// プログラム名
string msg =
$"{pgName} [/<Opts>] <PDFPath>\n"
+$"* Render of PDF file\n"
+$"\t/F <pdfPath> : pdfPath(pdfファイル名) /Fは省略可能\n"
+$"\t/O <output directory> : 出力ディレクトリ\n"
+$"\t/D <解像度> : 解像度指定 9 - 300dpi\n"
+ $"\t/B<x> : ボックス指定 x:M/B/T/A/C(default) ex. /BM (MediaBox/BleedBox/TrimBox/ArtBox/CropBox(*unsupport)\n"
+$"\t/P <PageRange> : ページの範囲を指定する(省略時は全ページ)(*unsupport)\n"
+$"\t\t連続した範囲を指定する場合は、ハイフン('-')を用いる\n"
+$"\t\t複数のページ範囲を指定する場合は、カンマ(',')を用いる\n"
+$"\t/L <input List text> : 入力PDFファイルリスト(*unsupport)\n"
+$"\t/OFFSET <X> <Y> : ミリ単位でオフセットを指定する(省略時は共に0mm)(*unsupport)\n"
+$"\t/OP <0 or 1> : オーバープリントのOn/Off (省略時は1)(*unsupport allready 1)\n"
+$"\t/T <tempPath> : テンポラリフォルダを指定(省略時は出力先フォルダと同じ(*unsupport no need)\n"
+$"\t/U <0 or 1> : 同名上書き設定 0:上書きしない 1:上書き(*unsupport)\n"
+$"\t/H or /? : Help\n"
+$"\t[Type of Image format]\n"
+$"\t/JPG: JPEGファイル出力\n"
+$"\t/PNG: PNGファイル出力\n"
+$"\t/TIF: TIFファイル出力\n"
+$"\t/GIF: GIFファイル出力\n"
+$"\t/BMP: BMPファイル出力\n"
+$"\t[JPEG Param]\n"
+$"\t/JPEGQ <quality>: Jpegの品質指定1-100(default=91)\n"
+$"\t[for TEST]\n"
+$"\t/M <mode> : pageBitMap(default), pageBitMapImage, page(same as pageBitMap), org(orginal source)\n"
+ "\n";
Console.Write(msg);
}
/// <summary>
/// PDFレンダラーメイン
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
static int Main(string[] args) {
var pdfPath="";
//static async Task Main(string[] args) {// async Task Main:おまじない Mainでawaitが書けるようになる C# 7.1からじゃないと書けない
var qu = new Queue<string>(args); // 引数をQueに登録 (qu.Enqueue(a)でも可能)
while (qu.Count > 0) {
// 引数のパース qu.Dequeue()で次の要素を取得する
var wd = qu.Dequeue(); // 取り出し
var wdi = wd.ToUpper(); // 大文字で比較
if (wdi == "/?" || wdi == "/H") {
DispHelp();
return -1;
} else if (wdi == "/F") {
pdfPath = (qu.Count > 0) ? qu.Dequeue() :"";// next word.
} else if (wdi == "/O") {
outuptImageDir = (qu.Count > 0) ? qu.Dequeue() :"";// next word.
} else if (wdi == "/D") {
dpi = (qu.Count > 0) ? qu.Dequeue():"";// next word.
if ( !double.TryParse(dpi, out double dmy)) {
Console.WriteLine($"解像度が不正です:/D {dpi}");
DispHelp();
return -1;
}
} else if (wdi == "/JPG" || wdi == "/JPEG") {
imageType = "JPG";
} else if (wdi == "/PNG") {
imageType = "PNG";
} else if (wdi == "/TIF") {
imageType = "TIFF";
} else if (wdi == "/GIF") {
imageType = "GIF";
} else if (wdi == "/BMP") {
imageType = "BMP";
} else if (wdi == "/JPEGQ") {
jpegQ = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
if (!int.TryParse(jpegQ, out int dmy)) {
Console.WriteLine($"JPEG Qualityが不正です:/JPEGQ {jpegQ}");
DispHelp();
return -1;
}
if ( !(0 < dmy && dmy <= 100) ) {
Console.WriteLine($"JPEG Qualityが不正です(not 1-100):/JPEGQ {dmy}");
return -1;
}
} else if (wdi == "/M") {
mode = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
} else {
// 引数をファイル名として取得する
if (pdfPath == "") {
pdfPath = wd;
}
}
}
if (pdfPath=="") {
Console.WriteLine("pdfファイルが指定されてません");
DispHelp();
return -1;
}
if ( !File.Exists(pdfPath) ) {
Console.WriteLine($"ファイルが存在しません:{pdfPath}");
return -1;
}
var watch = System.Diagnostics.Stopwatch.StartNew(); // 時間の生成と計測開始を同時に行う
var otDir = "";
if ( outuptImageDir == "" ) { // 出力ディレクトリの作成 // 元PDFの同一フォルダにIMGフォルダを作成する
otDir = Path.Combine(Directory.GetParent(pdfPath).FullName, "IMG");
if (!Directory.Exists(otDir))
Directory.CreateDirectory(otDir);
}
var ret = RenderPdfDocAsync(
pdfPath :Path.GetFullPath(pdfPath),
inDir :otDir,
inDpi :double.Parse(dpi),
imageType:imageType,
inJpegQ :int.Parse(jpegQ)
).Result;// スレッドの終了まで「待つ」
watch.Stop();
Console.WriteLine( $"result={ret},time={ watch.ElapsedMilliseconds/1000.0 }[sec]");
return ret;//success.
}
public static async Task<int> RenderPdfDocAsync(string pdfPath, string inDir = "", double inDpi = 9.0, string imageType = "JPG", int inJpegQ = 0) {
var otDir = inDir;
var otBaseName = Path.GetFileName(pdfPath);//*.pdf
var otExtention = imageType.ToLower();
{ // 出力ディレクトリの作成 // 元PDFの同一フォルダにIMGフォルダを作成する
otDir = Path.Combine(Directory.GetParent(pdfPath).FullName, "IMG");
if (!Directory.Exists(otDir))
Directory.CreateDirectory(otDir);
}
// PDFファイルを読み込む
var file = await Windows.Storage.StorageFile.GetFileFromPathAsync(pdfPath);
var pdfDoc = await Windows.Data.Pdf.PdfDocument.LoadFromFileAsync(file);
if (pdfDoc == null) {
Console.WriteLine("error: get PdfDocument failed");
return -1;
}
var n = pdfDoc.PageCount;
if (mode == "page" || mode == "pageBitMap" || mode == "pageBitMapImage") {
if (mode == "page") {
mode = "pageBitMap";
}
Console.WriteLine($"mode={mode}");
var taskList = new List<Task<int>>();
for (int i = 0; i < n; i++) {
taskList.Add(
RenderPageAync(
doc :pdfDoc,
page :pdfDoc.GetPage((uint)i),
nPage :i,
otPath :Path.Combine(otDir, $"{otBaseName}.{i + 1}.{otExtention}"),
inDpi :inDpi,
encName :imageType,
mode :mode,
inJpegQ :inJpegQ
)
); // docを渡す
}
await Task.WhenAll(taskList);// すべてのタスクを待つ。//int[] arrayInt =
} else if (mode == "org") {
// 並列で動く唯一のもの(Test)
var dir = await Windows.Storage.StorageFolder.GetFolderFromPathAsync(otDir);
Console.WriteLine("mode=org");
var taskList = new List<Task<int>>();
for (int i = 0; i < n; i++) {
taskList.Add(RenderPageOrgASync(pdfDoc.GetPage((uint)i), dir)); // docを渡す
}
await Task.WhenAll(taskList);// すべてのタスクを待つ。//int[] arrayInt =
}
return 0;// success.
}
/// <summary>
/// pdfのページを画像に出力する
/// </summary>
/// <param name="doc">PdfDocument</param>
/// <param name="nPage">ページ番号</param>
/// <param name="otPath">出力ファイル名</param>
/// <returns>正常:0 </returns>
public static async Task<int> RenderPageAync(PdfDocument doc, PdfPage page,int nPage, string otPath, double inDpi=72.0, string encName="JPG",string mode = "pageBitMap", int inJpegQ = 91) {
//おまじない このダミーのawait入れないとスレッドにならない
var dir = await Windows.Storage.StorageFolder.GetFolderFromPathAsync(Directory.GetParent(otPath).FullName);
var th = Thread.CurrentThread.ManagedThreadId;
// パラメータ
const double dpiWin = 96.0;/* , dpiPDF = 72.0*/
double resoScale = (inDpi / dpiWin);
var opt = new PdfPageRenderOptions() {
// SEE:https://github.com/microsoft/Windows-universal-samples/blob/master/Samples/PdfDocument/cs/Scenario1_Render.xaml.cs
//BitmapEncoderId = Windows.Graphics.Imaging.BitmapEncoder.JpegEncoderId,// JPEG
IsIgnoringHighContrast = false
};
opt.DestinationHeight = (uint)(page.Size.Height * resoScale + 0.5);
opt.DestinationWidth = (uint)(page.Size.Width * resoScale + 0.5);
//Console.WriteLine($"dpi={inDpi},scale={resoScale},height(org)={page.Size.Height}->{opt.DestinationHeight}");
using (var memStrm = new Windows.Storage.Streams.InMemoryRandomAccessStream()) {
await page.RenderToStreamAsync(memStrm,opt);
await memStrm.FlushAsync();
if (mode == "pageBitMap") {
var bmp = new System.Drawing.Bitmap(memStrm.AsStream());
//Console.WriteLine($"OrgReso({bmp.HorizontalResolution},{bmp.VerticalResolution})");
var imEnc = new ImageParams.EncData(encName);
imEnc.JpegQuality = inJpegQ;
bmp.SetResolution((float)inDpi, (float)inDpi);
Console.WriteLine($"ot[{Thread.CurrentThread.ManagedThreadId}]={Path.GetFileName(otPath)}({Directory.GetParent(otPath)})");
imEnc.SaveImage(bmp, otPath);
bmp.Dispose();
memStrm.Seek(0);
} else if (mode == "pageBitMapImage") {
var image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.StreamSource = memStrm.AsStream();
image.EndInit();
BitmapEncoder enc = null;
switch (encName) {
case "JPG": enc = new JpegBitmapEncoder(); break;
case "PNG": enc = new PngBitmapEncoder(); break;
case "TIF":
case "TIFF": enc = new TiffBitmapEncoder(); break;
case "GIF": enc = new GifBitmapEncoder(); break;
case "BMP": enc = new BmpBitmapEncoder(); break;
default: Console.WriteLine("failed encode"); return -2;
}
enc.Frames.Add(BitmapFrame.Create(image));
Console.WriteLine($"ot[{Thread.CurrentThread.ManagedThreadId}]={otPath}");
using (var fs = new FileStream(otPath, System.IO.FileMode.Create)) {
enc.Save(fs);
}
}
}
return 0;//success
}
/// <summary>
/// PDF Render サンプル
/// ref: https://csharp.hotexamples.com/examples/-/PdfPageRenderOptions/-/php-pdfpagerenderoptions-class-examples.html#0x66958305801896177d9d64dbfb6e64ebd307d702f05b801316d258b19a8d91d6-70,,84,
/// * コード量は少ないが、以下ができない
/// - Built-in のEncodeIdしか指定できない(パラメータが渡せない)
/// - 遅い:PDFレンダリングと同時にファイル保存するから?
/// </summary>
/// <param name="page"></param>
/// <param name="output"></param>
/// <returns></returns>
// ref: https://csharp.hotexamples.com/examples/-/PdfPageRenderOptions/-/php-pdfpagerenderoptions-class-examples.html#0x66958305801896177d9d64dbfb6e64ebd307d702f05b801316d258b19a8d91d6-70,,84,
private static async Task<int> RenderPageOrgASync(Windows.Data.Pdf.PdfPage page, Windows.Storage.StorageFolder output) {
var pagePath = string.Format("{0}.jpeg", page.Index);
var pageFile = await output.CreateFileAsync(pagePath, Windows.Storage.CreationCollisionOption.ReplaceExisting);
using (var imageStream = await pageFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite)) {
await page.RenderToStreamAsync(imageStream);
var renderOpt = new PdfPageRenderOptions() {
BitmapEncoderId = Windows.Graphics.Imaging.BitmapEncoder.JpegEncoderId,// JPEG
IsIgnoringHighContrast = false
};
await page.RenderToStreamAsync(imageStream, renderOpt);
await imageStream.FlushAsync();
}
Console.WriteLine($">{Thread.CurrentThread.ManagedThreadId} save {pagePath}");
return 0;
}
}
}
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
//using System.Text;
//using System.Threading;
//using System.Threading.Tasks;
//using System.Windows;
//using System.Windows.Media.Imaging;
using System.Reflection; // Assembly.
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
// UWP-APIの使用
// using Windows.Data.Pdf;
// 作成クラス
using CSRender;
using CSRender.UtHash;
// *重要* デスクトップアプリで UWP Api を呼び出す プロジェクトの設定方法が記載されている
// https://docs.microsoft.com/ja-jp/windows/apps/desktop/modernize/desktop-to-uwp-enhance
// 参照はwindows. winmd :C:\Program Files (x86) \Windows Kits\10\UnionMetadata\<sdk バージョン>/ファサード
namespace CSRenderMain {
class Program {
static void DispHelp() {
var pgName = Path.GetFileName(Path.GetFileName(Assembly.GetExecutingAssembly().Location));// プログラム名
string msg =
$"{pgName} [/<Opts>] <PDFPath or PDFDir>\n"
+ $"* Render of PDF file. available 3 command mode:[Basic Rendering] [Make Hash command] [Compare command], and [Render Options]\n"
+ $"\tPDFの画像化は[Basic Rendering]。\n"
+ $"\t比較は/MkHash([Make Hash command])後に、/FC([Compare command])で高速実行できます。\n"
+ $"\n"
+ $"[Basic Rendering] 基本的なレンダリング\n"
+ $"\t{pgName} [/<Render Options>] <PDFPath|PDFDir>\n"
+ $"\t/F <pdfPath|pdfDir> : pdfPath(pdfファイル名|ディレクトリ) /Fは省略可能\n"
+ $"\t/O <output directory> : 出力ディレクトリ。省略時は\"IMG\"フォルダ\n"
+ $"\n"
+ $"[Render Options] レンダリングオプション\n"
+ $"\t/D <解像度> : 解像度指定 9 - 300dpi(default=72dpi)\n"
+ $"\t/BM,/BT,/BA,/BA,/BC: Select one box.(default=/BC:CrobBox): Boxies:MediaBox/BleedBox/TrimBox/ArtBox/CropBox\n"
+ $"\t/JPG,/JPEG,/PNG,/TIF,/TIFF,/GIF,/BMP: Select one output format.(default=/JPG)\n"
+ $"\t/JPEGQ <quality>: Jpegの品質指定1-100(default=91)\n"
+ $"\n"
+ $"\t/P <PageRange> : ページの範囲を指定する(省略時は全ページ)\n"
+ $"\t\t連続した範囲を指定する場合は、ハイフン('-')を用いる。終了側を省略すると最終pageまで。\n"
+ $"\t\t複数のページを指定する場合は、カンマ(',')を用いる\n"
+ $"\t\tEx. /P \"1,2,30-100\" //1,2pages and 30-100pages.\n"
+ $"\t[unsupport] 未対応\n"
+ $"\t/L <input List text> : 入力PDFファイルリスト(*unsupport)\n"
+ $"\t/T <tempPath> : テンポラリフォルダを指定(省略時は出力先フォルダと同じ(*unsupport no need)\n"
+ $"\t/OP <0|1> : オーバープリントのOn/Off (省略時は1)(*unsupport allways on[1])\n"
+ $"\t/U <0|1> : 同名上書き設定 0:上書きしない 1:上書き(*unsupport allways overwrite[1])\n"
+ $"\t/OFFSET <X> <Y> : ミリ単位でオフセットを指定する(省略時は共に0mm)(*unsupport)\n"
+ $"\n"
+ $"[Make Hash command] 比較用ハッシュ値作成コマンド\n"
+ $"\t{pgName} /MkHash ...<Render Options>... <PDF|PDF dir>\n"
+ $"\t/MKHash : ハッシュ値を出力する。前記の[Render Options]を指定すること\n"
+ $"\t[HASHファイル作成]\n"
+ $"\n"
+ $"[Compare command] 比較コマンド\n"
+ $"\t{pgName} /FC ...<Render Options>... <Target PDF|PDF dir> <Reference PDF|PDF dir>\n"
+ $"\t/FC : 2つのPDFを比較する。前記の[Render Options]を指定すること。無名引数が2つ必要です\n"
+ $"\t 事前に/MkHashを実行しておくことで高速に処理できる\n"
+ $"\t/RESULT <result file> : 比較結果を格納するファイルパス\n"
+ $"\t\t/FCコマンドを指定すると一致したら0,不一致なら1を返却するようになる\n"
+ $"\t\t<result file>は、<pageNum(1始まり)>,<OK or NG>の行で構成される\n"
+ $"\n"
+ $"/H or /? : This help\n"
/* PDFと同じフォルダに
data.<出力条件>.jsonファイルを作成する
出力条件:<dpi>+<Box>+<IMFormat>+<JQ>
data.72_BT_JPG_Q34.json
既に存在したら、それを読んでから、追記(もしくは書き換える>。
*/
// Remove TEST
//+$"\t[for TEST]\n"
//+$"\t/M Sync(default) or ASync\n"
//+$"\t/M <mode> : pageBitMap(default), pageBitMapImage, page(same as pageBitMap), org(orginal source)\n"
+ "\n";
Console.Write(msg);
}
#if COMENT
// 設計の見直し
* ハッシュ作成のみのコマンド
/MkHashをつけると ハッシュファイルのみ作成。ただし、ディレクトリ指定に限る
CSRender /MkHash <PDFディレクトリ> <各種Renderパラメータ>
* 単純なRenderを維持。それに同時にハッシュファイルのOn/Off
/MkHashをつけなければよい。
CSRender <PDFディレクトリor PDFファイル> <各種Renderパラメータ>
* 比較モードは、Autoハッシュで、存在しなければ最初に作成。Target/Refともに。比較しながら作成してよし
Manualでハッシュなしで、遅いけどできるようにする。ハッシュ動作の検証用に
/FCをつけると、デフォルトでハッシュ優先で検査(Auto相当)、ハッシュ検査を無効にしたければ
/NoHash追加でハッシュを無視してTarget/Refとも再計算。ハッシュを使いたければ、事前に/MkHash
作成しておけばよい。
* ヘルプは <単純なRender> <ハッシュ作成> <比較>にわける
* <単純なレンダラ>: 1ファイルおよびディレクトリの比較。 Renderingパラメータの一覧(項目分ける)まで.
* <ハッシュ作成>: /MkHashで高速比較のための前準備。ディレクトリモードでハッシュファイルのみを作成する。Renderingパラメータは合わせること
* <比較>:/FCコマンドで比較の説明
* ここにAsiccDocを埋められないの? 情報なし*
// 遅くなるので
* 比較モード時の差異があったとき、Diffを出す上限値をLimitDiffNumがほしい(デフォルトは各PDF1pageとしたい)
* 比較NGになって、フルでDIFF画像を出したいときはLimitDiffを解除すべき。単独ファイル指定のとき。
// 設計の見直し(END)
#endif
/// <summary>
/// PDFレンダラーメイン
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
static int Main(string[] args) {
string outuptImageDir = ""; // /O
string dpi = "72.0"; // /D
string boxSelect = "Crop"; //B<x>
string pageRange = "1-*"; //P
string mode = "page"; //MODE
string imageType = "JPG"; //JPG or /PNG
string jpegQ = "91"; //JPEGQ
string pdfPath ="";
bool bHash = false; //ハッシュ値を生成する
bool bMkHash = false; //ハッシュファイルを作成する
bool bFC = false;
bool bDirMode = false; // ディレクト指定の場合
string pdfPath2 = ""; //比較ファイル
string resultPath = "";
//var pdfPathLst = new List<string>();
string[] pdfPathLst = null;
string[] pdfPathLst2 = null;
var pdfPathLstBoth = new List<string>();
var pdfPathLstNoBoth = new List<string>();
//ハッシュ関係
string hashBaseName = "RenderHash";
//
CSRender.Check.GetDPI();
{// ベースハッシュ値の計算テスト
var streamPDF = ResData.GetBaseHashPDF();
RenderPDF.RenderPdfInitCheck(streamPDF);
//return 0;
}
var qu = new Queue<string>(args); // 引数をQueに登録 (qu.Enqueue(a)でも可能)
while (qu.Count > 0) {
// 引数のパース
var wd = qu.Dequeue(); // 取り出しqu.Dequeue()で次の要素を取得する
if (wd.First() == '-') {
// 先頭-(ハイフンもオプション扱いにする)→"/"に置換
wd = Regex.Replace(wd,@"^\-","/");
}
//大文字小文字無視でオプションチェック
var eIgnoreCase = StringComparer.OrdinalIgnoreCase;
// オプションチェックローカル関数
bool isOpt(params string[] opts) => opts.Contains<string>(wd, eIgnoreCase);
// ボックスオプション辞書
var BoxSelOptDic = new Dictionary<string, string>(eIgnoreCase)
{ ["/BM"] = "Media", ["/BT"] = "Trim",
["/BB"] = "Bleed", ["/BC"] = "Crop",
["/BA"] = "Art"
};
if (isOpt("/?","/H")) {
DispHelp();
return -1;
} else if (isOpt("/F")) {
pdfPath = (qu.Count > 0) ? qu.Dequeue() :"";// next word.
} else if (isOpt("/O")) {
outuptImageDir = (qu.Count > 0) ? qu.Dequeue() :"";// next word.
} else if (isOpt("/D")) {
dpi = (qu.Count > 0) ? qu.Dequeue():"";// next word.
if (!double.TryParse(dpi, out double dmy)) {
Console.WriteLine($"解像度が不正です:/D {dpi}");
DispHelp();
return -1;
}
} else if (isOpt("/P")) {
pageRange = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
} else if (isOpt("/JPG","/JPEG")) {
imageType = "JPG";
} else if (isOpt("/PNG")) {
imageType = "PNG";
} else if (isOpt("/TIF","/TIFF")) {
imageType = "TIFF";
} else if (isOpt("/GIF", "/GIFF")) {
imageType = "GIF";
} else if (isOpt("/BMP")) {
imageType = "BMP";
} else if (isOpt("/JPEGQ")) {
jpegQ = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
if (!int.TryParse(jpegQ, out int dmy)) {
Console.WriteLine($"JPEG Qualityが不正です:/JPEGQ {jpegQ}");
DispHelp();
return -1;
}
if ( !(0 < dmy && dmy <= 100) ) {
Console.WriteLine($"JPEG Qualityが不正です(not 1-100):/JPEGQ {dmy}");
return -1;
}
} else if (isOpt("/M") ) {
mode = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
} else if ( BoxSelOptDic.ContainsKey(wd) ) {
boxSelect = BoxSelOptDic[wd];// "/BT" -> "Trim",...
} else if (isOpt("/HASH")) {
bHash = true;
} else if (isOpt("/MKHASH")) {
bMkHash = true;
bHash = true;
} else if (isOpt("/FC")) {
bFC = true;
} else if (isOpt("/RESULT")) {
resultPath = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
} else if (wd.First()=='/') {
// 処理の無いオプションを明示的に無視する
Console.WriteLine($"Warning::Ignore opt:{wd}");
} else {
// 引数をファイル名として取得する
if (pdfPath == "") {
pdfPath = wd;
continue;
}
if (bFC && (pdfPath2 == "") ) {
pdfPath2 = wd;// 比較時のみ取得
continue;
}
}
}
if (pdfPath=="") {
Console.WriteLine("pdfファイルが指定されてません");
DispHelp();
return -1;
}
if ( !(File.Exists(pdfPath)|| Directory.Exists(pdfPath)) ) {
// ファイルもしくはディレクトも見つからない場合
Console.WriteLine($"ファイルが存在しません:{pdfPath}");
return -1;
}
var rdCond = new RenderPDF.RenderConditionParams {
Dpi = double.Parse(dpi),
ImageType = imageType,
BoxType = boxSelect,
JpegQ= int.Parse(jpegQ)
};
bool bDir = File.GetAttributes(pdfPath).HasFlag(FileAttributes.Directory);
if ( bDir ) {
bDirMode = true;
// Directoryが指定されたのでファイルリストアップ
pdfPathLst = System.IO.Directory.GetFiles(pdfPath,"*.pdf"/*, System.IO.SearchOption.AllDirectories*/);
pdfPathLst = Array.ConvertAll(pdfPathLst, f => Path.GetFileName(f)); // 配列書き換え(ファイル名のみにする
// var enumLst = pdfPathLst.Select(f => Path.GetFileName(f)); LINQ式に置き換えることも可能(返り値は配列ではない)
foreach ( var f in pdfPathLst) {
Console.WriteLine($@"path1={f}");
}
}
if ((!bFC) && bDir ) {
// 単純レンダリング時およびディレクト時に対象リストに追加
foreach (var f in pdfPathLst) {
pdfPathLstBoth.Add(f);
}
}
if (bFC) {// 比較モード時
if (pdfPath2 == "") {
Console.WriteLine("比較モードで2つ目のpdfファイルが指定されてません");
return -1;
}
if (!(File.Exists(pdfPath2) || Directory.Exists(pdfPath2))) {
Console.WriteLine($"比較ファイルが存在しません:{pdfPath2}");
return -1;
}
bool bDir2 = File.GetAttributes(pdfPath2).HasFlag(FileAttributes.Directory);
if (bDir2) {
if (!bDir) {
Console.WriteLine($"比較対象はファイルパスでないといけません:{pdfPath2}");
return -1;
}
// 2つ目のファイルリストアップ
pdfPathLst2 = System.IO.Directory.GetFiles(pdfPath2, "*.pdf"/*, System.IO.SearchOption.AllDirectories*/);
pdfPathLst2 = Array.ConvertAll( pdfPathLst2, f => Path.GetFileName(f) );// 配列の書き換え
foreach( var f in pdfPathLst2) {
Console.WriteLine($@"path2={f}");
}
// 共通のファイルを見つける。Lstの要素がLst2に含まれているかどうか
foreach (var f in pdfPathLst) {
if (pdfPathLst2.Contains(f)) {
pdfPathLstBoth.Add(f);
} else {
pdfPathLstNoBoth.Add(f);// LstがLst2に含まれていない
}
}
// Lst2のみファイルをNoBothに登録
foreach (var f in pdfPathLst2) {
if (pdfPathLstBoth.Contains(f)) {
pdfPathLstNoBoth.Add(f);
}
}
// pdfPathBoth,pdfPathNoBothが作成済み
}
}
var watch = System.Diagnostics.Stopwatch.StartNew(); // 時間の生成と計測開始を同時に行う
var otDir = outuptImageDir;
if (otDir == "" ) {
// 出力ディレクトリの作成 // 元PDFの同一フォルダにIMGフォルダを作成する
otDir = Path.Combine(Directory.GetParent(pdfPath).FullName, "IMG");
}
if (!Directory.Exists(otDir) /* && (!bMkHash)*/ ) { // MkHashのとき不要→必要
Directory.CreateDirectory(otDir);
}
var otHashPath = "";
var otHashPath2 = "";
int ret = -1;
if (!bDirMode) {
if (bFC) {
//比較モード
// ハッシュデータの読み込み
Console.WriteLine($@"pre pdfPath={pdfPath}");
Console.WriteLine($@"pre pdfPath2={pdfPath2}");
var hashDataTgt = HashData.load(pdfPath, hashBaseName, dpi, boxSelect, imageType, jpegQ, ref otHashPath);
var hashDataRef = HashData.load(pdfPath2, hashBaseName, dpi, boxSelect, imageType, jpegQ, ref otHashPath2);
Console.WriteLine("<Compare Sync(Paralles) Version!>");
ret = RenderPDF.RenderPdfDocCompare(
pdfPath: Path.GetFullPath(pdfPath),
refPdfPath: Path.GetFullPath(pdfPath2),
inDir: otDir,
pm:rdCond,
inPageRange: pageRange,
inHashDataTgt: hashDataTgt,
inHashDataRef: hashDataRef
);
//} else if (mode.ToLower() == "async") {
// // これはもはや不要
// ret = RenderPDF.RenderPdfDocAsync(
// ...
// ).Result;// スレッドの終了まで「待つ」
} else {
// Sync version.
// Console.WriteLine("<Render Sync(Paralles) Version!>");
// シングル指定では既存のハッシュファイルを読みださない → 単独名のハッシュファイル<pdfFName+".hash")
// 空のハッシュデータを作成
var hashDataTgt = new HashData();
hashDataTgt.Head.SetRenderInfo(dpi, boxSelect, imageType, jpegQ);
//retはページ数
// rdCond
ret = RenderPDF.RenderPdfDoc(
pdfPath: Path.GetFullPath(pdfPath),
inDir: otDir,
pm :rdCond,
inPageRange: pageRange,
bSaveImage: bMkHash?false:true,// ハッシュ値生成ではイメージ保存しない。
bHash: bHash,
inHashData: hashDataTgt
);
if (bMkHash) {
// 個別のファイル名+"hash"拡張子で保存します。
var othashPath = Path.Combine(otDir,Path.GetFileName(pdfPath)+".hash");
hashDataTgt.save(othashPath);//ハッシュモードで保存する(Dutyチェックもいるでしょう
//不要:hashDataTgt.save(otHashPath);//比較モード,MakeHashに限定すること
//表示のみ まだやめておく:
}
// retはページ数です。
}
} else {
// 対象がディレクトリ
Console.WriteLine("For Directory mode");
HashData hashDataTgt = null, hashDataRef = null;
//if ( !bMkHash) {// MKHashの時にはLoadしない 。ファイルがなくても、otHashPathは帰ってくる
hashDataTgt = HashData.load(pdfPath, hashBaseName, dpi, boxSelect, imageType, jpegQ, ref otHashPath);
//}
if (hashDataTgt == null) {
// 空のハッシュデータを作成
hashDataTgt = new HashData();
hashDataTgt.Head.SetRenderInfo(dpi, boxSelect, imageType, jpegQ);
}
if ( bFC) {
hashDataRef = HashData.load(pdfPath2, hashBaseName, dpi, boxSelect, imageType, jpegQ, ref otHashPath2);
if (hashDataRef == null) {
// 空のハッシュデータを作成
hashDataRef = new HashData();
hashDataRef.Head.SetRenderInfo(dpi, boxSelect, imageType, jpegQ);
}
}
// ハッシュデータが適切に作成済みがどうかを確認。もしハッシュデータが存在しない場合は
// ハッシュデータを渡してはいけない。ハッシュのFilesで確認するか?
// ハッシュデータの作成プロセスをもっと簡単にすべき
Console.WriteLine($@"Start render:{pdfPathLstBoth.Count}");
//Console.WriteLine("<Render Sync(Paralles) Version!>");[
var count= pdfPathLstBoth.Count;
//ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = 6 };
//Parallel.For(0,pdfPathLstBoth.Count, options, index => {
//逆に遅くなる UWPコール(render)は対応していない?
for (var index=0; index < pdfPathLstBoth.Count; index++) {
GC.Collect();// これでメモリリークが解決した
var tgt = Path.Combine(pdfPath, pdfPathLstBoth[index]);
Console.WriteLine($@"tgt={tgt}:{index}/{pdfPathLstBoth.Count}");
if (bFC) {
//比較モード
var reff = Path.Combine(pdfPath2, pdfPathLstBoth[index]);
Console.WriteLine("<Compare Sync(Paralles) Version!>");
ret = RenderPDF.RenderPdfDocCompare(
pdfPath: Path.GetFullPath(tgt),
refPdfPath: Path.GetFullPath(reff),
inDir: otDir,
pm:rdCond,
inPageRange: pageRange,
inHashDataTgt: hashDataTgt,
inHashDataRef: hashDataRef
);
} else { // Sync version(Paralles).
ret = RenderPDF.RenderPdfDoc(
pdfPath: Path.GetFullPath(tgt),
inDir: otDir,
pm: rdCond,
inPageRange: pageRange,
bSaveImage: bMkHash ? false:true,// ハッシュ値生成ではイメージ保存しない。
bHash: bHash,// bHash,dumy
inHashData : bMkHash ? hashDataTgt:null //ハッシュコマンドモードのみDataを渡す
);
}
count--;
};
if (bMkHash) {
hashDataTgt.save(otHashPath);//ハッシュモードで保存する(Dutyチェックもいるでしょう
}
}
watch.Stop();
Console.WriteLine( $"result={ret},time={ watch.ElapsedMilliseconds/1000.0 }[sec]");
#if COMMNET
Assembly assm = Assembly.GetExecutingAssembly();
Console.WriteLine(assm.FullName);
// 参照しているすべてのアセンブリを取得し、表示する
foreach (AssemblyName refassm in assm.GetReferencedAssemblies()) {
Console.WriteLine($@" {refassm.FullName},Ver({refassm.Version}),VerComp({refassm.VersionCompatibility})" );
}
string clrVersion = System.Environment.Version.ToString();
Console.WriteLine($@"clrVer={clrVersion}");
#endif
return ret;//success.
}
// リソースからの取得
public static class ResData
{
public static Stream GetBaseHashPDF(string resName = "CSRender.RES.BaseHash.pdf") {
System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
var sel = from x in asm.GetManifestResourceNames() select resName;
if ( sel.Count() == 1) {
return asm.GetManifestResourceStream(sel.First());
}
return null;
}
}
}
}
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
//using System.Text;
//using System.Threading;
//using System.Threading.Tasks;
//using System.Windows;
//using System.Windows.Media.Imaging;
using System.Reflection; // Assembly.
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.ServiceModel; // WCF
using System.Diagnostics; // for Process
// UWP-APIの使用
// using Windows.Data.Pdf;
// 作成クラス
using CSRender;
using CSRender.UtHash;
// *重要* デスクトップアプリで UWP Api を呼び出す プロジェクトの設定方法が記載されている
// https://docs.microsoft.com/ja-jp/windows/apps/desktop/modernize/desktop-to-uwp-enhance
// 参照はwindows. winmd :C:\Program Files (x86) \Windows Kits\10\UnionMetadata\<sdk バージョン>/ファサード
namespace xChangeWCFPipe
{
}
namespace CSRenderMain {
[DataContract]
//[Serializable()] // これでもいけそう
public class ParamData {
[DataMember]
public string pdfPath = ""; //対象ファイル
[DataMember]
public string pdfPath2 = ""; //比較ファイル
[DataMember]
public string outuptImageDir = ""; // /O
[DataMember]
public string dpi = "72.0"; // /D
[DataMember]
public string boxSelect = "Crop"; // /B<x>
[DataMember]
public string pageRange = "1-*"; // /P
[DataMember]
public string mode = "page"; // /MODE
[DataMember]
public string imageType = "JPG"; // /JPG or /PNG
[DataMember]
public string jpegQ = "91"; // JPEGQ
[DataMember]
public bool bHash = false; // ハッシュ値を生成する
[DataMember]
public bool bMkHash = false; // ハッシュファイルを作成する
[DataMember]
public bool bFC = false;
[DataMember]
public string resultPath = "";
[DataMember]
public bool bPDFium = true;
//
[DataMember]
public bool bExeSepa = true;// 実行分離
[DataMember]
public string subExe = null;// "Sub"が指定されたら、処理をExe分離する。内部コマンド
// データはWCFの通信データを使う。引数はPortAddressNameとする
public ParamData Clone() {
return (ParamData)MemberwiseClone();
}
}
public class Program {
static void DispHelp() {
var pgName = Path.GetFileName(Path.GetFileName(Assembly.GetExecutingAssembly().Location));// プログラム名
var pgNameFull = Assembly.GetExecutingAssembly().Location;// プログラム名
string msg =
$"{pgName} [/<Opts>] <PDFPath or PDFDir>\n"
+ $"* Render of PDF file. available 3 command mode:[Basic Rendering] [Make Hash command] [Compare command], and [Render Options]\n"
+ $"\tPDFの画像化は[Basic Rendering]。\n"
+ $"\t比較は/MkHash([Make Hash command])後に、/FC([Compare command])で高速実行できます。\n"
+ $"\n"
+ $"[Basic Rendering] 基本的なレンダリング\n"
+ $"\t{pgName} [/<Render Options>] <PDFPath|PDFDir>\n"
+ $"\t/F <pdfPath|pdfDir> : pdfPath(pdfファイル名|ディレクトリ) /Fは省略可能\n"
+ $"\t/O <output directory> : 出力ディレクトリ。省略時は\"IMG\"フォルダ\n"
+ $"\n"
+ $"[Render Options] レンダリングオプション\n"
+ $"\t/D <解像度> : 解像度指定 9 - 300dpi(default=72dpi)\n"
+ $"\t/BM,/BT,/BA,/BA,/BC: Select one box.(default=/BC:CrobBox): Boxies:MediaBox/BleedBox/TrimBox/ArtBox/CropBox\n"
+ $"\t/JPG,/JPEG,/PNG,/TIF,/TIFF,/GIF,/BMP: Select one output format.(default=/JPG)\n"
+ $"\t/JPEGQ <quality>: Jpegの品質指定1-100(default=91)\n"
+ $"\n"
+ $"\t/P <PageRange> : ページの範囲を指定する(省略時は全ページ)\n"
+ $"\t\t連続した範囲を指定する場合は、ハイフン('-')を用いる。終了側を省略すると最終pageまで。\n"
+ $"\t\t複数のページを指定する場合は、カンマ(',')を用いる\n"
+ $"\t\tEx. /P \"1,2,30-100\" //1,2pages and 30-100pages.\n"
+ $"\t[unsupport] 未対応\n"
+ $"\t/L <input List text> : 入力PDFファイルリスト(*unsupport)\n"
+ $"\t/T <tempPath> : テンポラリフォルダを指定(省略時は出力先フォルダと同じ(*unsupport no need)\n"
+ $"\t/OP <0|1> : オーバープリントのOn/Off (省略時は1)(*unsupport allways on[1])\n"
+ $"\t/U <0|1> : 同名上書き設定 0:上書きしない 1:上書き(*unsupport allways overwrite[1])\n"
+ $"\t/OFFSET <X> <Y> : ミリ単位でオフセットを指定する(省略時は共に0mm)(*unsupport)\n"
+ $"\t/PDFium <0or1>: GoogoleのPDFiumViewerエンジンを使用する(default=1>\n"
+ $"\n"
+ $"[Make Hash command] 比較用ハッシュ値作成コマンド\n"
+ $"\t{pgName} /MkHash ...<Render Options>... <PDF|PDF dir>\n"
+ $"\t/MKHash : ハッシュ値を出力する。前記の[Render Options]を指定すること\n"
+ $"\t[HASHファイル作成]\n"
+ $"\n"
+ $"[Compare command] 比較コマンド\n"
+ $"\t{pgName} /FC ...<Render Options>... <Target PDF|PDF dir> <Reference PDF|PDF dir>\n"
+ $"\t/FC : 2つのPDFを比較する。前記の[Render Options]を指定すること。無名引数が2つ必要です\n"
+ $"\t 事前に/MkHashを実行しておくことで高速に処理できる\n"
+ $"\t/RESULT <result file> : 比較結果を格納するファイルパス\n"
+ $"\t\t/FCコマンドを指定すると一致したら0,不一致なら1を返却するようになる\n"
+ $"\t\t<result file>は、<pageNum(1始まり)>,<OK or NG>の行で構成される\n"
+ $"\n"
+ $"[ELSE ] その他のオプション\n"
+ $"\t/PDFium <0|1>:PDFiumライブラリを使う,デフォルト=1\n"
+ $"\t/NoExeSepa :実行分離しない(遅い)\n"
+ $"\t内部コマンド:/SubExe <WCF_PipeAddress> :実行分離,PDF単位で別Processで処理\n"
+ $"\n"
+ $"/H or /? : This help\n"
/* PDFと同じフォルダに
data.<出力条件>.jsonファイルを作成する
出力条件:<dpi>+<Box>+<IMFormat>+<JQ>
data.72_BT_JPG_Q34.json
既に存在したら、それを読んでから、追記(もしくは書き換える>。
*/
// Remove TEST
//+$"\t[for TEST]\n"
//+$"\t/M Sync(default) or ASync\n"
//+$"\t/M <mode> : pageBitMap(default), pageBitMapImage, page(same as pageBitMap), org(orginal source)\n"
+ "\n";
Console.Write(msg);
}
#if COMENT
// 設計の見直し
* ハッシュ作成のみのコマンド
/MkHashをつけると ハッシュファイルのみ作成。ただし、ディレクトリ指定に限る
CSRender /MkHash <PDFディレクトリ> <各種Renderパラメータ>
* 単純なRenderを維持。それに同時にハッシュファイルのOn/Off
/MkHashをつけなければよい。
CSRender <PDFディレクトリor PDFファイル> <各種Renderパラメータ>
* 比較モードは、Autoハッシュで、存在しなければ最初に作成。Target/Refともに。比較しながら作成してよし
Manualでハッシュなしで、遅いけどできるようにする。ハッシュ動作の検証用に
/FCをつけると、デフォルトでハッシュ優先で検査(Auto相当)、ハッシュ検査を無効にしたければ
/NoHash追加でハッシュを無視してTarget/Refとも再計算。ハッシュを使いたければ、事前に/MkHash
作成しておけばよい。
* ヘルプは <単純なRender> <ハッシュ作成> <比較>にわける
* <単純なレンダラ>: 1ファイルおよびディレクトリの比較。 Renderingパラメータの一覧(項目分ける)まで.
* <ハッシュ作成>: /MkHashで高速比較のための前準備。ディレクトリモードでハッシュファイルのみを作成する。Renderingパラメータは合わせること
* <比較>:/FCコマンドで比較の説明
* ここにAsiccDocを埋められないの? 情報なし*
// 遅くなるので
* 比較モード時の差異があったとき、Diffを出す上限値をLimitDiffNumがほしい(デフォルトは各PDF1pageとしたい)
* 比較NGになって、フルでDIFF画像を出したいときはLimitDiffを解除すべき。単独ファイル指定のとき。
// 設計の見直し(END)
#endif
/// <summary>
/// PDFレンダラーメイン
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
static int Main(string[] args) {
// 引数の保持
var pm = new ParamData();
bool bDirMode = false; // ディレクト指定の場合
//var pdfPathLst = new List<string>();
string[] pdfPathLst = null;
string[] pdfPathLst2 = null;
var pdfPathLstBoth = new List<string>();
var pdfPathLstNoBoth = new List<string>();
//ハッシュ関係
string hashBaseName = "RenderHash";
//
CSRender.Check.GetDPI();
{// ベースハッシュ値の計算テスト
var streamPDF = ResData.GetBaseHashPDF();
RenderPDF.RenderPdfInitCheck(streamPDF);
//return 0;
}
var qu = new Queue<string>(args); // 引数をQueに登録 (qu.Enqueue(a)でも可能)
while (qu.Count > 0) {
// 引数のパース
var wd = qu.Dequeue(); // 取り出しqu.Dequeue()で次の要素を取得する
if (wd.First() == '-') {
// 先頭-(ハイフンもオプション扱いにする)→"/"に置換
wd = Regex.Replace(wd, @"^\-", "/");
}
//大文字小文字無視でオプションチェック
var eIgnoreCase = StringComparer.OrdinalIgnoreCase;
// オプションチェックローカル関数
bool isOpt(params string[] opts) => opts.Contains<string>(wd, eIgnoreCase);
// ボックスオプション辞書
var BoxSelOptDic = new Dictionary<string, string>(eIgnoreCase) { ["/BM"] = "Media", ["/BT"] = "Trim",
["/BB"] = "Bleed", ["/BC"] = "Crop",
["/BA"] = "Art"
};
if (isOpt("/?", "/H")) {
DispHelp();
return -1;
} else if (isOpt("/F")) {
pm.pdfPath = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
} else if (isOpt("/O")) {
pm.outuptImageDir = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
} else if (isOpt("/D")) {
pm.dpi = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
if (!double.TryParse(pm.dpi, out double dmy)) {
Console.WriteLine($"解像度が不正です:/D {pm.dpi}");
DispHelp();
return -1;
}
} else if (isOpt("/P")) {
pm.pageRange = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
} else if (isOpt("/JPG", "/JPEG")) {
pm.imageType = "JPG";
} else if (isOpt("/PNG")) {
pm.imageType = "PNG";
} else if (isOpt("/TIF", "/TIFF")) {
pm.imageType = "TIFF";
} else if (isOpt("/GIF", "/GIFF")) {
pm.imageType = "GIF";
} else if (isOpt("/BMP")) {
pm.imageType = "BMP";
} else if (isOpt("/JPEGQ")) {
pm.jpegQ = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
if (!int.TryParse(pm.jpegQ, out int dmy)) {
Console.WriteLine($"JPEG Qualityが不正です:/JPEGQ {pm.jpegQ}");
DispHelp();
return -1;
}
if (!(0 < dmy && dmy <= 100)) {
Console.WriteLine($"JPEG Qualityが不正です(not 1-100):/JPEGQ {dmy}");
return -1;
}
} else if (isOpt("/M")) {
pm.mode = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
} else if (BoxSelOptDic.ContainsKey(wd)) {
pm.boxSelect = BoxSelOptDic[wd];// "/BT" -> "Trim",...
} else if (isOpt("/HASH")) {
pm.bHash = true;
} else if (isOpt("/MKHASH")) {
pm.bMkHash = true;
pm.bHash = true;
} else if (isOpt("/FC")) {
pm.bFC = true;
} else if (isOpt("/PDFium")) {
pm.bPDFium = true;
var flgStr = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
if (!int.TryParse(flgStr, out int dmy)) {
Console.WriteLine($"PDFiumフラグが不正です:/PDFium {flgStr}");
return -1;
}
if (dmy == 0) {
pm.bPDFium = false;
} else if (dmy == 1) {
pm.bPDFium = true;
} else {
Console.WriteLine($"PDFiumフラグが不正です:/PDFium {flgStr}");
return -1;
}
} else if (isOpt("/SubExe")) {
pm.subExe = (qu.Count > 0) ? qu.Dequeue() : null;// next word.
} else if (isOpt("/NoExeSepa")) {
pm.bExeSepa = false;
} else if (isOpt("/RESULT")) {
pm.resultPath = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
} else if (wd.First() == '/') {
// 処理の無いオプションを明示的に無視する
Console.WriteLine($"Warning::Ignore opt:{wd}");
} else {
// 引数をファイル名として取得する
if (pm.pdfPath == "") {
pm.pdfPath = wd;
continue;
}
if (pm.bFC && (pm.pdfPath2 == "")) {
pm.pdfPath2 = wd;// 比較時のみ取得
continue;
}
}
}
//
bool bSubExe = (pm.subExe != null);// SubExeで起動されている場合。
xChangeWCFPipe.IXData cltSrv = null;
if (!bSubExe) {
/// サーバー側のセットアップ
Console.WriteLine("++MainProcess start");
} else {
// SubExe側の動作に差し替える
Console.WriteLine("++SubProcess start:"+pm.subExe);
//cltSrv = xChangeWCFPipe.CLT.makeCLT(pipeName:"pName",pipeAddress:pm.subExe);
cltSrv = xChangeWCFPipeGEN.CLT_T.makeCLT<xChangeWCFPipe.IXData>(
pipeName:"pName",pipeAddress:pm.subExe);
Console.WriteLine("[S]:End makeCLT");
var pm2 = cltSrv.GetParam();
Console.WriteLine($@"[S]:pm2.pdfPath={pm2.pdfPath}");
var ppp = cltSrv.GetData();
cltSrv.SetMessage("Message");
Console.WriteLine("[S]:End GetData");
pm = ppp.pm; // パラメータを呼び出し元のものに置き換え
Console.WriteLine("[S]:End GetData pm");
Console.WriteLine($@"[S]:pm.pdfPath={ppp.pm.pdfPath}");
Console.WriteLine($@"[S]:ppp.dataB.b={ppp.dataB.b}");
}
if (pm.pdfPath == "") {
Console.WriteLine("pdfファイルが指定されてません");
DispHelp();
return -1;
}
if (!(File.Exists(pm.pdfPath) || Directory.Exists(pm.pdfPath))) {
// ファイルもしくはディレクトも見つからない場合
Console.WriteLine($"ファイルが存在しません:{pm.pdfPath}");
return -1;
}
var rdCond = new RenderPDF.RenderConditionParams {
Dpi = double.Parse(pm.dpi),
ImageType = pm.imageType,
BoxType = pm.boxSelect,
JpegQ = int.Parse(pm.jpegQ)
};
bool bDir = File.GetAttributes(pm.pdfPath).HasFlag(FileAttributes.Directory);
if (bDir) {
// Directoryが指定されたのでファイルリストアップ
bDirMode = true;
pdfPathLst = System.IO.Directory.GetFiles(pm.pdfPath, "*.pdf"/*, System.IO.SearchOption.AllDirectories*/);
pdfPathLst = Array.ConvertAll(pdfPathLst, f => Path.GetFileName(f)); // 配列書き換え(ファイル名のみにする
// var enumLst = pdfPathLst.Select(f => Path.GetFileName(f)); LINQ式に置き換えることも可能(返り値は配列ではない)
//foreach ( var f in pdfPathLst) {
// Console.WriteLine($@"path1={f}");
//}
Console.WriteLine($@"path1.Len={pdfPathLst.Count()}");
}
if ((!pm.bFC) && bDir) {
// 単純レンダリング時 かつ ディレクト時に 対象リストに追加
foreach (var f in pdfPathLst) {
pdfPathLstBoth.Add(f);
}
}
if (pm.bFC) {// 比較モード時
if (pm.pdfPath2 == "") {
Console.WriteLine("比較モードで2つ目のpdfファイルが指定されてません");
return -1;
}
if (!(File.Exists(pm.pdfPath2) || Directory.Exists(pm.pdfPath2))) {
Console.WriteLine($"比較ファイルが存在しません:{pm.pdfPath2}");
return -1;
}
bool bDir2 = File.GetAttributes(pm.pdfPath2).HasFlag(FileAttributes.Directory);
if (bDir2) {
if (!bDir) {
Console.WriteLine($"比較対象はファイルパスでないといけません:{pm.pdfPath2}");
return -1;
}
// 2つ目のファイルリストアップ
pdfPathLst2 = System.IO.Directory.GetFiles(pm.pdfPath2, "*.pdf"/*, System.IO.SearchOption.AllDirectories*/);
pdfPathLst2 = Array.ConvertAll(pdfPathLst2, f => Path.GetFileName(f));// 配列の書き換え
// 共通のファイルを見つける。Lstの要素がLst2に含まれているかどうか
foreach (var f in pdfPathLst) {
if (pdfPathLst2.Contains(f)) {
pdfPathLstBoth.Add(f);
} else {
pdfPathLstNoBoth.Add(f);// LstがLst2に含まれていない
}
}
// Lst2のみファイルをNoBothに登録
foreach (var f in pdfPathLst2) {
if (!pdfPathLstBoth.Contains(f)) {
pdfPathLstNoBoth.Add(f);
}
}
// pdfPathBoth,pdfPathNoBothが作成済み
if (pdfPathLstNoBoth.Count() != 0) {
Console.WriteLine($@"不一致のファイル={pdfPathLstNoBoth.Count()}");
foreach (var f in pdfPathLstNoBoth) {
Console.WriteLine($@"warning [no match]={f}");
}
}
}
}
var watch = System.Diagnostics.Stopwatch.StartNew(); // 時間の生成と計測開始を同時に行う
var otDir = pm.outuptImageDir;
if (otDir == "") {
// 出力ディレクトリの作成 // 元PDFの同一フォルダにIMGフォルダを作成する
otDir = Path.Combine(Directory.GetParent(pm.pdfPath).FullName, "IMG");
}
if (!Directory.Exists(otDir) /* && (!bMkHash)*/ ) { // MkHashのとき不要→必要
Directory.CreateDirectory(otDir);
}
var otHashPath = "";
var otHashPath2 = "";
int ret = -1;
Console.WriteLine($@"bPDFium={pm.bPDFium}");
if (!bDirMode) {
if (pm.bFC) {
//比較モード
// ハッシュデータの読み込み
Console.WriteLine($@"pre pdfPath={pm.pdfPath}");
Console.WriteLine($@"pre pdfPath2={pm.pdfPath2}");
var hashDataTgt = HashData.load(pm.pdfPath, hashBaseName, pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ, ref otHashPath);
var hashDataRef = HashData.load(pm.pdfPath2, hashBaseName, pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ, ref otHashPath2);
//Console.WriteLine("<Compare Sync(Paralles) Version!>");
ret = RenderPDF.RenderPdfDocCompare(
pdfPath : Path.GetFullPath(pm.pdfPath),
refPdfPath : Path.GetFullPath(pm.pdfPath2),
inDir : otDir,
pm : rdCond,
inPageRange : pm.pageRange,
inHashDataTgt: hashDataTgt,
inHashDataRef: hashDataRef,
bPDFium : pm.bPDFium
);
} else {
// Sync version.
// Console.WriteLine("<Render Sync(Paralles) Version!>");
// シングル指定では既存のハッシュファイルを読みださない → 単独名のハッシュファイル<pdfFName+".hash")
// 空のハッシュデータを作成
var hashDataTgt = new HashData();
hashDataTgt.Head.SetRenderInfo(pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ);
//retはページ数
// rdCond
ret = RenderPDF.RenderPdfDoc(
pdfPath : Path.GetFullPath(pm.pdfPath),
inDir : otDir,
pm : rdCond,
inPageRange : pm.pageRange,
bSaveImage : pm.bMkHash ? false : true,// ハッシュ値生成ではイメージ保存しない。
bHash : pm.bHash,
inHashData : hashDataTgt,
bPDFium : pm.bPDFium
);
if (pm.bMkHash) {
/// ここでMain側に通信データを返せばよい
if (bSubExe) {
cltSrv.SetHashData(hashDataTgt);
} else {
// 個別のファイル名+"hash"拡張子で保存します。
var othashPath = Path.Combine(otDir, Path.GetFileName(pm.pdfPath) + ".hash");
hashDataTgt.save(othashPath);//ハッシュモードで保存する(Dutyチェックもいるでしょう
//不要:hashDataTgt.save(otHashPath);//比較モード,MakeHashに限定すること
//表示のみ まだやめておく:
}
}
// retはページ数です。
}
} else {
// 対象がディレクトリ
Console.WriteLine("For Directory mode");
HashData hashDataTgt = null, hashDataRef = null;
hashDataTgt = HashData.load(pm.pdfPath, hashBaseName, pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ, ref otHashPath);
if (pm.bMkHash) {
hashDataTgt = null;// MKHashの時にはLoadしない → 一旦nullで除去して、otHashPathを利用する
}
if (hashDataTgt == null) {
// 空のハッシュデータを作成
hashDataTgt = new HashData();
hashDataTgt.Head.SetRenderInfo(pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ);
}
if (pm.bFC) {
// リファレンス側のハッシュの読み込み
hashDataRef = HashData.load(pm.pdfPath2, hashBaseName, pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ, ref otHashPath2);
if (hashDataRef == null) {
// 空のハッシュデータを作成
hashDataRef = new HashData();
hashDataRef.Head.SetRenderInfo(pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ);
}
}
// ハッシュデータが適切に作成済みがどうかを確認。もしハッシュデータが存在しない場合は
// ハッシュデータを渡してはいけない。ハッシュのFilesで確認するか?
// ハッシュデータの作成プロセスをもっと簡単にすべき
Console.WriteLine($@"Start render:{pdfPathLstBoth.Count}");
//Console.WriteLine("<Render Sync(Paralles) Version!>");[
var count = pdfPathLstBoth.Count;
//ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = 6 };
//Parallel.For(0,pdfPathLstBoth.Count, options, index => {
//逆に遅くなる UWPコール(render)は対応していない?
if (pm.bExeSepa) {
var tokenSource = new CancellationTokenSource();
ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = 4, CancellationToken=tokenSource.Token };
var loopResult = Parallel.For(0,pdfPathLstBoth.Count, options, (index,lpState) => {
//for (var index = 0; index < pdfPathLstBoth.Count; index++) {
var tgt = Path.Combine(pm.pdfPath, pdfPathLstBoth[index]);
Console.WriteLine($@"**remain({count})****tgt({index}/{pdfPathLstBoth.Count})={tgt}");
if (pm.bFC) {
//比較モード
var reff = Path.Combine(pm.pdfPath2, pdfPathLstBoth[index]);
} else { // Sync version(Paralles).
var svrData = new xChangeWCFPipe.XData();
var pmClone = pm.Clone();
pmClone.pdfPath = tgt;// 引数のターゲットのみを書き換える
svrData.SetParam(pmClone);
var svrHost = xChangeWCFPipeGEN.SVR_T.makeSVR(
baseIf : typeof(xChangeWCFPipe.IXData),
obj : svrData,
pipeName : "pName",
pipeAddress : $"PortName{index}"
);
//var svrHost = xChangeWCFPipe.SVR.makeSVR(x: svrData, pipeName: "pName", pipeAddress:$"PortName{index}");
if ( svrHost == null) {
Console.WriteLine("WCF cannot make");
//tokenSource.Cancel();// 処理のキャンセル( throwされる)
lpState.Stop();
return;
} else {
var pgFullName = Assembly.GetExecutingAssembly().Location;
var proc = Ut.Ut.DoCmd(
cmdAndArgs: new string[] { $@"{pgFullName}", "/SubExe", $"PortName{index}" }
, bEcho: false
, bSameConsole: true
);
while (!proc.HasExited) {
// DoCmd()が終了するまで監視
//var dc = svrData.GetData();
System.Threading.Thread.Sleep(2 * 1000);
}
var tmpH = svrData.GetHashData();
if (tmpH == null) {
Console.WriteLine("tmph is null");
}
if ((hashDataTgt != null) && (tmpH != null)) {
//hashDataTgt.Files += tmpH.Files;
Console.WriteLine($@"tempF.Count={tmpH.Files.Count()}");
var merged = hashDataTgt.Files
.Concat(tmpH.Files.Where(pair =>
!hashDataTgt.Files.ContainsKey(pair.Key))
).ToDictionary(
pair => pair.Key,
pair => pair.Value
);
hashDataTgt.Files = new SortedDictionary<string, HashFile>(merged);// hashを合成した。
}
proc.Dispose();
svrHost.Close();
svrData = null;
}
}
//GC.Collect();// これでメモリリークが解決した
count--;
});
if ( !loopResult.IsCompleted ) {
Console.WriteLine("中断");
pm.bMkHash = false;// Hash値保存抑制
}
////tokenSource.Cancel();// 処理のキャンセル
//if ( tokenSource.IsCancellationRequested ) {
// pm.bMkHash = false;// Hash値保存抑制
//}
//};
} else { // NoExeSepa
for (var index = 0; index < pdfPathLstBoth.Count; index++) {
var tgt = Path.Combine(pm.pdfPath, pdfPathLstBoth[index]);
Console.WriteLine($@"tgt={tgt}:{index}/{pdfPathLstBoth.Count}");
if (pm.bFC) {
//比較モード
var reff = Path.Combine(pm.pdfPath2, pdfPathLstBoth[index]);
//Console.WriteLine("<Compare Sync(Paralles) Version!>");
ret = RenderPDF.RenderPdfDocCompare(
pdfPath: Path.GetFullPath(tgt),
refPdfPath: Path.GetFullPath(reff),
inDir: otDir,
pm: rdCond,
inPageRange: pm.pageRange,
inHashDataTgt: hashDataTgt,
inHashDataRef: hashDataRef,
bPDFium: pm.bPDFium
);
} else { // Sync version(Paralles).
ret = RenderPDF.RenderPdfDoc(
pdfPath: Path.GetFullPath(tgt),
inDir: otDir,
pm: rdCond,
inPageRange: pm.pageRange,
bSaveImage: pm.bMkHash ? false : true,// ハッシュ値生成ではイメージ保存しない。
bHash: pm.bHash,// bHash,dumy
inHashData: pm.bMkHash ? hashDataTgt : null, //ハッシュコマンドモードのみDataを渡す
bPDFium: pm.bPDFium
);
}
count--;
GC.Collect();// これでメモリリークが解決した
};
}
if (pm.bMkHash) {
hashDataTgt.save(otHashPath);//ハッシュモードで保存する(Dutyチェックもいるでしょう
}
}
watch.Stop();
Console.WriteLine($"bPDFium={pm.bPDFium},result={ret},time={ watch.ElapsedMilliseconds / 1000.0 }[sec]");
#if COMMNET
Assembly assm = Assembly.GetExecutingAssembly();
Console.WriteLine(assm.FullName);
// 参照しているすべてのアセンブリを取得し、表示する
foreach (AssemblyName refassm in assm.GetReferencedAssemblies()) {
Console.WriteLine($@" {refassm.FullName},Ver({refassm.Version}),VerComp({refassm.VersionCompatibility})" );
}
string clrVersion = System.Environment.Version.ToString();
Console.WriteLine($@"clrVer={clrVersion}");
#endif
return ret;//success.
}
// リソースからの取得
public static class ResData {
public static Stream GetBaseHashPDF(string resName = "CSRender.RES.BaseHash.pdf") {
System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
var sel = from x in asm.GetManifestResourceNames() select resName;
if (sel.Count() == 1) {
return asm.GetManifestResourceStream(sel.First());
}
return null;
}
}
}
}
/// <summary>
/// WCF通信モジュールのラッパクラス。
/// 2つのExe間をWCFパイプモードで通信を行う
/// </summary>
namespace xChangeWCFPipe
{
/// シリアライズ可能にすること
/// </summary>
[ServiceContract]
public interface IXData
{
[OperationContract(IsOneWay = true)]
void Execute();
[OperationContract]
bool SetMessage(string msg);
[OperationContract]
bool SetProgress(int per);//0-100.
[OperationContract]
DataContainer GetData();
[OperationContract]
void SetData(DataContainer d);
[OperationContract]
HashData GetHashData();
[OperationContract]
void SetHashData(HashData d);
[OperationContract]
CSRenderMain.ParamData GetParam();
//CSRenderMain.Program.ParamData GetParam();
}
// ServiceContract https://tnakamura.hatenablog.com/entry/20080606/1220023868
// https://devlights.hatenablog.com/entry/20111023/p2
/// <summary>
/// 通信用複雑データ。スカラー型(int,double,,,.)以外は[DataCOntract]属性を
/// つけて、通知用Interfaceの引数や、返値で利用する
/// </summary>
// 複雑データ
[DataContract]
public class DataContainer
{
[DataMember]
public DataA dataA;
[DataMember]
public DataB dataB;
[DataMember]
public CSRenderMain.ParamData pm;
[DataMember]
public HashData hdata;
}
public class DataA
{
public int a;
}
public class DataB : Inheritance
{
public string b;
}
public abstract class Inheritance
{
public byte[] c;
}
}
namespace xChangeWCFPipe
{
/// <summary>
/// Main(サーバー)側 データ定義
/// </summary>
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
public class XData : IXData
{
private readonly Object LockObj = new object();// 排他制御用
public delegate void callFunc();
public callFunc callDelegate;
public XData() {
_dc.dataA = new DataA();
_dc.dataA.a = 1;
_dc.dataB = new DataB();
_dc.dataB.b = "OK!!!!x";
_dc.dataB.c = new byte[] { 0, 1, 2, 3 };
_dc.pm = new CSRenderMain.ParamData();
_dc.pm.pdfPath = "hoge init path";
}
public void Execute() {
lock (LockObj) {
callDelegate(); // 実装はデリゲートします
}
}
public bool SetMessage(string msg) {
lock (LockObj) {
Console.WriteLine($"SVR:called setMessage({msg}) from CLT");
_msg = msg;
}
return true;
}
public bool SetProgress(int per) {//0-100.
lock (LockObj) {
Console.WriteLine($"SVR:called setProgress({per}) from CLT");
_progress = per;
}
return true;
}
public DataContainer GetData() {
lock (LockObj) {
return _dc;
}
}
public void SetData(DataContainer dc) {
lock (LockObj) {
_dc = dc;
}
}
public void SetHashData(HashData h) {
lock (LockObj) {
_dc.hdata = h;
}
}
public HashData GetHashData() {
lock (LockObj) {
return _dc.hdata;
}
}
//public void SetParam(ParamData pm) {
public void SetParam(CSRenderMain.ParamData pm) {
lock (LockObj) {
Console.WriteLine("w: ParamData");
Console.WriteLine($@"w1:path:{pm.pdfPath}");
_dc.pm = pm;
Console.WriteLine($@"w2:path:{_dc.pm.pdfPath}");
}
}
public CSRenderMain.ParamData GetParam() {
//public CSRenderMain.Program.ParamData GetParam() {
lock (LockObj) {
Console.WriteLine("getParam call");
Console.WriteLine($@"getParam pdfPath={_dc.pm.pdfPath}");
return _dc.pm;
}
}
// private data
private string _msg = "init msg";
private int _progress = 0;// 0-100
public DataContainer _dc = new DataContainer();
}
/// <summary>
/// Main(サーバー)側クラス
/// </summary>
public class SVR
{
// - static -
/// <summary>
/// 通信用のインスタンスを作成する
/// </summary>
/// <param name="x"></param>
/// <param name="pipeName"></param>
/// <param name="pipeAddress"></param>
/// <returns></returns>
static public SVR makeSVR(XData x, string pipeName = "PDFormstudioESorGS", string pipeAddress = "SubModuleAddress") {
return (new SVR(x, pipeName, pipeAddress));
}
// - public I/F -
public void Close() {
Console.WriteLine($"Close Service:{_service!=null},{_serviceHost != null}");
_service = null;
Console.WriteLine("1");
_serviceHost.Close();
Console.WriteLine("2");
}
// - private -
private XData _service = null;// 要らないかも
private ServiceHost _serviceHost = null;
private SVR() { }
private SVR(XData x, string pipeName = "PDFormstudioESorGS", string pipeAddress = "SubModuleAddress") {
const string pipeBase = "net.pipe://localhost";
var uri = pipeBase + "/" + pipeName;
_service = x;
// デリゲート登録
//callDelegate = () => { Console.WriteLine("svr:Delegate func called"); }
#if false
{
// インターフェースを求める
// AddServiceEndpoint()にわたすIXDataはXData.Interfaces()から求められるが
// インタフェースは一つとは限らないのでやめておく。
Type interfType = null;
Type type = _service.GetType();
Type[] interfaces = type.GetInterfaces();
Console.WriteLine($@"GetInterfaces***********************************");
foreach (Type t in interfaces) {
Console.WriteLine(t.ToString());
interfType = t;
};
Console.WriteLine($@"End of GetInterfaces***********************************");
}
#endif
_serviceHost = new ServiceHost(_service, new Uri(uri));
try {
_serviceHost.AddServiceEndpoint(typeof(IXData)/*interfType*/, new NetNamedPipeBinding(), pipeAddress);
_serviceHost.Open();
} catch (AddressAlreadyInUseException) {
Console.WriteLine("既にサービスは起動しています。");
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
}
}
namespace xChangeWCFPipe
{
/// <summary>
/// Sub(クライアント)側クラス
/// </summary>
public class CLT
{
/// <summary>
/// Sub側の初期化処理。Main側とpipeName,pipeAddressを同じにすること
/// </summary>
/// <param name="pipeName"></param>
/// <param name="pipeAddress"></param>
/// <returns></returns>
static public IXData makeCLT(string pipeName = "PDFormstudioESorGS", string pipeAddress = "SubModuleAddress") {
const string pipeBase = "net.pipe://localhost";
var address = pipeBase + "/" + pipeName + "/" + pipeAddress;
//try {
var factory = (new ChannelFactory<IXData>(new NetNamedPipeBinding(), new EndpointAddress(address)));
IXData toMain = factory.CreateChannel();
return toMain;
//} catch (Exception e) {
// Console.WriteLine("makeCLT failed:" + e.ToString());
// return null;
//}
}
}
}
/// <summary>
/// ジェネリック版
/// </summary>
///
#if COMMENT
// インターフェースクラスはサーバーとクライアント両方で参照可能なところに定義する
// 実装データクラスはサーバー内で定義する
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
public class XData : IXData
{
...
}
#endif
namespace xChangeWCFPipeGEN
{
/// <summary>
/// Main(サーバー)側 データ定義
/// </summary>
//[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
//public class XData : IXData
//{
// ...
//}
/// <summary>
/// Main(サーバー)側クラス
/// </summary>
///
public class SVR_T
{
// - static -
/// <summary>
///
/// </summary>
/// <param name="baseIf"> 公開するインターフェースクラス </param>
/// <param name="x">実装インスタンス(baseIfを含むこと)</param>
/// <param name="pipeName"></param>
/// <param name="pipeAddress"></param>
/// <returns></returns>
static public SVR_T makeSVR(Type baseIf, object obj/*XData*/ , string pipeName = "PDFormstudioESorGS", string pipeAddress = "SubModuleAddress") {
Type oType = obj.GetType();
bool hasBaseIf = oType.GetInterfaces().Any(t => (t == baseIf) );
if ( !hasBaseIf) {
Console.WriteLine($@"Error:'{oType.FullName}' have not the interface '{baseIf.FullName}'");//A have not the interface B.
return null;
}
return (new SVR_T(baseIf, obj, pipeName, pipeAddress));
}
// - public I/F -
public void Close() {
Console.WriteLine($"Close Service:{_service != null},{_serviceHost != null}");
_service = null;
_serviceHost.Close();
}
// - private -
private object _service = null;// 要らないかも
private Type _baseIf = null;
private ServiceHost _serviceHost = null;
private SVR_T() { }
private SVR_T(Type baseIf, object oInstance, string pipeName, string pipeAddress) {
const string pipeBase = "net.pipe://localhost";
var uri = pipeBase + "/" + pipeName;
_baseIf = baseIf;
_service = oInstance;
// デリゲート登録
//callDelegate = () => { Console.WriteLine("svr:Delegate func called"); }
#if false
{
// インターフェースを求める
// AddServiceEndpoint()にわたすIXDataはXData.Interfaces()から求められるが
// インタフェースは一つとは限らないのでやめておく。
Type interfType = null;
Type type = _service.GetType();
Type[] interfaces = type.GetInterfaces();
Console.WriteLine($@"GetInterfaces***********************************");
foreach (Type t in interfaces) {
Console.WriteLine(t.ToString());
interfType = t;
};
Console.WriteLine($@"End of GetInterfaces***********************************");
}
#endif
_serviceHost = new ServiceHost(_service, new Uri(uri));
try {
_serviceHost.AddServiceEndpoint(_baseIf/*typeof(Ti)*/, new NetNamedPipeBinding(), pipeAddress);
_serviceHost.Open();
} catch (AddressAlreadyInUseException) {
Console.WriteLine("既にサービスは起動しています。");
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
}
/// <summary>
/// Sub(クライアント)側クラス
/// </summary>
public class CLT_T
{
/// <summary>
/// Sub側の初期化処理。Main側とpipeName,pipeAddressを同じにすること
/// </summary>
/// <param name="pipeName"></param>
/// <param name="pipeAddress"></param>
/// <returns></returns>
static public Ti makeCLT<Ti>(string pipeName = "PDFormstudioESorGS", string pipeAddress = "SubModuleAddress") {
const string pipeBase = "net.pipe://localhost";
var address = pipeBase + "/" + pipeName + "/" + pipeAddress;
//try {
var factory = (new ChannelFactory<Ti>(new NetNamedPipeBinding(), new EndpointAddress(address)));
Ti toMain = factory.CreateChannel();
return toMain;
//} catch (Exception e) {
// Console.WriteLine("makeCLT failed:" + e.ToString());
// return null;
//}
}
}
}
namespace Ut
{
public class Ut
{
// Util
// --------------------------------------------------------------
/// <summary>
/// 親プロセスが終了したら、自身を終了させる
/// </summary>
/// <param name="bEnable"></param>
public static void SetAutoSelfKillByMainProcEnd(bool bEnable = true) {
if (_SingletonProc != null)
return;//一度しか呼び出せない
if (bEnable == false)
return;
const string fname = "SetAutoSelfKillByMainProcEnd";
// 自動的に親のプロセスがいなくなったら自動的にキルモードを設定する
// メインプロセスの終了チェック
// 親プロセスIDでProcessハンドルを取得、そのExitedイベントに自身の終了関数を設定(Environment.Exit())
int paProcID = GetParentProcessId();
var paProc = Process.GetProcessById(paProcID);
paProc.EnableRaisingEvents = true;
Console.WriteLine($@"{fname}:ParrentProcessName ={paProc.ProcessName}({paProcID})");
paProc.Exited += new EventHandler(
(object s, EventArgs a) => {
Console.WriteLine($@"{fname}:Exited Event!!!!");
var ss = s as Process;
Console.WriteLine($@"Sure ProcName is {ss.ProcessName}({ss.Id}) {ss.StartInfo.Arguments}"); ;
System.Threading.Thread.Sleep(10 * 1000);
ss.Close();
ss.Dispose();
Console.WriteLine($@"{fname}:Exited Event!!!!(afer10sec)");
//Environment.Exit(-1);
});
//
_SingletonProc = paProc;
}
private static System.Diagnostics.Process _SingletonProc = null;
/// <summary>
/// コマンドライン引数複数個をエンコードして、スペースで結合
/// </summary>
/// <param name="values">string[] コマンドライン引数</param>
/// <returns>コマンドライン文字列(Escaped)</returns>
public static string makeCmdLine(IEnumerable<string> args) {
if (args == null)
throw new ArgumentNullException("args");
string EscapeCmdLineArg(string v) {
if (string.IsNullOrEmpty(v)) return "";
var containsSpace = v.IndexOfAny(new[] { ' ', '\t' }) != -1;
v = ReCommandLineEscapePattern.Replace(v, @"$1\$&");//「\…\"」をエスケープ.「"」直前の「\」の数を 2倍+1
if (containsSpace) {
v = "\"" + ReLastBackSlashPattern.Replace(v, "$1$1") + "\"";
}
return v;
}
return string.Join(" ", args.Select(v => EscapeCmdLineArg(v)));
}
private static Regex ReCommandLineEscapePattern = new Regex("(\\\\*)\"");
private static Regex ReLastBackSlashPattern = new Regex(@"(\\+)$");
/// <summary>
/// 親のプロセスIDを取得する
/// </summary>
/// <returns>親ProcessID</returns>
static int GetParentProcessId() {
var myProcId = GetCurrentProcessId();
var query = string.Format($@"SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = {myProcId}");
//クエリから結果を取得
using (var search = new System.Management.ManagementObjectSearcher(@"root\CIMV2", query))
using (var results = search.Get().GetEnumerator()) {
if (!results.MoveNext())
throw new ApplicationException("Couldn't Get ParrentProcessId.");
var queryResult = results.Current;
//親プロセスのPIDを取得
uint pa = (uint)(queryResult["ParentProcessId"]);
return (int)(pa);
}
}
/// <summary>
/// 自身のプロセスIDを取得する
/// </summary>
/// <returns>ProcessID</returns>
static int GetCurrentProcessId() { return Process.GetCurrentProcess().Id; }
/// <summary>
/// 外部プログラムを起動する
/// </summary>
/// <param name="cmdAndArgs">引数文字列の配列</param>
/// <param name="bSameConsole">true:コンソールを呼び出しと共有 false:別Console Windows</param>
/// <param name="bEcho">標準出力(未実装)</param>
/// <param name="bWait">コマンドが終了するまで待つ(false:未実装,常に待つ)</param>
/// <param name="nWaitLimitMSec">タイムアウト時間ms(未実装)</param>
/// <returns></returns>
public static Process DoCmd(IEnumerable<string> cmdAndArgs, bool bSameConsole = true, bool bEcho = true, bool bWait = false, int nWaitLimitMSec = -1) {
var cmdName = cmdAndArgs.First();//[0];
var argStr = makeCmdLine(cmdAndArgs.Skip(1));// 先頭を除外してコピー new ArraySegment<string>(cmdAndArgs.ToArray(), 1, cmdAndArgs.Count()-1)
Console.WriteLine($@"DoCmd:{cmdName}:args[{argStr}]");
//using (var p = new Process()) {
var p = new Process();
{
var info = p.StartInfo;
p.StartInfo.FileName = cmdName;
p.StartInfo.Arguments = argStr;
if (bSameConsole) {
Console.WriteLine("same windows mode");
p.StartInfo.UseShellExecute = false; // Shell経由で実行しない(必須) true: 別ウインドウ。false:コンソールを共有
p.StartInfo.CreateNoWindow = false; // ウィンドウを作成しない
} else {
Console.WriteLine("new windows mode");
p.StartInfo.UseShellExecute = true;
p.StartInfo.CreateNoWindow = true;
}
p.Start();// 実行
if (bWait == false) {
return p;
}
if (nWaitLimitMSec == -1) {
p.WaitForExit();// タイムアウト無し
} else {
bool bExit = p.WaitForExit(nWaitLimitMSec);
if (!bExit) {// 処理の終了を待つ
Console.WriteLine("処理が終了しないので強制終了");
p.Kill(); // 強制終了する
return p;
}
}
return p;
}
}
}
}
\ No newline at end of file
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Reflection; // Assembly.
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Collections.ObjectModel;
using System.Runtime.InteropServices;
// for Stream conv.
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Storage.Streams;
//using System.IO.WindowsRuntimeStreamExtensions;
//
//using Codeplex.Data; // DynamicJson
// UWP-APIの使用
using Windows.Data.Pdf;
// PDFiumの追加
using PdfiumViewer;
using static CSRender.RenderPDF;
//https://proself2.screen.co.jp/public/OcyIQAHPksNAnE4Bs3BxIPQApnAEmSCIBOxsCZ946Uur
//Screen8080
//1_A4縦_2×1_両面_可変長レコード.pdf
// TOshiba:
//#region アセンブリ Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime
// C:\UserData\GIT_JSH\WinRT\CSRender\CSRender\bin\Debug\Windows.winmd
// WindowsRuntime 1.3
//#endregion
// MacBookPro:
// WindowsRuntime 1.4
//CSRender, Version=1.1.0.0, Culture=neutral, PublicKeyToken=null
// mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089,Ver(4.0.0.0),VerComp(SameMachine)
// System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089,Ver(4.0.0.0),VerComp(SameMachine)
// Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime,Ver(255.255.255.255),VerComp(SameMachine)
// System.Runtime.WindowsRuntime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089,Ver(4.0.0.0),VerComp(SameMachine)
// System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,Ver(4.0.0.0),VerComp(SameMachine)
// System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089,Ver(4.0.0.0),VerComp(SameMachine)
// System.Runtime.Serialization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089,Ver(4.0.0.0),VerComp(SameMachine)
// clrVer=4.0.30319.42000
// 参考: zoomパレメータなど
// https://www.syncfusion.com/kb/8767/how-to-print-pdf-documents-in-xamarin-forms-platform
//var DisplayInformation = Windows.Graphics.Display.DisplayInformation.GetForCurrentView();
//var dpi = DisplayInformation.LogicalDpi / 96;
// https://elesynd.blogspot.com/2018/11/hDpiForm.html
//Program.csでDPIAwareする
//FormクラスのAutoScaleModeをUIを使って"Dpi"に変更する
//それでもズレるコントロールは、FontをUIを使って明示的に指定してみる
// https://qiita.com/felis_silv/items/efee4b1a397b0b95100a
// スケーリング grph.FromImage(bmp)後にスケール
namespace CSRender {
#pragma warning disable IDE1006 // 小文字のメソッド含む
static public class Check
{
//https://gist.github.com/retorillo/4e0c4a3cf4c7096e05ac
static public bool bDump = false;
static public bool bThDump = false;
const int LOGPIXELSX = 88;
const int LOGPIXELSY = 90;
//
//
const int HORZSIZE = 4;//物理画面の幅・高さ(ミリメートル単位)
const int VERTSIZE = 5;
const int HORZRES = 8; //画面の幅・高さ(ピクセル単位)
const int VERZRES = 10;
//
const int RASTERCAPS = 38;
// 返却値のマスク
//1 (RC_BITBLT) ビットマップの転送
//2 (RC_BANDING) バンド処理のサポートが必要
//4 (RC_SCALING) スケーリング
//8 (RC_BITMAP64) 64KB より大きいビットマップ
//0x0080 (RC_DI_BITMAP) SetDIBits 関数と GetDIBits 関数
//0x0100 (RC_PALETTE) デバイスはパレットベースのデバイスである
//0x0200 (RC_DIBTODEV) SetDIBitsToDevice 関数
//0x0800 (RC_STRETCHBLT) StretchBlt 関数
//0x1000 (RC_FLOODFILL) 塗りつぶし
//0x2000 (RC_STRETCHDIB) StretchDIBits 関数
const int SCALINGFACTORX = 114;//x 軸・ y 軸のスケーリングファクター
const int SCALINGFACTORY = 115;
[DllImport("user32.dll")]
extern static bool SetProcessDPIAware();
[DllImport("user32.dll")]
extern static IntPtr GetWindowDC(IntPtr hwnd);
[DllImport("gdi32.dll")]
extern static int GetDeviceCaps(IntPtr hdc, int index);
[DllImport("user32.dll")]
extern static int ReleaseDC(IntPtr hwnd, IntPtr hdc);
public static int GetDPI() {
//return 96;
SetProcessDPIAware();// もしくはdpiAwareをマニフェストで設定すればよい。
var dc = GetWindowDC(IntPtr.Zero);
var dpi = GetDeviceCaps(dc, LOGPIXELSX);
if ( bDump ) {
Console.WriteLine("DpiX: {0}", GetDeviceCaps(dc, LOGPIXELSX));
Console.WriteLine("DpiY: {0}", GetDeviceCaps(dc, LOGPIXELSY));
Console.WriteLine("SCALINGFACTORYX: {0}", GetDeviceCaps(dc, SCALINGFACTORX));
Console.WriteLine("SCALINGFACTORY: {0}", GetDeviceCaps(dc, SCALINGFACTORY));
//if ( false ) {// これは倍率で変更されない
// int width = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width; // 幅(pixel)
// int height = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height; // 高さ(pixel)
// // 取得したスクリーンのサイズをコンソールに出力する
// string message = string.Format("This screen size is {0} x {1} (pixel)", width, height);
// System.Console.WriteLine(message);
//}
//if (false){// コンソールアプリでは呼び出せない
// var di = Windows.Graphics.Display.DisplayInformation.GetForCurrentView();
// Console.WriteLine($@"di.LogicalDpi: {di.LogicalDpi}");
// Console.WriteLine($@"di.RawDpiX: {di.RawDpiX}");
// Console.WriteLine($@"di.ResoSacle: {di.ResolutionScale.ToString()}");
// Console.WriteLine($@"di.StereoEnabled: {di.StereoEnabled}");
// Console.WriteLine($@"di: {di.ToString()}");
//}
}
ReleaseDC(IntPtr.Zero, dc);
return dpi;// 96;// dpi;
}
}
public static class RenderPDF
{
/// <summary>
/// Rendering Condition
/// </summary>
[DataContract]
public class RenderConditionParams
{
[DataMember(Order = 0)]
public double Dpi = 72.0;
[DataMember(Order = 1)]
public string BoxType = "Crop";
[DataMember(Order = 2)]
public string ImageType = "JPEG";
[DataMember(Order = 3)]
public int JpegQ = 91;
// Method non
}
// Verbose
public static void setEcho(bool b) {
bEcho = b;
}
public static bool bEcho = false;
public static void echo(params object[] args) {
if (!bEcho) return;
var s = "";
foreach (object a in args) {
s += a.ToString();
}
Console.WriteLine(s);
}
// 事前チェック BashHash
public static bool RenderPdfInitCheck( Stream stream /* PDFストリーム */) {
Windows.Storage.Streams.InMemoryRandomAccessStream rmStrageStream=null;
{// Stream->Memstream -> byte array -> IBuffer -> InMemmory...Stream()
var ms = new MemoryStream();
stream.CopyTo(ms);
var bAray = ms.ToArray();
IBuffer ib = bAray.AsBuffer();
rmStrageStream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
//await s.WriteAsync(ib);
async Task<uint> wa() => await rmStrageStream.WriteAsync(ib);
var wa_ret = wa().Result;
}
async Task<Windows.Data.Pdf.PdfDocument> LoadS() => await Windows.Data.Pdf.PdfDocument.LoadFromStreamAsync(rmStrageStream);
var pdfDoc = LoadS().Result;
if (pdfDoc == null) {
Console.WriteLine("error: get PdfDocument failed");
return false;
}
// var memStream = new MemoryStream();
// memStream.AsInputStream();
// WindowsRuntimeStreamExtensions.
// var ras = WindowsRuntimeStreamExtensions.AsRandomAccessStream(stream);
//https://blog.ch3cooh.jp/entry/20131207/1386342000
//https://csharp.hotexamples.com/site/file?hash=0xe951daae5be57f9f35507c45eb09a1085819b0a42b846aaa211ac138a2d1b5af&fullName=src/Nutrition/Nutrition.WP/WPOCRService.cs&project=SamirHafez/Nutrition
//なんだけどな。。。→ .NetFrameworkにAsRandomAccessStream(x)が存在しない。.Net Coreのみみたい。
// exeと同一場所に"baseRender.jpg"
string otPath = Path.Combine(Directory.GetParent(Assembly.GetEntryAssembly().Location).FullName,"baseRender.jpg");
bool bSaveImage = false;// Debug時にtrueにする
Console.WriteLine($"mode=Hash base check");
var taskList = new List<Task<int>>();
var hashValue = "";
var pm = new RenderConditionParams();
var ret = RenderPage(
doc: pdfDoc,
page: pdfDoc.GetPage(0),
otPath: otPath,
pm:pm,
bSaveImage: bSaveImage,
bHash: true,
otHashCode: ref hashValue
);
Console.WriteLine($@"Hash={hashValue},Host={Environment.MachineName},{Environment.OSVersion}");
return true;// true:OK, false:NG
}
// Sync version( no async -> Pallale Task ) **************************************************************************************
/// <summary>
/// PDFのレンダリング
/// </summary>
/// <param name="pdfPath"></param>
/// <param name="inDir"></param>
/// <param name="pm">レンダリングの条件</param>
/// <param name="inPageRange"></param>
/// <param name="inMode"></param>
/// <param name="bSaveImage"></param>
/// <param name="bHash">未使用,常にtrueで使用</param>
/// <param name="inHashData"></param>
/// <returns></returns>
public static int RenderPdfDoc(
string pdfPath,
string inDir = "",
RenderConditionParams pm = null,
string inPageRange = "1-*",
string inMode = "pageBitMap",
bool bSaveImage = true, //ハッシュ値のみ計算するときにfalseにする
bool bHash = false,
UtHash.HashData inHashData = null,
bool bPDFium = false
) {
if (pm == null) {
pm = new RenderConditionParams();
}
var otDir = inDir;
var otBaseName = Path.GetFileName(pdfPath);//*.pdf
var otExtention = pm.ImageType.ToLower();
if (bSaveImage && otDir == "") {
// 出力ディレクトリが空→元PDFの同一フォルダにIMGフォルダを作成する
otDir = Path.Combine(Directory.GetParent(pdfPath).FullName, "IMG");
if (!Directory.Exists(otDir))
Directory.CreateDirectory(otDir);
}
// PDFファイルを読み込む
async Task<Windows.Storage.StorageFile> GetStrageFilePath(string path)
=> await Windows.Storage.StorageFile.GetFileFromPathAsync(path);
var file = GetStrageFilePath(pdfPath).Result;
async Task<Windows.Data.Pdf.PdfDocument> Load(Windows.Storage.StorageFile path)
=> await Windows.Data.Pdf.PdfDocument.LoadFromFileAsync(file);
var pdfDoc = Load(file).Result;
// 2つを合わせることができそう
//async Task<Windows.Data.Pdf.PdfDocument> GetLoadFromPath(string path)
//{
// var a1 = await Windows.Storage.StorageFile.GetFileFromPathAsync(path);
// var a2 = await Windows.Data.Pdf.PdfDocument.LoadFromFileAsync(a1);
// return a2;
//};
//var pdfDoc2 = GetLoadFromPath(pdfPath).Result;
if (pdfDoc == null) {
Console.WriteLine("error: get PdfDocument failed");
return -1;
}
var n = pdfDoc.PageCount;
inMode = "pageBitMap";
//Console.WriteLine($"mode={inMode},bPDFium={bPDFium}");
var taskList = new List<Task<int>>();
uint[] rNo = makePageRange(inPageRange, pdfDoc.PageCount);
if (inHashData != null) {
// ハッシュ対象の最大ページ数の設定必須。
inHashData.SetFile(pdfPath, (int)pdfDoc.PageCount);
}
// PDFiumViewer
PdfiumViewer.PdfDocument docG = null;
if (bPDFium) {
docG = PdfiumViewer.PdfDocument.Load(pdfPath);
}
//Console.WriteLine($@"dpi={pm.Dpi}");
/////並行処理するスレッド数を指定(2-4ぐらいが穏便な数値)
ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = 4 };
Parallel.ForEach(rNo, options, i => {
//Console.WriteLine($"*****{i}*****/{rNo.Length}");
var hashValue = "";
var ret = RenderPage(
doc: pdfDoc,
page: pdfDoc.GetPage((uint)(i - 1)),
otPath: Path.Combine(otDir, $"{otBaseName}.{i}.{otExtention}"),
pm: pm,
bSaveImage: bSaveImage, // ファイル保存
bHash: bHash,
otHashCode: ref hashValue,
docG : docG
);
if (inHashData != null) {
lock (inHashData) {
inHashData.AddHashCode(pdfPath, (int)i, hashValue);
}
}
});
if ( docG != null)
docG.Dispose();
return (int)pdfDoc.PageCount;// ページ数を返却します
//return 0;// success.
}
/// <summary>
/// pdfのページを画像に出力する
/// </summary>
/// <param name="doc">PdfDocument</param>
/// <param name="nPage">ページ番号</param>
/// <param name="otPath">出力ファイル名</param>
/// <returns>正常:0 </returns>
public static int RenderPage(
// Need:
Windows.Data.Pdf.PdfDocument doc, // Need GetPage() only. (Total page number);
PdfPage page, // Target Page Data(page.index:0-x)
string otPath,
ref string otHashCode,
// Optional:
RenderConditionParams pm = null,
bool bSaveImage = true,// ファイル保存有無。ハッシュ値計算のみのときにfalseにする
bool bHash = false,
PdfiumViewer.PdfDocument docG = null //
){
if( pm == null) {
pm = new RenderConditionParams();
}
double dpiWin = Check.GetDPI(); //96.0;/* , dpiPDF = 72.0*/
//double resoScale = (96.0 / dpiWin);
double resoScale = (pm.Dpi / 96.0);
//double resoScale = (inDpi / dpiWin);
var bDump = Check.bDump;
var bThDump = Check.bThDump;
var opt = new PdfPageRenderOptions() {
// SEE:https://github.com/microsoft/Windows-universal-samples/blob/master/Samples/PdfDocument/cs/Scenario1_Render.xaml.cs
//BitmapEncoderId = Windows.Graphics.Imaging.BitmapEncoder.JpegEncoderId,// JPEG
IsIgnoringHighContrast = false
};
var boxDic = new Dictionary<string, Windows.Foundation.Rect>() {
// Init
["Media"] = page.Dimensions.MediaBox,
["Trim"] = page.Dimensions.TrimBox,
["Bleed"] = page.Dimensions.BleedBox,
["Crop"] = page.Dimensions.CropBox,
["Art"] = page.Dimensions.ArtBox
};
//Dump:
if ( bDump){
Console.WriteLine($@"PageZoom={page.PreferredZoom}");
Console.WriteLine($@"PageRotate={page.Rotation.ToString()}");
Console.WriteLine($"{"Size",-5}=({page.Size.Width,8:f2},{page.Size.Height,8:f2})");
foreach (var b in boxDic.Keys) {
var r = boxDic[b];
Console.WriteLine($"{b,-5}=({r.X,8:f2},{r.Y,8:f2}) W({r.Width,8:f2},{r.Height,8:f2})");
Console.WriteLine($"{b,-5}=L {r.Left,-8:f2} R {r.Right,-8:f2}) T {r.Top,-8:f2} B {r.Bottom,-8:f2})");
}
}
opt.SourceRect = boxDic.ContainsKey(pm.BoxType) ? boxDic[pm.BoxType] : boxDic["Crop"];// Cannot find -> "Crop";
//Console.WriteLine($"Select {inBoxType} box.");
// 何も変倍しないとどうなる
opt.DestinationWidth = (uint)(opt.SourceRect.Width * resoScale + 0.5);
opt.DestinationHeight = (uint)(opt.SourceRect.Height * resoScale + 0.5);
// 150%の時は * 0.5358を設定するとよい解像度になるが、この数値の計算方法がわからない
//opt.DestinationWidth = (uint)(opt.SourceRect.Width * 0.5358/*resoScale*/ + 0.5);
//opt.DestinationHeight = (uint)(opt.SourceRect.Height * 0.5358/*resoScale*/ + 0.5);
if (bDump) {
Console.WriteLine($"dpi={pm.Dpi},scale={resoScale},width(org)={page.Size.Width}->{opt.DestinationWidth}");
Console.WriteLine($"dpi={pm.Dpi},scale={resoScale},height(org)={page.Size.Height}->{opt.DestinationHeight}");
}
using (var memStrm = new Windows.Storage.Streams.InMemoryRandomAccessStream()) {
if (docG == null) {
async Task RenderToStream(PdfPage p) => await p.RenderToStreamAsync(memStrm, opt);
RenderToStream(page).Wait();
} else {
PdfRenderFlags flg = (PdfRenderFlags.ForPrinting | PdfRenderFlags.CorrectFromDpi);
System.Drawing.Image img = docG.Render((int)(page.Index), (float)pm.Dpi, (float)pm.Dpi, flg);
img.Save(memStrm.AsStream(), System.Drawing.Imaging.ImageFormat.Jpeg);
// [注意] PDFuim用に直接 AsStream()に書き込んでいるので、AsStream().Flush()しないとだめです
}
async Task<bool> FlushX() => await memStrm.FlushAsync();
FlushX().Wait();
var bmp = new System.Drawing.Bitmap(memStrm.AsStream());
if (bDump) {
Console.WriteLine($"bmp=w:{bmp.Size.Width},h:{bmp.Size.Height}");
}
//Console.WriteLine($"OrgReso({bmp.HorizontalResolution},{bmp.VerticalResolution})");
if (bHash) {
var h =GetHashValue(memStrm);
//Console.WriteLine($"HashString:{h}");
otHashCode = h;
}
var th = Thread.CurrentThread.ManagedThreadId;
if ( !bSaveImage ) { //ファイル保存しない.ハッシュ計算のみ
if ( bThDump ) {
Console.WriteLine($"ot[th{th},{(page.Index + 1)}/{doc.PageCount}]=,{Path.GetFileName(otPath)},hash:{otHashCode}");
}
return 0;
}
var imEnc = new UtImage.Enc(pm.ImageType) { JpegQuality = pm.JpegQ };// Init membrers.
bmp.SetResolution((float)pm.Dpi, (float)pm.Dpi);
if (bThDump) {
Console.WriteLine($"ot[th{th},{(page.Index + 1)}/{doc.PageCount}]={Path.GetFileName(otPath)}({Directory.GetParent(otPath)})");
}
//
imEnc.SaveImage(bmp, otPath);
//
bmp.Dispose();
//memStrm.Seek(0);
}
return 0;//success
}
// Sync version( 比較モード(/FC ) **************************************************************************************
/// <summary>
/// レンダリング(比較モード)
/// </summary>
/// <param name="pdfPath"></param>
/// <param name="refPdfPath"></param>
/// <param name="inDir"></param>
/// <param name="pm">レンダリング条件</param>
/// <param name="inPageRange"></param>
/// <param name="inMode"></param>
/// <param name="bHash">未使用常にtrueで利用する</param>
/// <param name="inHashDataTgt"></param>
/// <param name="inHashDataRef"></param>
/// <returns>一致した場合は0、不一致の場合は!0を返却する</returns>
public static int RenderPdfDocCompare(
string pdfPath,
string refPdfPath,
string resultDataPath,
string inDir = "",
RenderConditionParams pm = null,
string inPageRange = "1-*",
string inMode = "pageBitMap",
bool bHash = false,
UtHash.HashData inHashDataTgt = null,
UtHash.HashData inHashDataRef = null,
bool bPDFium = false
// 比較結果を返す ページ番号とメッセージ
) {
var bDump = Check.bDump;
var bThDump = Check.bThDump;
if(bDump)
Console.WriteLine("RenderPdfDocCompare & diff Image! & non Para");
if (pm == null)
pm = new RenderConditionParams();
var otDir = inDir;// 今は未使用
var otBaseName = Path.GetFileName(pdfPath);//xxx.pdf
var otExtention = pm.ImageType.ToLower();
if (otDir == "") {
// 出力ディレクトリが空→元PDFの同一フォルダにIMGフォルダを作成する
otDir = Path.Combine(Directory.GetParent(pdfPath).FullName, "IMG");
if (!Directory.Exists(otDir))
Directory.CreateDirectory(otDir);
}
// PDFファイルを読み込む
// 以下のコードで良いみたい。
// [変更待ち] var file2 = Windows.Storage.StorageFile.GetFileFromPathAsync(pdfPath).GetAwaiter().GetResult();
async Task<Windows.Storage.StorageFile> GetStrageFilePath(string path)
=> await Windows.Storage.StorageFile.GetFileFromPathAsync(path);
var file = GetStrageFilePath(pdfPath).Result;
async Task<Windows.Data.Pdf.PdfDocument> Load(Windows.Storage.StorageFile path)
=> await Windows.Data.Pdf.PdfDocument.LoadFromFileAsync(path);
var pdfDoc = Load(file).Result;
if (pdfDoc == null) {
Console.WriteLine("error: get PdfDocument failed");
return -1;
}
// ref
var fileRef = GetStrageFilePath(refPdfPath).Result;
var pdfDocRef = Load(fileRef).Result;
if (pdfDocRef == null) {
Console.WriteLine("error: get PdfDocument(ref) failed");
return -1;
}
var n = pdfDoc.PageCount;
if ( n != pdfDocRef.PageCount) {
Console.WriteLine($"error: differ page length:{n}:{pdfDocRef.PageCount}");
return -1;
}
uint[] rNo = makePageRange(inPageRange, n);
int nRetAll = 0;// 一致(def)
// ハッシュ情報の確認
/*
- 双方のハッシュ値が存在するか確認
- tgtののみなら、refのrender
- refのみなら、tgtのみrender
- とう感じ
*/
UtHash.HashFile tgtHf=null;
if (inHashDataTgt!=null) {
var f = Path.GetFileName(pdfPath);
if (inHashDataTgt.Files.ContainsKey(f)) {
tgtHf = inHashDataTgt.Files[f];
}
}
UtHash.HashFile refHf = null;
if (inHashDataRef != null) {
var f = Path.GetFileName(refPdfPath);
if ( inHashDataRef.Files.ContainsKey(f) ) {
refHf = inHashDataRef.Files[f];
}
}
Console.WriteLine($@"UsingHashFile:tgt({(tgtHf==null?0:1)}),ref({(refHf == null ? 0 : 1)})");
// tgtHf,refHfを構築完了
var fcResultMsg = new SortedDictionary<int,string>();// 比較結果を返す ページ番号とメッセージ
// PDFiumViewer
PdfiumViewer.PdfDocument docG = null;
PdfiumViewer.PdfDocument docGRef = null;
if (bPDFium) {
docG = PdfiumViewer.PdfDocument.Load(pdfPath);
docGRef = PdfiumViewer.PdfDocument.Load(refPdfPath);
}
/////並行処理するスレッド数を指定(2-4ぐらいが穏便な数値)
ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = 4 };
Parallel.ForEach(rNo, options, i => {
Windows.Storage.Streams.InMemoryRandomAccessStream tgtStrm = null, refStrm = null;
string tgtHash = "", refHash = "";
// ターゲット レンダー
InMemoryRandomAccessStream RendPageTGT() {
var strm = RenderPageStream(doc:pdfDoc,page:pdfDoc.GetPage((uint)(i-1)), pm:pm,docG:docG);
return strm;
}
// リファレンス レンダー
InMemoryRandomAccessStream RendPageREF() {
var strm = RenderPageStream(doc:pdfDocRef,page:pdfDocRef.GetPage((uint)(i-1)), pm:pm,docG:docGRef);
return strm;
}
//tgtStrm = RendPageTGT();
if (tgtHf == null) {
tgtStrm = RendPageTGT();
tgtHash = GetHashValue(tgtStrm);
} else {
lock (inHashDataTgt) {
tgtHash = tgtHf.GetHashValue((int)(i - 1));
}
}
// リファレンス
if (refHf == null) {
refStrm = RendPageREF();
refHash = GetHashValue(refStrm);
} else {
lock (inHashDataRef) {
refHash = refHf.GetHashValue((int)(i - 1));
}
}
// compare stream;
int nRet = 1;//異なる(def).
var dateStr = DateTime.Now.ToString();
//Console.WriteLine($@"tgt={i}:{tgtHash}");
//Console.WriteLine($@"ref={i}:{refHash}");
if (tgtHash != refHash) {
nRet = 1;
nRetAll = nRet;//全体の不一致設定
echo($"{i}:NotMatch:{i},tgt[{tgtHash}],ref[{refHash}]");
//2020年3月2日 15:23:55:[@Difference]:<fullpath>.diff.jpg
lock (fcResultMsg) {
fcResultMsg.Add((int)i, $@"{dateStr}:[@Difference]:{pdfPath}.diff.jpg");
}
//if ( true && tgtStrm != null && bSave) {
{
echo("***** save diff image");
// diffのjpegを書き出してみる(tgt)
if (tgtStrm == null) tgtStrm = RendPageTGT();
var otPath = Path.Combine(otDir, $"{otBaseName}.{i}.tgt.{otExtention}");
var bmp = new System.Drawing.Bitmap(tgtStrm.AsStream());
var imEnc = new UtImage.Enc(pm.ImageType) { JpegQuality = pm.JpegQ };// Init membrers.
bmp.SetResolution((float)pm.Dpi, (float)pm.Dpi);
imEnc.SaveImage(bmp, otPath);
bmp.Dispose();
}
//if (true && refStrm != null && bSave) {
{
// diffのjpegを書き出してみる(ref)
if (refStrm == null) refStrm = RendPageREF();
var otPath = Path.Combine(otDir, $"{otBaseName}.{i}.ref.{otExtention}");
var bmp = new System.Drawing.Bitmap(refStrm.AsStream());
var imEnc = new UtImage.Enc(pm.ImageType) { JpegQuality = pm.JpegQ };// Init membrers.
bmp.SetResolution((float)pm.Dpi, (float)pm.Dpi);
imEnc.SaveImage(bmp, otPath);
bmp.Dispose();
}
} else {
nRet = 0;// match
//Console.WriteLine($"{i}:Match:{i}");
// 2019年12月18日 19:31:38:[OK]:fname.pdf.1.png
lock (fcResultMsg) {
fcResultMsg.Add((int)i, $@"{dateStr}:[OK]:{Path.GetFileName(pdfPath)}.{i}.png");
}
}
// dispose:
if (refStrm != null) refStrm.Dispose();
if (tgtStrm != null) tgtStrm.Dispose();
});
if ( docG != null)
docG.Dispose();
if (docGRef != null)
docGRef.Dispose();
// まとめて表示
foreach ( var v in fcResultMsg){
Console.WriteLine("@CMP@"+v.Value);
}
if (resultDataPath != "") {
// まとめて書き出し
var resCont =($"{pdfPath}\n");
foreach (var v in fcResultMsg) {
resCont += ("@CMP@" + v.Value) + "\n";
}
File.AppendAllText(resultDataPath, resCont);
}
return nRetAll;// success.
}
/// <summary>
/// 比較モード
/// </summary>
/// <param name="doc">PdfDocument</param>
/// <param name="nPage">ページ番号</param>
/// <param name="otPath">出力ファイル名</param>
/// <returns>正常:0 </returns>
public static Windows.Storage.Streams.InMemoryRandomAccessStream RenderPageStream(
// Need:
Windows.Data.Pdf.PdfDocument doc, // Need GetPage() only. (Total page number);
PdfPage page, // Target Page Data(page.index:0-x)
//string otPath,
// Optional:
RenderConditionParams pm = null,
PdfiumViewer.PdfDocument docG = null //
) {
var bDump = Check.bDump;
var bThDump = Check.bThDump;
if (pm == null)
pm = new RenderConditionParams();
double dpiWin = Check.GetDPI(); //96.0;/* , dpiPDF = 72.0*/
double resoScale = (pm.Dpi / dpiWin);
var opt = new PdfPageRenderOptions() {
// SEE:https://github.com/microsoft/Windows-universal-samples/blob/master/Samples/PdfDocument/cs/Scenario1_Render.xaml.cs
//BitmapEncoderId = Windows.Graphics.Imaging.BitmapEncoder.JpegEncoderId,// JPEG
IsIgnoringHighContrast = false
};
//
//async Task PreparePage(PdfPage p) => await p.PreparePageAsync();//ページの完成を待つ
//PreparePage(page).Wait();
//page.PreparePageAsync
var boxDic = new Dictionary<string, Windows.Foundation.Rect>() {
// Init
["Media"] = page.Dimensions.MediaBox,
["Trim"] = page.Dimensions.TrimBox,
["Bleed"] = page.Dimensions.BleedBox,
["Crop"] = page.Dimensions.CropBox,
["Art"] = page.Dimensions.ArtBox
};
opt.SourceRect = boxDic.ContainsKey(pm.BoxType) ? boxDic[pm.BoxType] : boxDic["Crop"];// Cannot find -> "Crop";
opt.DestinationWidth = (uint)(opt.SourceRect.Width * resoScale + 0.5);
opt.DestinationHeight = (uint)(opt.SourceRect.Height * resoScale + 0.5);
if (bDump)
Console.WriteLine($"dpi={pm.Dpi},scale={resoScale},height(org)={page.Size.Height}->{opt.DestinationHeight}");
var memStrm = new Windows.Storage.Streams.InMemoryRandomAccessStream();
if(true) {
if (docG == null) {
async Task RenderToStream(PdfPage p) => await p.RenderToStreamAsync(memStrm, opt);
RenderToStream(page).Wait();
} else {
PdfRenderFlags flg = (PdfRenderFlags.ForPrinting | PdfRenderFlags.CorrectFromDpi);
System.Drawing.Image img = docG.Render((int)(page.Index), (float)pm.Dpi, (float)pm.Dpi, flg);
img.Save(memStrm.AsStream(), System.Drawing.Imaging.ImageFormat.Jpeg);
// [注意] PDFuim用に直接 AsStream()に書き込んでいるので、AsStream().Flush()しないとだめです
memStrm.AsStream().Flush();
}
async Task<bool> FlushX() => await memStrm.FlushAsync();
//var dmy =FlushX().Result;
FlushX().Wait();
}
//page.Dispose();
return memStrm;//
}
/// <summary>
/// ページ1から始まるページ範囲の配列を返す
/// </summary>
/// <param name="pageRange"></param>
/// <param name="maxPage"></param>
/// <returns></returns>
private static uint[] makePageRange(string pageRange = "1", uint endPage = 100) {
var range = new SortedSet<uint>();
var vec = pageRange.Split(',');//カンマで分割
var reRange = new Regex($@"([\d]+)[\s]*\-[\s]*([\d]*|\*)");// n-m or n- or n-*
var reOne = new Regex($@"([\d]+)"); // n
bool isRange(uint x) => (0 < x && x <= endPage); // 範囲チェック
void swap<T>(ref T a, ref T b) { T tmp = a; a = b; b = tmp; }
foreach (var s in vec) {
//範囲指定
var m = reRange.Match(s);
if (m.Success) {
uint st = uint.Parse(m.Groups[1].Value);
uint en = 0;
if (!isRange(st))
continue;//開始値が範囲外で無効
uint.TryParse(m.Groups[2].Value, out en);
if (!isRange(en))
en = endPage;// 最終値が無効なため最終ページ
if (st > en) swap(ref st, ref en);
// 範囲登録
foreach (var g in Enumerable.Range((int)st, (int)(en - st + 1)))
range.Add((uint)g);
continue;
}
//ページ指定
m = reOne.Match(s);
if (m.Success) {
var n = uint.Parse(m.Groups[1].Value);
if (isRange(n))
range.Add(n);
}
}
return range.ToArray<uint>();
}
public static string GetHashValue(Windows.Storage.Streams.InMemoryRandomAccessStream strm) {
var alg = new SHA256CryptoServiceProvider();
strm.Seek(0);
var bin = alg.ComputeHash(strm.AsStream());
alg.Clear();
// バイト配列をUTF8エンコードで文字列化
var hashedText = new StringBuilder();
foreach (var b in bin) {
hashedText.AppendFormat("{0:X2}", b);
}
return hashedText.ToString();
}
}
/// <summary>
/// ファイルのハッシュ値のIO
/// </summary>
namespace UtHash
// https://qiita.com/Akasaki/items/dee137b24aea4b7e2bcb
// http://mokake.hatenablog.com/entry/2017/09/28/234433
// https://lifetime-engineer.com/csharp-create-json-indent/
// DataMemberでOrderを指定することで順序を確定。
// JsonReaderWriterFactory.CreateJsonWriterでindent=trueにすることでjsonの可視性向上
{
[DataContract]
public class HashHead
{
public bool Dirty = false; // 書き換えられたらTrue 保存対象外
[DataMember(Order = 0)]
public string HashBaseName; // 保存時にベース名を設定する
[DataMember(Order=1)]
public string HashFilePath;
[DataMember(Order=2)]
public string Dpi;
[DataMember(Order=3)]
public string Box;
[DataMember(Order=4)]
public string ImType;
[DataMember(Order=5)]
public string JQ;
// メソッド
public HashHead() {
SetRenderInfo("0", "Bx", "IMx", "xx");
}
public HashHead SetRenderInfo(string dpi, string box, string imType, string jq) {
Dpi = dpi; Box = box; ImType = imType; JQ = jq;
return this;
}
public string GetRenderInfoStr() { return $@"{Dpi}_{Box}_{ImType}_{JQ}"; }
}
[DataContract]
public class HashFile
{
[DataMember(Order=0)]
public DateTime UpdateTime; // ファイルの更新日
[DataMember(Order=1)]
public string UpdateTimeStr; // ファイルの更新日(Json目視用)
[DataMember(Order=2)]
public List<string> PageHashCode = new List<string>(); // ページ毎のハッシュ値の配列
// メソッド
public string GetHashValue(int i) {
// 範囲チェック
if ( !(0 <= i && i < PageHashCode.Count) ){
return "";
}
return PageHashCode[i];
}
}
[DataContract]
public class HashData
{
[DataMember(Order=0)]
public HashHead Head = new HashHead();
[DataMember(Order=1)]
public SortedDictionary<string, HashFile> Files = new SortedDictionary<string, HashFile>();
// メソッド
static public string GetHashFileName(string baseName, string dpi, string box, string imType, string jq) {
var h = new HashHead();
var f = baseName + "_" + h.SetRenderInfo(dpi, box, imType, jq).GetRenderInfoStr() + ".json";
return f;
}
static public HashData load(string pdfPath/*or Dir*/, string baseName, string dpi, string box, string imType, string jq, ref string otPath) {
var hashPath = "";
if (Path.GetExtension(pdfPath).ToLower() == ".pdf") {
var paPath = Directory.GetParent(Path.GetFullPath(pdfPath)).ToString();
var hashFName = GetHashFileName(baseName, dpi, box, imType, jq);
hashPath = Path.Combine(paPath, hashFName);
} else if (File.GetAttributes(pdfPath).HasFlag(FileAttributes.Directory)) {
var hashFName = GetHashFileName(baseName, dpi, box, imType, jq);
hashPath = Path.Combine(pdfPath, hashFName);
}
//Console.WriteLine($@"hashPath={hashPath}");
if (otPath != null) {
otPath = hashPath;
}
var hd = HashData.load(hashPath); //ファイルの存在はこっちに任す
return hd;
}
static public HashData load(string hashPath) {
if (!File.Exists(hashPath)) {
echo("not find load hash data file");
return null;
}
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HashData));
using (var rd = new FileStream(hashPath, FileMode.Open,FileAccess.Read,FileShare.ReadWrite)) {
var a = (HashData)serializer.ReadObject(rd);
a.Head.Dirty = false;// clear
return a;
}
}
static public HashData loadFromString(string s) {
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HashData));
using (var rd = new MemoryStream( Encoding.UTF8.GetBytes(s) )) {
var a = (HashData)serializer.ReadObject(rd);
a.Head.Dirty = false;// clear
return a;
}
}
public override string ToString() {
//文字列に書き出す
using (var m = new MemoryStream())
using (var writer = JsonReaderWriterFactory.CreateJsonWriter(m, Encoding.UTF8, true, true, " ")) {
var serializer = new DataContractJsonSerializer(typeof(HashData));
serializer.WriteObject(writer, this);
var x= Encoding.UTF8.GetString(m.ToArray());// 文字列に変換
return x;
}
}
public bool save(string path) {
// JSONに変換するデータを作る。
// 再保存の抑制
//this.Head.Dirtyがfalseなら更新されていないことになる。
//またかつ保存パスが同じ this.Head.HashFilePath = path;
echo($@"HashData.save:{path}");
this.Head.HashFilePath = Path.GetFullPath(path);
this.Head.HashBaseName = this.Head.GetRenderInfoStr();
try {
using (var fs = new FileStream(path, FileMode.Create))
using (var writer = JsonReaderWriterFactory.CreateJsonWriter(fs, Encoding.UTF8, true, true, " ")) {
var serializer = new DataContractJsonSerializer(typeof(HashData));
serializer.WriteObject(writer, this);
return true;
}
} catch (Exception e) {
Console.WriteLine($@"error Save json anything error:{e}");
return false;
}
}
public bool SetFile(string pathPDF, int pageNum) {
var fi = new FileInfo(pathPDF);
var fName = fi.Name;
HashFile hf;
if (!Files.ContainsKey(fName)) {
this.Head.Dirty = true;// 変更あり
hf = new HashFile() {
UpdateTime = fi.LastWriteTimeUtc,
UpdateTimeStr= fi.LastWriteTime.ToString(),
PageHashCode = new List<string>(pageNum)
};
// Console.WriteLine($@"update={hf.UpdateTime}");
for (var i = 0; i < pageNum; i++) {
hf.PageHashCode.Add("");
}
Files.Add(fName,hf);
} else {
// 既に存在、pageNumがかわらないことだけチェック
var pageNumOrg = Files[fName].PageHashCode.Count;
if (Files[fName].UpdateTime.ToString() != fi.LastWriteTimeUtc.ToString()) {
// 日付が一致しなければ更新(ToStringで比較しないとだめです
this.Head.Dirty = true;// 変更あり
Files[fName].UpdateTime = fi.LastWriteTimeUtc;
Files[fName].UpdateTimeStr = fi.LastWriteTime.ToString();
Files[fName].PageHashCode = new List<string>(pageNum);
for (var i = 0; i < pageNum; i++) {
Files[fName].PageHashCode.Add("");
}
}
// ありえないけど、同一日付でページ数が異なる
if (pageNumOrg != pageNum) {
Console.WriteLine($@"Mismatch pageNum:setP:{pageNum},DbP:{Files[fName].PageHashCode.Count}");
this.Head.Dirty = true;// 変更あり
return false; // Page数が一致しない
}
}
return true;
}
public bool AddHashCode(string pathPDF, int pageNo/*1開始*/, string hashCode) {
//Console.WriteLine("call addHashCode:" + pathPDF + ":" + pageNo);
var fi = new FileInfo(pathPDF);
var fName = fi.Name;
var n = pageNo - 1;//0始まり
if (!Files.ContainsKey(fName)) {
this.Head.Dirty = true;// 変更あり
return false;
}
if (Files[fName].PageHashCode[n] != hashCode) {
this.Head.Dirty = true;// 変更あり
Files[fName].PageHashCode[n] = hashCode;
}
return true;
}
public string GetHashCode(string pathPDF, int pageNo/*1開始*/) {
var fi = new FileInfo(pathPDF);
var fName = fi.Name;
var n = pageNo - 1;//0始まり
if (!Files.ContainsKey(fName)) {
return "";
}
var v = Files[fName].PageHashCode;
return (n < v.Count) ? v[n] : "";
}
}
}
namespace UtImage // Image保存のユーティリティー
{
// ref:https://water2litter.net/rum/post/cs_pdf_wpf/
//using EncType = System.Drawing.Imaging.Encoder;// 別名
//using EncParamType = System.Drawing.Imaging.EncoderParameter;//別名
/// <summary>
/// BitMapのSaveに使うImage Encodeパラメータの設定値の生成と 画像保存
/// var enc = new UtImage.Enc("jpeg");
/// //enc.SetImageType("PNG"); // 後で変更できる
/// //enc.JJpegQuality = 100; JpegのQuarty変更
/// enc.SaveImage(BitMap,path);
/// // enc.SaveImage(BitMap,path,"PNG");
/// </summary>
///
public class Enc
{
// SEE:https://dobon.net/vb/dotnet/graphics/encoderparameters.html
public Enc(string imageType = "jpeg") { SetImageType(imageType); }
public long JpegQuality { get; set; } = 91;// 指定しないときの値は91と一致する
private string ImageType = "jpeg";
public Enc SetImageType(string imageType) {
imageType = imageType.ToLower();
if (imageType == "jpeg" || imageType == "jpg") {
ImageType = "jpeg";
} else if (imageType == "png") {
ImageType = "png";
} else if (imageType == "tif" || imageType == "tiff") {
ImageType = "tiff";
} else {
ImageType = imageType;// 小文字を設定
}
return this;
}
public int SaveImage(System.Drawing.Bitmap bitmap, string path, string imageType = null) {
var p = GetParams();
string imType = imageType?.ToLower();
if (p != null) {
bitmap.Save(path, GetInfo(imType), GetParams());// imageTypeがnullならSetImageType()のものが使われる
} else {// パラメータが空の場合
var imageFormat = new System.Drawing.Imaging.ImageFormat(GetInfo(imType).FormatID);
bitmap.Save(path, imageFormat);
}
return 0;
}
/// <summary>
/// サポートするEncodeパラメータ一覧
/// 現状Errorが発生して取得できない
/// </summary>
/// <param name="bitmap1">対象のBitMap</param>
public static void GetSupportedParameters(System.Drawing.Bitmap bitmap1 = null) {
// https://docs.microsoft.com/ja-jp/dotnet/framework/winforms/advanced/how-to-determine-the-parameters-supported-by-an-encoder
try {
if (bitmap1 == null) {
bitmap1 = new System.Drawing.Bitmap(100, 100);
var destBitmapData = bitmap1.LockBits(
new System.Drawing.Rectangle(0, 0, 100, 100),
System.Drawing.Imaging.ImageLockMode.ReadOnly,
bitmap1.PixelFormat
);
bitmap1.UnlockBits(destBitmapData);
}
var jpgEncoder = GetEncoderInfo(System.Drawing.Imaging.ImageFormat.Tiff);
var paramList = bitmap1.GetEncoderParameterList(jpgEncoder.Clsid);
var encParams = paramList.Param;
for (int i = 0; i < encParams.Length; i++) {
Console.WriteLine("Param " + i + " holds " + encParams[i].NumberOfValues +
" items of type " +
encParams[i].ValueType + "\r\n" + "Guid category: " + encParams[i].Encoder.Guid + "\r\n");
}
} catch (Exception e) {
Console.WriteLine($"Ignore error ={e.ToString()}");
}
}
// inner method.
private System.Drawing.Imaging.EncoderParameters GetParams() {
var encList = new List<System.Drawing.Imaging.EncoderParameter>();
//encList.Clear();
// 今はJPEGパラメータだけ
encList.Add(new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, JpegQuality));
//...
// 結合
var eps = new System.Drawing.Imaging.EncoderParameters(encList.Count);
for (var i = 0; i < encList.Count; i++)
eps.Param[i] = encList[i];
return eps;
}
private System.Drawing.Imaging.ImageCodecInfo GetInfo(string it = null) {
if (it == null) {// SetImageType()で指定したものを使う
it = ImageType;
}
return GetEncoderInfo($"image/{it}");
}
//ImageFormatで指定されたImageCodecInfoを探して返す
private static System.Drawing.Imaging.ImageCodecInfo GetEncoderInfo(System.Drawing.Imaging.ImageFormat f) {
var encs = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
foreach (var enc in encs) {
if (enc.FormatID == f.Guid)
return enc;
}
return null;
}
private static System.Drawing.Imaging.ImageCodecInfo GetEncoderInfo(string mineType) {
var encs = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
//指定されたMimeTypeを探して見つかれば返す
foreach (System.Drawing.Imaging.ImageCodecInfo enc in encs) {
if (enc.MimeType == mineType)
return enc;
}
return null;
}
}
}
}
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
//using System.Text;
//using System.Threading;
//using System.Threading.Tasks;
//using System.Windows;
//using System.Windows.Media.Imaging;
using System.Reflection; // Assembly.
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.ServiceModel; // WCF
using System.Diagnostics; // for Process
// 作成クラス
using CSRender;
using CSRender.UtHash;
using static CSRender.RenderPDF;
// *重要* デスクトップアプリで UWP Api を呼び出す プロジェクトの設定方法が記載されている
// https://docs.microsoft.com/ja-jp/windows/apps/desktop/modernize/desktop-to-uwp-enhance
// 参照はwindows. winmd :C:\Program Files (x86) \Windows Kits\10\UnionMetadata\<sdk バージョン>/ファサード
namespace CSRenderMain {
[DataContract]
//[Serializable()]
public class ParamData {
[DataMember]
public string pdfPath = ""; //対象ファイル
[DataMember]
public string pdfPath2 = ""; //比較ファイル
[DataMember]
public string outuptImageDir = ""; // /O
[DataMember]
public string dpi = "72.0"; // /D
[DataMember]
public int para = 4; // 並行数
[DataMember]
public string boxSelect = "Crop"; // /B<x>
[DataMember]
public string pageRange = "1-*"; // /P
[DataMember]
public string mode = "page"; // /MODE
[DataMember]
public string imageType = "JPG"; // /JPG or /PNG
[DataMember]
public string jpegQ = "91"; // JPEGQ
[DataMember]
public bool bHash = false; // ハッシュ値を生成する
[DataMember]
public bool bMkHash = false; // ハッシュファイルを作成する
[DataMember]
public bool bFC = false;
[DataMember]
public string resultPath = "";
[DataMember]
public bool bPDFium = true;
//
[DataMember]
public bool bExeSepa = true;// 実行分離
[DataMember]
public string subExe = null;// "Sub"が指定されたら、処理をExe分離する。内部コマンド
// データはWCFの通信データを使う。引数はPipeName:PortAddressNameとする
[DataMember]
public bool bVerbose = false;// 詳細デバッグ
public ParamData Clone() {
return (ParamData)MemberwiseClone();
}
}
public class Program {
static void DispHelp() {
var pgName = Path.GetFileName(Path.GetFileName(Assembly.GetExecutingAssembly().Location));// プログラム名
var pgNameFullPath = Assembly.GetExecutingAssembly().Location;// プログラム名
Console.WriteLine("pageNameF="+pgNameFullPath);
string msg =
$"{pgName} [/<Opts>] <PDFPath or PDFDir>\n"
+ $"* Render of PDF file. available 3 command mode:[Basic Rendering] [Make Hash command] [Compare command], and [Render Options]\n"
+ $"\tPDFの画像化は[Basic Rendering]。\n"
+ $"\t比較は/MkHash([Make Hash command])後に、/FC([Compare command])で高速実行できます。\n"
+ $"\n"
+ $"[Basic Rendering] 基本的なレンダリング\n"
+ $"\t{pgName} [/<Render Options>] <PDFPath|PDFDir>\n"
+ $"\t/F <pdfPath|pdfDir> : pdfPath(pdfファイル名|ディレクトリ) /Fは省略可能\n"
+ $"\t/O <output directory> : 出力ディレクトリ。省略時は\"IMG\"フォルダ\n"
+ $"\n"
+ $"[Render Options] レンダリングオプション\n"
+ $"\t/D <解像度> : 解像度指定 9 - 300dpi(default=72dpi)\n"
+ $"\t/JPG,/JPEG,/PNG,/TIF,/TIFF,/GIF,/BMP: Select one output format.(default=/JPG)\n"
+ $"\t/JPEGQ <quality>: Jpegの品質指定1-100(default=91)\n"
+ $"\n"
+ $"\t/P <PageRange> : ページの範囲を指定する(省略時は全ページ)\n"
+ $"\t\t連続した範囲を指定する場合は、ハイフン('-')を用いる。終了側を省略すると最終pageまで。\n"
+ $"\t\t複数のページを指定する場合は、カンマ(',')を用いる\n"
+ $"\t\tEx. /P \"1,2,30-100\" //1,2pages and 30-100pages.\n"
+ $"\t[Unsupport] 未対応↓\n"
+ $"\t/L <input List text> : 入力PDFファイルリスト(*unsupport)\n"
+ $"\t/T <tempPath> : テンポラリフォルダを指定(省略時は出力先フォルダと同じ(*unsupport no need)\n"
+ $"\t/OP <0|1> : オーバープリントのOn/Off (省略時は1)(*unsupport allways on[1])\n"
+ $"\t/U <0|1> : 同名上書き設定 0:上書きしない 1:上書き(*unsupport allways overwrite[1])\n"
+ $"\t/OFFSET <X> <Y> : ミリ単位でオフセットを指定する(省略時は共に0mm)(*unsupport)\n"
+ $"\t/PDFium <0or1>: GoogoleのPDFiumViewerエンジンを使用する(default=1>\n"
+ $"\t【未】/BM,/BT,/BA,/BA,/BC: Select one box.(default=/BC:CrobBox): Boxies:MediaBox/BleedBox/TrimBox/ArtBox/CropBox\n"
+ $"\n"
+ $"[Make Hash command] 比較用ハッシュ値作成コマンド\n"
+ $"\t{pgName} /MkHash ...<Render Options>... <PDF|PDF dir>\n"
+ $"\t/MKHash : ハッシュ値を出力する。前記の[Render Options]を指定すること\n"
+ $"\t[HASHファイル作成]\n"
+ $"\n"
+ $"[Compare command] 比較コマンド\n"
+ $"\t{pgName} /FC ...<Render Options>... <Target PDF|PDF dir> <Reference PDF|PDF dir>\n"
+ $"\t/FC : 2つのPDFを比較する。前記の[Render Options]を指定すること。無名引数が2つ必要です\n"
+ $"\t 事前に/MkHashを実行しておくことで高速に処理できる\n"
+ $"\n"
+ $"\t/RESULT <result file> : 比較結果を格納するファイルパス\n"
+ $"\t\t/FCコマンドを指定すると一致したら0,不一致なら1を返却するようになる\n"
+ $"\t\t<result file>は、<pageNum(1始まり)>,<[OK] or [@Difference]>の行で構成される\n"
+ $"\n"
+ $"[ELSE ] その他のオプション\n"
+ $"\t/PDFium <0|1>:PDFiumライブラリを使う,デフォルト=1\n"
+ $"\t/NoExeSepa :実行分離しない(遅い)\n"
+ $"\t/para <並行数>:並行数を指定(デフォルト4)\n"
+ $"\t内部コマンド:/SubExe <WCF_PipeAddress> :実行分離,PDF単位で別Processで処理\n"
+ $"\n"
+ $"/H or /? : This help\n"
/* PDFと同じフォルダに
data.<出力条件>.jsonファイルを作成する
出力条件:<dpi>+<Box>+<IMFormat>+<JQ>
data.72_BT_JPG_Q34.json
既に存在したら、それを読んでから、追記(もしくは書き換える>。
*/
// Remove TEST
//+$"\t[for TEST]\n"
//+$"\t/M Sync(default) or ASync\n"
//+$"\t/M <mode> : pageBitMap(default), pageBitMapImage, page(same as pageBitMap), org(orginal source)\n"
+ "\n";
Console.Write(msg);
}
#if COMENT
// 設計の見直し
* ハッシュ作成のみのコマンド
/MkHashをつけると ハッシュファイルのみ作成。ただし、ディレクトリ指定に限る
CSRender /MkHash <PDFディレクトリ> <各種Renderパラメータ>
* 単純なRenderを維持。それに同時にハッシュファイルのOn/Off
/MkHashをつけなければよい。
CSRender <PDFディレクトリor PDFファイル> <各種Renderパラメータ>
* 比較モードは、Autoハッシュで、存在しなければ最初に作成。Target/Refともに。比較しながら作成してよし
Manualでハッシュなしで、遅いけどできるようにする。ハッシュ動作の検証用に
/FCをつけると、デフォルトでハッシュ優先で検査(Auto相当)、ハッシュ検査を無効にしたければ
/NoHash追加でハッシュを無視してTarget/Refとも再計算。ハッシュを使いたければ、事前に/MkHash
作成しておけばよい。
* ヘルプは <単純なRender> <ハッシュ作成> <比較>にわける
* <単純なレンダラ>: 1ファイルおよびディレクトリの比較。 Renderingパラメータの一覧(項目分ける)まで.
* <ハッシュ作成>: /MkHashで高速比較のための前準備。ディレクトリモードでハッシュファイルのみを作成する。Renderingパラメータは合わせること
* <比較>:/FCコマンドで比較の説明
* ここにAsiccDocを埋められないの? 情報なし*
// 遅くなるので
* 比較モード時の差異があったとき、Diffを出す上限値をLimitDiffNumがほしい(デフォルトは各PDF1pageとしたい)
* 比較NGになって、フルでDIFF画像を出したいときはLimitDiffを解除すべき。単独ファイル指定のとき。
// 設計の見直し(END)
#endif
/// <summary>
/// PDF renderer main
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
static int Main(string[] args) {
// 引数の保持
var pm = new ParamData();
bool bDirMode = false; // ディレクト指定の場合
//var pdfPathLst = new List<string>();
string[] pdfPathLst = null;
string[] pdfPathLst2 = null;
var pdfPathLstBoth = new List<string>();
var pdfPathLstNoBoth = new List<string>();
//ハッシュ関係
string hashBaseName = "RenderHash";
CSRender.Check.GetDPI();
//{// ベースハッシュ値の計算テスト
// // 一旦使用しない
// var streamPDF = ResData.GetBaseHashPDF();
// RenderPDF.RenderPdfInitCheck(streamPDF);
//}
var qu = new Queue<string>(args); // 引数をQueに登録 (qu.Enqueue(a)でも可能)
while (qu.Count > 0) {
// 引数のパース
var wd = qu.Dequeue(); // 取り出しqu.Dequeue()で次の要素を取得する
if (wd.First() == '-') {
// 先頭-(ハイフンもオプション扱いにする)→"/"に置換
wd = Regex.Replace(wd, @"^\-", "/");
}
//大文字小文字無視でオプションチェック
var eIgnoreCase = StringComparer.OrdinalIgnoreCase;
// オプションチェックローカル関数
bool isOpt(params string[] opts) => opts.Contains<string>(wd, eIgnoreCase);
// ボックスオプション辞書
var BoxSelOptDic = new Dictionary<string, string>(eIgnoreCase) { ["/BM"] = "Media", ["/BT"] = "Trim",
["/BB"] = "Bleed", ["/BC"] = "Crop",
["/BA"] = "Art"
};
if (isOpt("/?", "/H")) {
DispHelp();
return -1;
} else if (isOpt("/F")) {
pm.pdfPath = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
} else if (isOpt("/O")) {
pm.outuptImageDir = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
} else if (isOpt("/D")) {
pm.dpi = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
if (!double.TryParse(pm.dpi, out double dmy)) {
Console.WriteLine($"解像度が不正です:/D {pm.dpi}");
DispHelp();
return -1;
}
} else if (isOpt("/Para")) {
string paraNum = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
if (!int.TryParse(paraNum, out pm.para)) {
Console.WriteLine($"並行数が不正です:/para {paraNum}");
DispHelp();
return -1;
}
} else if (isOpt("/P")) {
pm.pageRange = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
} else if (isOpt("/JPG", "/JPEG")) {
pm.imageType = "JPG";
} else if (isOpt("/PNG")) {
pm.imageType = "PNG";
} else if (isOpt("/TIF", "/TIFF")) {
pm.imageType = "TIFF";
} else if (isOpt("/GIF", "/GIFF")) {
pm.imageType = "GIF";
} else if (isOpt("/BMP")) {
pm.imageType = "BMP";
} else if (isOpt("/JPEGQ")) {
pm.jpegQ = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
if (!int.TryParse(pm.jpegQ, out int dmy)) {
Console.WriteLine($"JPEG Qualityが不正です:/JPEGQ {pm.jpegQ}");
DispHelp();
return -1;
}
if (!(0 < dmy && dmy <= 100)) {
Console.WriteLine($"JPEG Qualityが不正です(not 1-100):/JPEGQ {dmy}");
return -1;
}
} else if (isOpt("/M")) {
pm.mode = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
} else if (BoxSelOptDic.ContainsKey(wd)) {
pm.boxSelect = BoxSelOptDic[wd];// "/BT" -> "Trim",...
} else if (isOpt("/HASH")) {
pm.bHash = true;
} else if (isOpt("/MKHASH")) {
pm.bMkHash = true;
pm.bHash = true;
} else if (isOpt("/FC")) {
pm.bFC = true;
} else if (isOpt("/PDFium")) {
pm.bPDFium = true;
var flgStr = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
if (!int.TryParse(flgStr, out int dmy)) {
Console.WriteLine($"PDFiumフラグが不正です:/PDFium {flgStr}");
return -1;
}
if (dmy == 0) {
pm.bPDFium = false;
} else if (dmy == 1) {
pm.bPDFium = true;
} else {
Console.WriteLine($"PDFiumフラグが不正です:/PDFium {flgStr}");
return -1;
}
} else if (isOpt("/Verbose")) {
var arg = (qu.Count > 0) ? qu.Dequeue() : "True";// next word.
string[] sel = {"True","1","ON"};
pm.bVerbose = sel.Contains(arg, eIgnoreCase);
} else if (isOpt("/SubExe")) {
pm.subExe = (qu.Count > 0) ? qu.Dequeue() : null;// next word.
var sp = pm.subExe.Split(':');
if (sp.Length < 2 ) {
Console.WriteLine($"SubExe指定は\":\"区切りが必要: {pm.subExe}");
return -1;
}
} else if (isOpt("/NoExeSepa")) {
pm.bExeSepa = false;
} else if (isOpt("/RESULT")) {
pm.resultPath = (qu.Count > 0) ? qu.Dequeue() : "";// next word.
} else if (wd.First() == '/') {
// 処理の無いオプションを明示的に無視する
Console.WriteLine($"Warning::Ignore opt:{wd}");
} else {
// 引数をファイル名として取得する
if (pm.pdfPath == "") {
pm.pdfPath = wd;
continue;
}
if (pm.bFC && (pm.pdfPath2 == "")) {
pm.pdfPath2 = wd;// 比較時のみ取得
continue;
}
}
}
// ↑引数解析終わり
setEcho(pm.bVerbose);
if (pm.bVerbose)
echo("Varbose Mode!");
//
bool bSubExe = (pm.subExe != null);// SubExeで起動されている場合。
xChangeWCFPipe.IXData cltSrv = null;
if (!bSubExe) {
/// サーバー側
echo("++MainProcess start");
} else {
// SubExe側の動作に差し替える
var sp = pm.subExe.Split(':');
var pipeName = sp[0]; var pipeAddr = sp[1];
cltSrv = xChangeWCFPipeGEN.CLT_T.makeCLT<xChangeWCFPipe.IXData>(pipeName:pipeName,pipeAddress:pipeAddr);
Ut.Ut.SetAutoSelfKillByMainProcEnd(); // 起動元が終了した場合に自身を終了させる
pm = cltSrv.GetParam(); // パラメータを書き換える
setEcho(pm.bVerbose);
echo("++SubProcess start:" + pm.subExe);
}
if (pm.pdfPath == "") {
Console.WriteLine("pdfファイルが指定されてません");
DispHelp();
return -1;
}
if (!(File.Exists(pm.pdfPath) || Directory.Exists(pm.pdfPath))) {
// ファイルもしくはディレクトも見つからない場合
Console.WriteLine($"ファイルが存在しません:{pm.pdfPath}");
return -1;
}
var rdCond = new RenderPDF.RenderConditionParams {
Dpi = double.Parse(pm.dpi),
ImageType = pm.imageType,
BoxType = pm.boxSelect,
JpegQ = int.Parse(pm.jpegQ)
};
bool bDir = File.GetAttributes(pm.pdfPath).HasFlag(FileAttributes.Directory);
if (bDir) {
// Directoryが指定されたのでファイルリストアップ
bDirMode = true;
pdfPathLst = System.IO.Directory.GetFiles(pm.pdfPath, "*.pdf"/*, System.IO.SearchOption.AllDirectories*/);
pdfPathLst = Array.ConvertAll(pdfPathLst, f => Path.GetFileName(f)); // 配列書き換え(ファイル名のみにする
// var enumLst = pdfPathLst.Select(f => Path.GetFileName(f)); LINQ式に置き換えることも可能(返り値は配列ではない)
//foreach ( var f in pdfPathLst) {
// Console.WriteLine($@"path1={f}");
//}
//Console.WriteLine($@"path1.Len={pdfPathLst.Count()}");
}
var resultData = new SortedDictionary<int, string>();
if ((!pm.bFC) && bDir) {
// 単純レンダリング時 かつ ディレクト時に 対象リストに追加
foreach (var f in pdfPathLst) {
pdfPathLstBoth.Add(f);
}
}
if (pm.bFC) {// 比較モード時
if (pm.pdfPath2 == "") {
Console.WriteLine("比較モードで2つ目のpdfファイルが指定されてません");
return -1;
}
if (!(File.Exists(pm.pdfPath2) || Directory.Exists(pm.pdfPath2))) {
Console.WriteLine($"比較ファイルが存在しません:{pm.pdfPath2}");
return -1;
}
bool bDir2 = File.GetAttributes(pm.pdfPath2).HasFlag(FileAttributes.Directory);
if (bDir2) {
if (!bDir) {
Console.WriteLine($"比較対象はファイルパスでないといけません:{pm.pdfPath2}");
return -1;
}
// 2つ目のファイルリストアップ
pdfPathLst2 = System.IO.Directory.GetFiles(pm.pdfPath2, "*.pdf"/*, System.IO.SearchOption.AllDirectories*/);
pdfPathLst2 = Array.ConvertAll(pdfPathLst2, f => Path.GetFileName(f));// 配列の書き換え
// 共通のファイルを見つける。Lstの要素がLst2に含まれているかどうか
foreach (var f in pdfPathLst) {
if (pdfPathLst2.Contains(f)) {
pdfPathLstBoth.Add(f);
} else {
pdfPathLstNoBoth.Add(f);// LstがLst2に含まれていない
}
}
// Lst2のみファイルをNoBothに登録
foreach (var f in pdfPathLst2) {
if (!pdfPathLstBoth.Contains(f)) {
pdfPathLstNoBoth.Add(f);
}
}
// pdfPathBoth,pdfPathNoBothが作成済み
if (pdfPathLstNoBoth.Count() != 0) {
Console.WriteLine($@"不一致のファイル={pdfPathLstNoBoth.Count()}");
foreach (var f in pdfPathLstNoBoth) {
Console.WriteLine($@"warning [no match]={f}");
}
}
}
}
var watch = System.Diagnostics.Stopwatch.StartNew(); // 時間の生成と計測開始を同時に行う
var otDir = pm.outuptImageDir;
if (otDir == "") {
// 出力ディレクトリの作成 // 元PDFの同一フォルダにIMGフォルダを作成する
otDir = Path.Combine(Directory.GetParent(pm.pdfPath).FullName, "IMG");
}
if (!Directory.Exists(otDir) /* && (!bMkHash)*/ ) { // MkHashのとき不要→必要
Directory.CreateDirectory(otDir);
}
var otHashPath = "";
var otHashPath2 = "";
int ret = -1;
//Console.WriteLine($@"Use bPDFium={pm.bPDFium}");
if (!bDirMode) {
if (pm.bFC) {
//比較モード
// ハッシュデータの読み込み
echo($@"pre pdfPath={pm.pdfPath}");
echo($@"pre pdfPath2={pm.pdfPath2}");
var hashDataTgt = HashData.load(pm.pdfPath, hashBaseName, pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ, ref otHashPath);
var hashDataRef = HashData.load(pm.pdfPath2, hashBaseName, pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ, ref otHashPath2);
//Console.WriteLine("<Compare Sync(Paralles) Version!>");
if (pm.resultPath != "") {// 初期化
File.WriteAllText(Path.GetFullPath(pm.resultPath), "");
}
ret = RenderPDF.RenderPdfDocCompare(
pdfPath: Path.GetFullPath(pm.pdfPath),
refPdfPath: Path.GetFullPath(pm.pdfPath2),
resultDataPath: pm.resultPath,
inDir : otDir,
pm : rdCond,
inPageRange : pm.pageRange,
inHashDataTgt: hashDataTgt,
inHashDataRef: hashDataRef,
bPDFium : pm.bPDFium
);
} else {
// Sync version.
// Console.WriteLine("<Render Sync(Paralles) Version!>");
// シングル指定では既存のハッシュファイルを読みださない → 単独名のハッシュファイル<pdfFName+".hash")
// 空のハッシュデータを作成
var hashDataTgt = new HashData();
hashDataTgt.Head.SetRenderInfo(pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ);
//retはページ数
// rdCond
ret = RenderPDF.RenderPdfDoc(
pdfPath : Path.GetFullPath(pm.pdfPath),
inDir : otDir,
pm : rdCond,
inPageRange : pm.pageRange,
bSaveImage : pm.bMkHash ? false : true,// ハッシュ値生成ではイメージ保存しない。
bHash : pm.bHash,
inHashData : hashDataTgt,
bPDFium : pm.bPDFium
);
if (pm.bMkHash) {
/// ここでMain側に通信データを返せばよい
if (bSubExe) {
cltSrv.SetHashData(hashDataTgt);
} else {
// 個別のファイル名+"hash"拡張子で保存します。
var othashPath = Path.Combine(otDir, Path.GetFileName(pm.pdfPath) + ".hash");
hashDataTgt.save(othashPath);//ハッシュモードで保存する(Dutyチェックもいるでしょう
//不要:hashDataTgt.save(otHashPath);//比較モード,MakeHashに限定すること
//表示のみ まだやめておく:
}
}
// retはページ数です。
}
} else {
// 対象がディレクトリ
echo("For Directory mode");
HashData hashDataTgt = null, hashDataRef = null;
hashDataTgt = HashData.load(pm.pdfPath, hashBaseName, pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ, ref otHashPath);
if (pm.bMkHash) {
hashDataTgt = null;// MKHashの時にはLoadしない → 一旦nullで除去して、otHashPathを利用する
}
if (hashDataTgt == null) {
// 空のハッシュデータを作成
hashDataTgt = new HashData();
hashDataTgt.Head.SetRenderInfo(pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ);
}
if (pm.bFC) {
// リファレンス側のハッシュの読み込み
hashDataRef = HashData.load(pm.pdfPath2, hashBaseName, pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ, ref otHashPath2);
if (hashDataRef == null) {
// 空のハッシュデータを作成
hashDataRef = new HashData();
hashDataRef.Head.SetRenderInfo(pm.dpi, pm.boxSelect, pm.imageType, pm.jpegQ);
}
}
// ハッシュデータが適切に作成済みがどうかを確認。もしハッシュデータが存在しない場合は
// ハッシュデータを渡してはいけない。ハッシュのFilesで確認するか?
// ハッシュデータの作成プロセスをもっと簡単にすべき
echo($@"Start render:Count={pdfPathLstBoth.Count}");
//Console.WriteLine("<Render Sync(Paralles) Version!>");[
var count = pdfPathLstBoth.Count;
//ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = 6 };
//Parallel.For(0,pdfPathLstBoth.Count, options, index => {
//逆に遅くなる UWPコール(render)は対応していない?
if (pm.bExeSepa &&(!pm.bFC)) { // FCモードは除外します。
var tokenSource = new CancellationTokenSource();
ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = pm.para };
ret = 0;//Success
var loopResult = Parallel.For(0,pdfPathLstBoth.Count, options, (index,lpState) => {
//for (var index = 0; index < pdfPathLstBoth.Count; index++) {
var tgt = Path.Combine(pm.pdfPath, pdfPathLstBoth[index]);
var tgtID = $@"{index}/{pdfPathLstBoth.Count}";
Console.WriteLine($@"**Remain({count})****tgt({tgtID})={tgt}");
if (pm.bFC) {
//比較モード
var reff = Path.Combine(pm.pdfPath2, pdfPathLstBoth[index]);
} else { // Sync version(Paralles).
var svrData = new xChangeWCFPipe.XData();
var pmClone = pm.Clone();
pmClone.pdfPath = tgt;// 引数のターゲットのみを書き換える
svrData.SetParam(pmClone);
string guidStr = Guid.NewGuid().ToString("N");
string pipeName = $"PN_{guidStr}";
string pipeAddress = $"P_{index}_{guidStr}";
var svrHost = xChangeWCFPipeGEN.SVR_T.makeSVR(
baseIf : typeof(xChangeWCFPipe.IXData),
obj : svrData,
pipeName : pipeName,
pipeAddress : pipeAddress
);
if ( svrHost == null) {
Console.WriteLine("WCF cannot make");
//tokenSource.Cancel();// 処理のキャンセル( throwされる)
lpState.Stop();
return;
}
var myExePath = Assembly.GetExecutingAssembly().Location;
var proc = Ut.Ut.DoCmd(
cmdAndArgs: new string[] { myExePath, "/SubExe",$"{pipeName}:{pipeAddress}" }
, bEcho: false
, bSameConsole: true
);
proc.WaitForExit();
var retProc = proc.ExitCode;
echo($@"retProc={retProc}");
if ( retProc < 1 ) {
//PDFページ数以外が返った時
ret = -1;
Console.WriteLine( $@"Warning ::Cannot get PDFPage:{retProc}");
} else {
;// 初期値 ret=0;
}
//while (!proc.HasExited) {
// System.Threading.Thread.Sleep(2 * 1000);
//}
var tmpH = svrData.GetHashData();
if (tmpH == null) {
echo("tmpH is null");
}
if ( (hashDataTgt!=null)&&(tmpH!=null)) {
lock(hashDataTgt) {
//hashDataTgt.Files += tmpH.Files;
if ( tmpH.Files.Count() < 1 ) {// 中身が空なら警告
Console.WriteLine($@"Warning tempF.Count={tmpH.Files.Count()}");
}
var merged = hashDataTgt.Files
.Concat(tmpH.Files.Where(pair =>
!hashDataTgt.Files.ContainsKey(pair.Key))
).ToDictionary(
pair => pair.Key,
pair => pair.Value
);
hashDataTgt.Files = new SortedDictionary<string, HashFile>(merged);// hashを合成した。
}
}
proc.Dispose();
svrHost.Close();
svrData = null;
Console.WriteLine($@"End tgt({tgtID})");
}
//GC.Collect();// これでメモリリークが解決した Paraの中ではやめておく
count--;
});
if ( !loopResult.IsCompleted ) {
Console.WriteLine("中断");
pm.bMkHash = false;// Hash値保存抑制
}
////tokenSource.Cancel();// 処理のキャンセル
//if ( tokenSource.IsCancellationRequested ) {
// pm.bMkHash = false;// Hash値保存抑制
//}
//}; // Non Para Block
} else { // NoExeSepa
if (pm.resultPath != "") {// 初期化
File.WriteAllText(Path.GetFullPath(pm.resultPath), "");
}
for (var index = 0; index < pdfPathLstBoth.Count; index++) {
var tgt = Path.Combine(pm.pdfPath, pdfPathLstBoth[index]);
Console.WriteLine($@"tgt={index+1}/{pdfPathLstBoth.Count}:{tgt}");
if (pm.bFC) {
//比較モード
var reff = Path.Combine(pm.pdfPath2, pdfPathLstBoth[index]);
//Console.WriteLine("<Compare Sync(Paralles) Version!>");
ret = RenderPDF.RenderPdfDocCompare(
pdfPath: Path.GetFullPath(tgt),
refPdfPath: Path.GetFullPath(reff),
resultDataPath: pm.resultPath,
inDir: otDir,
pm: rdCond,
inPageRange: pm.pageRange,
inHashDataTgt: hashDataTgt,
inHashDataRef: hashDataRef,
bPDFium: pm.bPDFium
);
} else { // Sync version(Paralles).
ret = RenderPDF.RenderPdfDoc(
pdfPath: Path.GetFullPath(tgt),
inDir: otDir,
pm: rdCond,
inPageRange: pm.pageRange,
bSaveImage: pm.bMkHash ? false : true,// ハッシュ値生成ではイメージ保存しない。
bHash: pm.bHash,// bHash,dumy
inHashData: pm.bMkHash ? hashDataTgt : null, //ハッシュコマンドモードのみDataを渡す
bPDFium: pm.bPDFium
);
}
count--;
GC.Collect();// これでメモリリークが解決した
};
}
if (pm.bMkHash) {
hashDataTgt.save(otHashPath);//ハッシュモードで保存する(Dutyチェックもいるでしょう
}
}
watch.Stop();
Console.WriteLine($"result={ret},time={ watch.ElapsedMilliseconds / 1000.0 }[sec]");
#if COMMNET
Assembly assm = Assembly.GetExecutingAssembly();
Console.WriteLine(assm.FullName);
// 参照しているすべてのアセンブリを取得し、表示する
foreach (AssemblyName refassm in assm.GetReferencedAssemblies()) {
Console.WriteLine($@" {refassm.FullName},Ver({refassm.Version}),VerComp({refassm.VersionCompatibility})" );
}
string clrVersion = System.Environment.Version.ToString();
Console.WriteLine($@"clrVer={clrVersion}");
#endif
return ret;//success.
}
// リソースからの取得
public static class ResData {
public static Stream GetBaseHashPDF(string resName = "CSRender.RES.BaseHash.pdf") {
System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
var sel = from x in asm.GetManifestResourceNames() select resName;
if (sel.Count() == 1) {
return asm.GetManifestResourceStream(sel.First());
}
return null;
}
}
}
}
/// <summary>
/// WCF通信モジュールのラッパクラス。
/// 2つのExe間をWCFパイプモードで通信を行う
/// </summary>
namespace xChangeWCFPipe
{
/// シリアライズ可能にすること
/// </summary>
[ServiceContract]
public interface IXData {
[OperationContract(IsOneWay = true)]
void Execute();
[OperationContract]
bool SetMessage(string msg);
[OperationContract]
bool SetProgress(int per);//0-100.
[OperationContract]
HashData GetHashData();
[OperationContract]
void SetHashData(HashData d);
[OperationContract]
CSRenderMain.ParamData GetParam();
//CSRenderMain.Program.ParamData GetParam();
}
// ServiceContract https://tnakamura.hatenablog.com/entry/20080606/1220023868
// https://devlights.hatenablog.com/entry/20111023/p2
/// <summary>
/// 通信用複雑データ。スカラー型(int,double,,,.)以外は[DataCOntract]属性を
/// つけて、通知用Interfaceの引数や、返値で利用する
/// </summary>
[DataContract]
public class DataContainer
{
[DataMember]
public CSRenderMain.ParamData pm;
[DataMember]
public HashData hdata;
}
}
namespace xChangeWCFPipe
{
/// <summary>
/// Main(サーバー)側 データ定義
/// </summary>
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
public class XData : IXData
{
private readonly Object LockObj = new object();// 排他制御用
public delegate void callFunc();
public callFunc callDelegate;
public XData() {
_dc.pm = new CSRenderMain.ParamData();
}
public void Execute() {
lock (LockObj) {
callDelegate(); // 実装はデリゲートします
}
}
public bool SetMessage(string msg) {
lock (LockObj) {
Console.WriteLine($"SVR:called setMessage({msg}) from CLT");
_msg = msg;
}
return true;
}
public bool SetProgress(int per) {//0-100.
lock (LockObj) {
Console.WriteLine($"SVR:called setProgress({per}) from CLT");
_progress = per;
}
return true;
}
public void SetHashData(HashData h) {
lock (LockObj) {
_dc.hdata = h;
}
}
public HashData GetHashData() {
lock (LockObj) {
return _dc.hdata;
}
}
public CSRenderMain.ParamData GetParam() {
lock (LockObj) {
return _dc.pm;
}
}
// クライアントに公開しなくてもよいI/F
public void SetParam(CSRenderMain.ParamData pm) {
lock (LockObj) {
_dc.pm = pm;
}
}
// private data
private string _msg = "init msg";
private int _progress = 0;// 0-100
private DataContainer _dc = new DataContainer();
}
}
namespace xChangeWCFPipeGEN
{
/// <summary>
/// Main(サーバー)側 データ定義
/// </summary>
//[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
//public class XData : IXData
//{
// ...
//}
/// <summary>
/// Main(サーバー)側クラス
/// </summary>
///
public class SVR_T
{
// - static -
/// <summary>
///
/// </summary>
/// <param name="baseIf"> 公開するインターフェースクラス </param>
/// <param name="x">実装インスタンス(baseIfを含むこと)</param>
/// <param name="pipeName"></param>
/// <param name="pipeAddress"></param>
/// <returns></returns>
static public SVR_T makeSVR(Type baseIf, object obj/*XData*/ , string pipeName = "PDFormstudioESorGS", string pipeAddress = "SubModuleAddress") {
Type oType = obj.GetType();
bool hasBaseIf = oType.GetInterfaces().Any(t => (t == baseIf) );
if ( !hasBaseIf) {
Console.WriteLine($@"Error:'{oType.FullName}' have not the interface '{baseIf.FullName}'");//A have not the interface B.
return null;
}
return (new SVR_T(baseIf, obj, pipeName, pipeAddress));
}
// - public I/F -
public void Close() {
echo($"Close Service:{_service != null},{_serviceHost != null}");
_service = null;
_serviceHost.Close();
}
// - private -
private object _service = null;// 要らないかも
private Type _baseIf = null;
private ServiceHost _serviceHost = null;
private SVR_T() { }
private SVR_T(Type baseIf, object oInstance, string pipeName, string pipeAddress) {
const string pipeBase = "net.pipe://localhost";
var uri = pipeBase + "/" + pipeName;
_baseIf = baseIf;
_service = oInstance;
// デリゲート登録
//callDelegate = () => { Console.WriteLine("svr:Delegate func called"); }
#if false
{
// インターフェースを求める
// AddServiceEndpoint()にわたすIXDataはXData.Interfaces()から求められるが
// インタフェースは一つとは限らないのでやめておく。
Type interfType = null;
Type type = _service.GetType();
Type[] interfaces = type.GetInterfaces();
Console.WriteLine($@"GetInterfaces***********************************");
foreach (Type t in interfaces) {
Console.WriteLine(t.ToString());
interfType = t;
};
Console.WriteLine($@"End of GetInterfaces***********************************");
}
#endif
_serviceHost = new ServiceHost(_service, new Uri(uri));
try {
_serviceHost.AddServiceEndpoint(_baseIf/*typeof(Ti)*/, new NetNamedPipeBinding(), pipeAddress);
_serviceHost.Open();
} catch (AddressAlreadyInUseException) {
Console.WriteLine("既にサービスは起動しています。");
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
}
/// <summary>
/// Sub(クライアント)側クラス
/// </summary>
public class CLT_T
{
/// <summary>
/// Sub側の初期化処理。Main側とpipeName,pipeAddressを同じにすること
/// </summary>
/// <param name="pipeName"></param>
/// <param name="pipeAddress"></param>
/// <returns></returns>
static public Ti makeCLT<Ti>(string pipeName = "PDFormstudioESorGS", string pipeAddress = "SubModuleAddress") {
const string pipeBase = "net.pipe://localhost";
var address = pipeBase + "/" + pipeName + "/" + pipeAddress;
//try {
var factory = (new ChannelFactory<Ti>(new NetNamedPipeBinding(), new EndpointAddress(address)));
Ti toMain = factory.CreateChannel();
return toMain;
//} catch (Exception e) {
// Console.WriteLine("makeCLT failed:" + e.ToString());
// return null;
//}
}
}
}
namespace Ut
{
public class Ut
{
// Util
// --------------------------------------------------------------
/// <summary>
/// 親プロセスが終了したら、自身を終了させる
/// </summary>
/// <param name="bEnable"></param>
public static void SetAutoSelfKillByMainProcEnd(bool bEnable = true) {
if (_SingletonProc != null)
return;//一度しか呼び出せない
if (bEnable == false)
return;
const string fname = "SetAutoSelfKillByMainProcEnd";
// 自動的に親のプロセスがいなくなったら自動的にキルモードを設定する
// メインプロセスの終了チェック
// 親プロセスIDでProcessハンドルを取得、そのExitedイベントに自身の終了関数を設定(Environment.Exit())
int paProcID = GetParentProcessId();
var paProc = Process.GetProcessById(paProcID);
paProc.EnableRaisingEvents = true;
//Console.WriteLine($@"{fname}:ParrentProcessName ={paProc.ProcessName}({paProcID})");
paProc.Exited += new EventHandler(
(object s, EventArgs a) => {
Console.WriteLine($@"{fname}:Exited Event!!!!");
var ss = s as Process;
Console.WriteLine($@"Sure ProcName is {ss.ProcessName}({ss.Id}) {ss.StartInfo.Arguments}"); ;
System.Threading.Thread.Sleep(10 * 1000);
ss.Close();
ss.Dispose();
Console.WriteLine($@"{fname}:Exited Event!!!!(afer10sec)");
//Environment.Exit(-1);
});
//
_SingletonProc = paProc;
}
private static System.Diagnostics.Process _SingletonProc = null;
/// <summary>
/// コマンドライン引数複数個をエンコードして、スペースで結合
/// </summary>
/// <param name="values">string[] コマンドライン引数</param>
/// <returns>コマンドライン文字列(Escaped)</returns>
public static string makeCmdLine(IEnumerable<string> args) {
if (args == null)
throw new ArgumentNullException("args");
string EscapeCmdLineArg(string v) {
if (string.IsNullOrEmpty(v)) return "";
var containsSpace = v.IndexOfAny(new[] { ' ', '\t' }) != -1;
v = ReCommandLineEscapePattern.Replace(v, @"$1\$&");//「\…\"」をエスケープ.「"」直前の「\」の数を 2倍+1
if (containsSpace) {
v = "\"" + ReLastBackSlashPattern.Replace(v, "$1$1") + "\"";
}
return v;
}
return string.Join(" ", args.Select(v => EscapeCmdLineArg(v)));
}
private static Regex ReCommandLineEscapePattern = new Regex("(\\\\*)\"");
private static Regex ReLastBackSlashPattern = new Regex(@"(\\+)$");
/// <summary>
/// 親のプロセスIDを取得する
/// </summary>
/// <returns>親ProcessID</returns>
static int GetParentProcessId() {
var myProcId = GetCurrentProcessId();
var query = string.Format($@"SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = {myProcId}");
//クエリから結果を取得
using (var search = new System.Management.ManagementObjectSearcher(@"root\CIMV2", query))
using (var results = search.Get().GetEnumerator()) {
if (!results.MoveNext())
throw new ApplicationException("Couldn't Get ParrentProcessId.");
var queryResult = results.Current;
//親プロセスのPIDを取得
uint pa = (uint)(queryResult["ParentProcessId"]);
return (int)(pa);
}
}
/// <summary>
/// 自身のプロセスIDを取得する
/// </summary>
/// <returns>ProcessID</returns>
static int GetCurrentProcessId() { return Process.GetCurrentProcess().Id; }
/// <summary>
/// 外部プログラムを起動する
/// </summary>
/// <param name="cmdAndArgs">引数文字列の配列</param>
/// <param name="bSameConsole">true:コンソールを呼び出しと共有 false:別Console Windows</param>
/// <param name="bEcho">標準出力(未実装)</param>
/// <param name="bWait">コマンドが終了するまで待つ(false:未実装,常に待つ)</param>
/// <param name="nWaitLimitMSec">タイムアウト時間ms(未実装)</param>
/// <returns></returns>
public static Process DoCmd(IEnumerable<string> cmdAndArgs, bool bSameConsole = true, bool bEcho = true, bool bWait = false, int nWaitLimitMSec = -1) {
var cmdName = cmdAndArgs.First();//[0];
var argStr = makeCmdLine(cmdAndArgs.Skip(1));// 先頭を除外してコピー new ArraySegment<string>(cmdAndArgs.ToArray(), 1, cmdAndArgs.Count()-1)
//Console.WriteLine($@"DoCmd:{cmdName}:args[{argStr}]");
//using (var p = new Process()) {
var p = new Process();
{
var info = p.StartInfo;
p.StartInfo.FileName = cmdName;
p.StartInfo.Arguments = argStr;
if (bSameConsole) {
//Console.WriteLine("Same windows mode");
p.StartInfo.UseShellExecute = false; // Shell経由で実行しない(必須) true: 別ウインドウ。false:コンソールを共有
p.StartInfo.CreateNoWindow = false; // ウィンドウを作成しない
} else {
//Console.WriteLine("New windows mode");
p.StartInfo.UseShellExecute = true;
p.StartInfo.CreateNoWindow = true;
}
p.Start();// 実行
if (bWait == false) {
return p;
}
if (nWaitLimitMSec == -1) {
p.WaitForExit();// タイムアウト無し
} else {
bool bExit = p.WaitForExit(nWaitLimitMSec);
if (!bExit) {// 処理の終了を待つ
Console.WriteLine("処理が終了しないので強制終了");
p.Kill(); // 強制終了する
return p;
}
}
return p;
}
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC マニフェスト オプション
Windows のユーザー アカウント制御のレベルを変更するには、
requestedExecutionLevel ノードを以下のいずれかで置換します。
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
requestedExecutionLevel 要素を指定すると、ファイルおよびレジストリの仮想化が無効にされます。
アプリケーションが下位互換性を保つためにこの仮想化を要求する場合、この要素を
削除します。
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- このアプリケーションがテストされ、動作するよう設計された Windows バージョンの
一覧。適切な要素をコメント解除すると、最も互換性のある環境を Windows が
自動的に選択します。-->
<!-- Windows Vista -->
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
<!-- Windows 7 -->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
<!-- Windows 8 -->
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
<!-- Windows 8.1 -->
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
<!-- Windows 10 -->
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
</application>
</compatibility>
<!-- アプリケーションが DPI 対応であり、それ以上の DPI で Windows によって自動的にスケーリングされないことを
示します。Windows Presentation Foundation (WPF) アプリケーションは自動的に DPI に対応し、オプトインする必要は
ありません。さらに、この設定にオプトインする .NET Framework 4.6 を対象とする Windows Forms アプリケーションは、
app.config ファイルで 'EnableWindowsFormsHighDpiAutoResizing' 設定を 'true' に設定する必要があります。
per monitor - true
-->
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
<!-- Windows のコモン コントロールとダイアログのテーマを有効にします (Windows XP 以降) -->
<!--
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
-->
</assembly>
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="PdfiumViewer" version="2.13.0.0" targetFramework="net461" />
<package id="PdfiumViewer.Native.x86_64.v8-xfa" version="2018.4.8.256" targetFramework="net461" />
</packages>
\ No newline at end of file

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31613.86
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSRender2019", "CSRender\CSRender2019.csproj", "{FD99EFAA-2479-4E3B-BD1A-5B785288E3B3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FD99EFAA-2479-4E3B-BD1A-5B785288E3B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD99EFAA-2479-4E3B-BD1A-5B785288E3B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD99EFAA-2479-4E3B-BD1A-5B785288E3B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD99EFAA-2479-4E3B-BD1A-5B785288E3B3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8B1418EB-CA5D-4F34-9026-020B0B30AE79}
EndGlobalSection
EndGlobal

:lang: ja
include::config.adoc[]
:toc: left
{ExtendStyle}
// After need empty-one-line
= CSRenderCLI Readme
[.text-right]
--
2022/05/08
--
== Change Log
* V1.3.2.x:2022/05/08 :
- /fc時のhashFile異常時にhashFileを再作成する。PDFファイル更新をチェック
- /fc時のターゲットとリファレンスの同一パスを禁止
- /fc時のVerifyMode追加
* V1.3.2.0:2021/12/20 :aRGB4チャンネル保存からRGB3チャンネルに変更
* V1.3.1.0:2021/10/04 :UWP用、Data.pdfの削除、整理
- UWP用コード削除。通常のファイルアクセスやMemoryStreamに変更
- Widnows RT Windows.Data.pdfの使用を削除.PDFiumのみとした
- /ParaPageオプション追加。PageRenderのスレッド数(Def=4)
- TIFF出力時のJpegのノイズ削除
* V1.3.0.4:2021/04/29 :Helpの記述抜け "/Result"の対応
* V1.3.0.3:2020/11/22 :/Result <比較結果> を実装。diff画像を出力
* V1.3.0.2:2020/07/11 :不具合修正
比較時に差異があるとクラッシュしていた。streamのフラッシュミス
* V1.3.0.1:2020/06/20 :不具合修正
2つのファイルの比較が常にOKになっていた可能性があるので修正
* V1.3.0.0:2020/06/10 :基本的なPDFの画像化(PNG,JPG)とPDFの比較を行えるもの
== Command-Line Parameters
以下、CSRender /? のヘルプ内容です
TestSampleフォルダに使用例がありますので合わせて参照のこと
CSRender.exe [/<Opts>] <PDFPath or PDFDir>
* Render of PDF file. available 3 command mode:[Basic Rendering] [Make Hash command] [Compare command], and [Render Options]
PDFの画像化は[Basic Rendering]。
比較は/MkHash([Make Hash command])後に、/FC([Compare command])で高速実行できます。
[Basic Rendering] 基本的なレンダリング
CSRender.exe [/<Render Options>] <PDFPath|PDFDir>
/F <pdfPath|pdfDir> : pdfPath(pdfファイル名|ディレクトリ) /Fは省略可能
/O <output directory> : 出力ディレクトリ。省略時は"IMG"フォルダ
[Render Options] レンダリングオプション
/D <解像度> : 解像度指定 9 - 300dpi(default=72dpi)
/JPG,/JPEG,/PNG,/TIF,/TIFF,/GIF,/BMP: Select one output format.(default=/JPG)
/JPEGQ <quality>: Jpegの品質指定1-100(default=91)
/P <PageRange> : ページの範囲を指定する(省略時は全ページ)
連続した範囲を指定する場合は、ハイフン('-')を用いる。終了側を省略すると最終pageまで。
複数のページを指定する場合は、カンマ(',')を用いる
Ex. /P "1,2,30-100" //1,2pages and 30-100pages.
[Unsupport] 未対応↓
/L <input List text> : 入力PDFファイルリスト(*unsupport)
/T <tempPath> : テンポラリフォルダを指定(省略時は出力先フォルダと同じ(*unsupport no need)
/OP <0|1> : オーバープリントのOn/Off (省略時は1)(*unsupport allways on[1])
/U <0|1> : 同名上書き設定 0:上書きしない 1:上書き(*unsupport allways overwrite[1])
/OFFSET <X> <Y> : ミリ単位でオフセットを指定する(省略時は共に0mm)(*unsupport)
/PDFium <0or1>: GoogoleのPDFiumViewerエンジンを使用する(default=1>
【未】/BM,/BT,/BA,/BA,/BC: Select one box.(default=/BC:CrobBox): Boxies:MediaBox/BleedBox/TrimBox/ArtBox/CropBox
[Make Hash command] 比較用ハッシュ値作成コマンド
CSRender.exe /MkHash ...<Render Options>... <PDF|PDF dir>
/MKHash : ハッシュ値を出力する。前記の[Render Options]を指定すること
[HASHファイル作成]
[Compare command] 比較コマンド
CSRender.exe /FC ...<Render Options>... <Target PDF|PDF dir> <Reference PDF|PDF dir>
/FC : 2つのPDFを比較する。前記の[Render Options]を指定すること。無名引数が2つ必要です
事前に/MkHashを実行しておくことで高速に処理できる
【未】/RESULT <result file> : 比較結果を格納するファイルパス
/FCコマンドを指定すると一致したら0,不一致なら1を返却するようになる
<result file>は、<pageNum(1始まり)>,<OK or NG>の行で構成される
[ELSE ] その他のオプション
/PDFium <0|1>:PDFiumライブラリを使う,デフォルト=1
/NoExeSepa :実行分離しない(遅い)
内部コマンド:/SubExe <WCF_PipeAddress> :実行分離,PDF単位で別Processで処理
/H or /? : This help
END
\ No newline at end of file
VC2019でのCSRendefソリューションのセットアップ方法 2021/08/30 菱池
1.CSRender.slnのオープン
  VC2019で上記ソリューションを開く
2.ソリューションエクスプローラーの[参照]を右クリックし、[参照の追加(R)...]を選択
2-1.System.Windowsを追加
3.[ツール] -> [NuGet パッケージ マネージャー] -> [パッケージ マネージャー設定] の順にクリック
3-1.[既定のパッケージ管理形式] に [PackageReference] が選択されていることを確認 <-- 重要
3-2.ソリューション エクスプローラー でプロジェクトを右クリックし、 [NuGet パッケージの管理] を選択
3-3.[NuGet パッケージ マネージャー] ウィンドウで、 [参照] タブを選択して、Microsoft.Windows.SDK.Contracts を検索
3-4.Microsoft.Windows.SDK.Contracts パッケージが見つかったら、 [NuGet パッケージ マネージャー] ウィンドウの右側のペインで
    ターゲットにする Windows 10 のバージョンに基づいて、インストールするパッケージの バージョン を選択
    ※10.0.19041.xxxx:Windows 10 Version 2004 の場合は、これを選択
3-5.[インストール] をクリック
備考:Microsoft.Windows.SDK.Contractsが見つからない場合、または使用できない場合
4.[NuGet パッケージ マネージャー] ウィンドウの右上にあるパッケージソースが「nuget.org」になっていることを確認
5.なっていない場合は、右側の設定アイコンをクリック
6.「+」ボタンを押下し、
    名前 :nuget.org
    ソース:https://api.nuget.org/v3/index.json
  更新ボタンを押下
7.Microsoft.Windows.SDK.Contractsを再インストールする
参照:https://docs.microsoft.com/en-us/dotnet/api/system.drawing.imaging.encoder.compression?view=net-5.0
A\Data.pdf
B\Data.pdf
50Pageのデータで49pageだけ、内容が異なるものです
●CSRender /fc A\Data.pdf B\Data.pdf
で実行すると、A\IMGフォルダを作成して、完全一致しないJPEGファイルを
生成します。この場合は49pageのみ。
IMG\
Data.pdf.49.tgt.jpg
Data.pdf.49.ref.jpg
差異は、WinMeergeで十分確認できるでしょう
●CSRender /fc A B
同一ファイル名のPDFファイルをそれぞれ配置した場合はフォルダ指定で
比較可能。この場合は、A Bと同一階層のIMGフォルダに出力されます。
いずれも一致したかどうかはコンソールに出力されるのでリダイレクトして確認ください
すべて一致した場合は、CSRenderは0を返却。一つでも不一致だとNot0を返却します。
以上です。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
</startup>
</configuration>
<?xml version="1.0"?>
<doc>
<assembly>
<name>PdfiumViewer</name>
</assembly>
<members>
<member name="M:PdfiumViewer.CustomScrollControl.IsInputKey(System.Windows.Forms.Keys)">
<summary>
Determines whether the specified key is a regular input key or a special key that requires preprocessing.
</summary>
<returns>
true if the specified key is a regular input key; otherwise, false.
</returns>
<param name="keyData">One of the <see cref="T:System.Windows.Forms.Keys"/> values. </param>
</member>
<member name="T:PdfiumViewer.IPdfDocument">
<summary>
Represents a PDF document.
</summary>
</member>
<member name="P:PdfiumViewer.IPdfDocument.PageCount">
<summary>
Number of pages in the PDF document.
</summary>
</member>
<member name="P:PdfiumViewer.IPdfDocument.Bookmarks">
<summary>
Bookmarks stored in this PdfFile
</summary>
</member>
<member name="P:PdfiumViewer.IPdfDocument.PageSizes">
<summary>
Size of each page in the PDF document.
</summary>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Render(System.Int32,System.Drawing.Graphics,System.Single,System.Single,System.Drawing.Rectangle,System.Boolean)">
<summary>
Renders a page of the PDF document to the provided graphics instance.
</summary>
<param name="page">Number of the page to render.</param>
<param name="graphics">Graphics instance to render the page on.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="bounds">Bounds to render the page in.</param>
<param name="forPrinting">Render the page for printing.</param>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Render(System.Int32,System.Drawing.Graphics,System.Single,System.Single,System.Drawing.Rectangle,PdfiumViewer.PdfRenderFlags)">
<summary>
Renders a page of the PDF document to the provided graphics instance.
</summary>
<param name="page">Number of the page to render.</param>
<param name="graphics">Graphics instance to render the page on.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="bounds">Bounds to render the page in.</param>
<param name="flags">Flags used to influence the rendering.</param>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Render(System.Int32,System.Single,System.Single,System.Boolean)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="forPrinting">Render the page for printing.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Render(System.Int32,System.Single,System.Single,PdfiumViewer.PdfRenderFlags)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="flags">Flags used to influence the rendering.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Render(System.Int32,System.Int32,System.Int32,System.Single,System.Single,System.Boolean)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="width">Width of the rendered image.</param>
<param name="height">Height of the rendered image.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="forPrinting">Render the page for printing.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Render(System.Int32,System.Int32,System.Int32,System.Single,System.Single,PdfiumViewer.PdfRenderFlags)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="width">Width of the rendered image.</param>
<param name="height">Height of the rendered image.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="flags">Flags used to influence the rendering.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Render(System.Int32,System.Int32,System.Int32,System.Single,System.Single,PdfiumViewer.PdfRotation,PdfiumViewer.PdfRenderFlags)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="width">Width of the rendered image.</param>
<param name="height">Height of the rendered image.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="rotate">Rotation.</param>
<param name="flags">Flags used to influence the rendering.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Save(System.String)">
<summary>
Save the PDF document to the specified location.
</summary>
<param name="path">Path to save the PDF document to.</param>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Save(System.IO.Stream)">
<summary>
Save the PDF document to the specified location.
</summary>
<param name="stream">Stream to save the PDF document to.</param>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Search(System.String,System.Boolean,System.Boolean)">
<summary>
Finds all occurences of text.
</summary>
<param name="text">The text to search for.</param>
<param name="matchCase">Whether to match case.</param>
<param name="wholeWord">Whether to match whole words only.</param>
<returns>All matches.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Search(System.String,System.Boolean,System.Boolean,System.Int32)">
<summary>
Finds all occurences of text.
</summary>
<param name="text">The text to search for.</param>
<param name="matchCase">Whether to match case.</param>
<param name="wholeWord">Whether to match whole words only.</param>
<param name="page">The page to search on.</param>
<returns>All matches.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Search(System.String,System.Boolean,System.Boolean,System.Int32,System.Int32)">
<summary>
Finds all occurences of text.
</summary>
<param name="text">The text to search for.</param>
<param name="matchCase">Whether to match case.</param>
<param name="wholeWord">Whether to match whole words only.</param>
<param name="startPage">The page to start searching.</param>
<param name="endPage">The page to end searching.</param>
<returns>All matches.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.CreatePrintDocument">
<summary>
Creates a <see cref="T:System.Drawing.Printing.PrintDocument"/> for the PDF document.
</summary>
<returns></returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.CreatePrintDocument(PdfiumViewer.PdfPrintMode)">
<summary>
Creates a <see cref="T:System.Drawing.Printing.PrintDocument"/> for the PDF document.
</summary>
<param name="printMode">Specifies the mode for printing. The default
value for this parameter is CutMargin.</param>
<returns></returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.CreatePrintDocument(PdfiumViewer.PdfPrintSettings)">
<summary>
Creates a <see cref="T:System.Drawing.Printing.PrintDocument"/> for the PDF document.
</summary>
<param name="settings">The settings used to configure the print document.</param>
<returns></returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.GetPageLinks(System.Int32,System.Drawing.Size)">
<summary>
Returns all links on the PDF page.
</summary>
<param name="page">The page to get the links for.</param>
<param name="size">The size of the page.</param>
<returns>A collection with the links on the page.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.DeletePage(System.Int32)">
<summary>
Delete the page from the PDF document.
</summary>
<param name="page">The page to delete.</param>
</member>
<member name="M:PdfiumViewer.IPdfDocument.RotatePage(System.Int32,PdfiumViewer.PdfRotation)">
<summary>
Rotate the page.
</summary>
<param name="page">The page to rotate.</param>
<param name="rotation">How to rotate the page.</param>
</member>
<member name="M:PdfiumViewer.IPdfDocument.GetInformation">
<summary>
Get metadata information from the PDF document.
</summary>
<returns>The PDF metadata.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.GetPdfText(System.Int32)">
<summary>
Get all text on the page.
</summary>
<param name="page">The page to get the text for.</param>
<returns>The text on the page.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.GetPdfText(PdfiumViewer.PdfTextSpan)">
<summary>
Get all text matching the text span.
</summary>
<param name="textSpan">The span to get the text for.</param>
<returns>The text matching the span.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.GetTextBounds(PdfiumViewer.PdfTextSpan)">
<summary>
Get all bounding rectangles for the text span.
</summary>
<description>
The algorithm used to get the bounding rectangles tries to join
adjacent character bounds into larger rectangles.
</description>
<param name="textSpan">The span to get the bounding rectangles for.</param>
<returns>The bounding rectangles.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.PointToPdf(System.Int32,System.Drawing.Point)">
<summary>
Convert a point from device coordinates to page coordinates.
</summary>
<param name="page">The page number where the point is from.</param>
<param name="point">The point to convert.</param>
<returns>The converted point.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.PointFromPdf(System.Int32,System.Drawing.PointF)">
<summary>
Convert a point from page coordinates to device coordinates.
</summary>
<param name="page">The page number where the point is from.</param>
<param name="point">The point to convert.</param>
<returns>The converted point.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.RectangleToPdf(System.Int32,System.Drawing.Rectangle)">
<summary>
Convert a rectangle from device coordinates to page coordinates.
</summary>
<param name="page">The page where the rectangle is from.</param>
<param name="rect">The rectangle to convert.</param>
<returns>The converted rectangle.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.RectangleFromPdf(System.Int32,System.Drawing.RectangleF)">
<summary>
Convert a rectangle from page coordinates to device coordinates.
</summary>
<param name="page">The page where the rectangle is from.</param>
<param name="rect">The rectangle to convert.</param>
<returns>The converted rectangle.</returns>
</member>
<member name="T:PdfiumViewer.IPdfMarker">
<summary>
Represents a marker on a PDF page.
</summary>
</member>
<member name="P:PdfiumViewer.IPdfMarker.Page">
<summary>
The page where the marker is drawn on.
</summary>
</member>
<member name="M:PdfiumViewer.IPdfMarker.Draw(PdfiumViewer.PdfRenderer,System.Drawing.Graphics)">
<summary>
Draw the marker.
</summary>
<param name="renderer">The PdfRenderer to draw the marker with.</param>
<param name="graphics">The Graphics to draw the marker with.</param>
</member>
<member name="P:PdfiumViewer.LinkClickEventArgs.Link">
<summary>
Gets the link that was clicked.
</summary>
</member>
<member name="M:PdfiumViewer.NativeMethods.FPDF_LoadCustomDocument(System.IO.Stream,System.String,System.Int32)">
<summary>
Opens a document using a .NET Stream. Allows opening huge
PDFs without loading them into memory first.
</summary>
<param name="input">The input Stream. Don't dispose prior to closing the pdf.</param>
<param name="password">Password, if the PDF is protected. Can be null.</param>
<param name="id">Retrieves an IntPtr to the COM object for the Stream. The caller must release this with Marshal.Release prior to Disposing the Stream.</param>
<returns>An IntPtr to the FPDF_DOCUMENT object.</returns>
</member>
<member name="P:PdfiumViewer.PanningZoomingScrollControl.Zoom">
<summary>
Gets or sets the current zoom level.
</summary>
</member>
<member name="M:PdfiumViewer.PanningZoomingScrollControl.ZoomIn">
<summary>
Zooms the PDF document in one step.
</summary>
</member>
<member name="M:PdfiumViewer.PanningZoomingScrollControl.ZoomOut">
<summary>
Zooms the PDF document out one step.
</summary>
</member>
<member name="M:PdfiumViewer.PanningZoomingScrollControl.OnMouseWheel(System.Windows.Forms.MouseEventArgs)">
<summary>
Raises the <see cref="E:System.Windows.Forms.Control.MouseWheel"/> event.
</summary>
<param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data. </param>
</member>
<member name="M:PdfiumViewer.PanningZoomingScrollControl.IsInputKey(System.Windows.Forms.Keys)">
<summary>
Determines whether the specified key is a regular input key or a special key that requires preprocessing.
</summary>
<returns>
true if the specified key is a regular input key; otherwise, false.
</returns>
<param name="keyData">One of the <see cref="T:System.Windows.Forms.Keys"/> values. </param>
</member>
<member name="F:PdfiumViewer.PasswordForm.components">
<summary>
Required designer variable.
</summary>
</member>
<member name="M:PdfiumViewer.PasswordForm.Dispose(System.Boolean)">
<summary>
Clean up any resources being used.
</summary>
<param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
</member>
<member name="M:PdfiumViewer.PasswordForm.InitializeComponent">
<summary>
Required method for Designer support - do not modify
the contents of this method with the code editor.
</summary>
</member>
<member name="T:PdfiumViewer.PdfPrintMultiplePages">
<summary>
Configuration for printing multiple PDF pages on a single page.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPrintMultiplePages.Horizontal">
<summary>
Gets the number of pages to print horizontally.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPrintMultiplePages.Vertical">
<summary>
Gets the number of pages to print vertically.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPrintMultiplePages.Orientation">
<summary>
Gets the orientation in which PDF pages are layed out on the
physical page.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPrintMultiplePages.Margin">
<summary>
Gets the margin between PDF pages in device units.
</summary>
</member>
<member name="M:PdfiumViewer.PdfPrintMultiplePages.#ctor(System.Int32,System.Int32,System.Windows.Forms.Orientation,System.Single)">
<summary>
Creates a new instance of the PdfPrintMultiplePages class.
</summary>
<param name="horizontal">The number of pages to print horizontally.</param>
<param name="vertical">The number of pages to print vertically.</param>
<param name="orientation">The orientation in which PDF pages are layed out on
the physical page.</param>
<param name="margin">The margin between PDF pages in device units.</param>
</member>
<member name="T:PdfiumViewer.PdfPrintSettings">
<summary>
Configures the print document.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPrintSettings.Mode">
<summary>
Gets the mode used to print margins.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPrintSettings.MultiplePages">
<summary>
Gets configuration for printing multiple PDF pages on a single page.
</summary>
</member>
<member name="M:PdfiumViewer.PdfPrintSettings.#ctor(PdfiumViewer.PdfPrintMode,PdfiumViewer.PdfPrintMultiplePages)">
<summary>
Creates a new instance of the PdfPrintSettings class.
</summary>
<param name="mode">The mode used to print margins.</param>
<param name="multiplePages">Configuration for printing multiple PDF
pages on a single page.</param>
</member>
<member name="T:PdfiumViewer.PdfDocument">
<summary>
Provides functionality to render a PDF document.
</summary>
</member>
<member name="M:PdfiumViewer.PdfDocument.Load(System.String)">
<summary>
Initializes a new instance of the PdfDocument class with the provided path.
</summary>
<param name="path">Path to the PDF document.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Load(System.String,System.String)">
<summary>
Initializes a new instance of the PdfDocument class with the provided path.
</summary>
<param name="path">Path to the PDF document.</param>
<param name="password">Password for the PDF document.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Load(System.Windows.Forms.IWin32Window,System.String)">
<summary>
Initializes a new instance of the PdfDocument class with the provided path.
</summary>
<param name="owner">Window to show any UI for.</param>
<param name="path">Path to the PDF document.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Load(System.Windows.Forms.IWin32Window,System.IO.Stream)">
<summary>
Initializes a new instance of the PdfDocument class with the provided path.
</summary>
<param name="owner">Window to show any UI for.</param>
<param name="stream">Stream for the PDF document.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Load(System.IO.Stream)">
<summary>
Initializes a new instance of the PdfDocument class with the provided stream.
</summary>
<param name="stream">Stream for the PDF document.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Load(System.IO.Stream,System.String)">
<summary>
Initializes a new instance of the PdfDocument class with the provided stream.
</summary>
<param name="stream">Stream for the PDF document.</param>
<param name="password">Password for the PDF document.</param>
</member>
<member name="P:PdfiumViewer.PdfDocument.PageCount">
<summary>
Number of pages in the PDF document.
</summary>
</member>
<member name="P:PdfiumViewer.PdfDocument.Bookmarks">
<summary>
Bookmarks stored in this PdfFile
</summary>
</member>
<member name="P:PdfiumViewer.PdfDocument.PageSizes">
<summary>
Size of each page in the PDF document.
</summary>
</member>
<member name="M:PdfiumViewer.PdfDocument.Render(System.Int32,System.Drawing.Graphics,System.Single,System.Single,System.Drawing.Rectangle,System.Boolean)">
<summary>
Renders a page of the PDF document to the provided graphics instance.
</summary>
<param name="page">Number of the page to render.</param>
<param name="graphics">Graphics instance to render the page on.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="bounds">Bounds to render the page in.</param>
<param name="forPrinting">Render the page for printing.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Render(System.Int32,System.Drawing.Graphics,System.Single,System.Single,System.Drawing.Rectangle,PdfiumViewer.PdfRenderFlags)">
<summary>
Renders a page of the PDF document to the provided graphics instance.
</summary>
<param name="page">Number of the page to render.</param>
<param name="graphics">Graphics instance to render the page on.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="bounds">Bounds to render the page in.</param>
<param name="flags">Flags used to influence the rendering.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Render(System.Int32,System.Single,System.Single,System.Boolean)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="forPrinting">Render the page for printing.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.Render(System.Int32,System.Single,System.Single,PdfiumViewer.PdfRenderFlags)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="flags">Flags used to influence the rendering.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.Render(System.Int32,System.Int32,System.Int32,System.Single,System.Single,System.Boolean)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="width">Width of the rendered image.</param>
<param name="height">Height of the rendered image.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="forPrinting">Render the page for printing.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.Render(System.Int32,System.Int32,System.Int32,System.Single,System.Single,PdfiumViewer.PdfRenderFlags)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="width">Width of the rendered image.</param>
<param name="height">Height of the rendered image.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="flags">Flags used to influence the rendering.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.Render(System.Int32,System.Int32,System.Int32,System.Single,System.Single,PdfiumViewer.PdfRotation,PdfiumViewer.PdfRenderFlags)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="width">Width of the rendered image.</param>
<param name="height">Height of the rendered image.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="rotate">Rotation.</param>
<param name="flags">Flags used to influence the rendering.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.Save(System.String)">
<summary>
Save the PDF document to the specified location.
</summary>
<param name="path">Path to save the PDF document to.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Save(System.IO.Stream)">
<summary>
Save the PDF document to the specified location.
</summary>
<param name="stream">Stream to save the PDF document to.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Search(System.String,System.Boolean,System.Boolean)">
<summary>
Finds all occurences of text.
</summary>
<param name="text">The text to search for.</param>
<param name="matchCase">Whether to match case.</param>
<param name="wholeWord">Whether to match whole words only.</param>
<returns>All matches.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.Search(System.String,System.Boolean,System.Boolean,System.Int32)">
<summary>
Finds all occurences of text.
</summary>
<param name="text">The text to search for.</param>
<param name="matchCase">Whether to match case.</param>
<param name="wholeWord">Whether to match whole words only.</param>
<param name="page">The page to search on.</param>
<returns>All matches.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.Search(System.String,System.Boolean,System.Boolean,System.Int32,System.Int32)">
<summary>
Finds all occurences of text.
</summary>
<param name="text">The text to search for.</param>
<param name="matchCase">Whether to match case.</param>
<param name="wholeWord">Whether to match whole words only.</param>
<param name="startPage">The page to start searching.</param>
<param name="endPage">The page to end searching.</param>
<returns>All matches.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.GetPdfText(System.Int32)">
<summary>
Get all text on the page.
</summary>
<param name="page">The page to get the text for.</param>
<returns>The text on the page.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.GetPdfText(PdfiumViewer.PdfTextSpan)">
<summary>
Get all text matching the text span.
</summary>
<param name="textSpan">The span to get the text for.</param>
<returns>The text matching the span.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.GetTextBounds(PdfiumViewer.PdfTextSpan)">
<summary>
Get all bounding rectangles for the text span.
</summary>
<description>
The algorithm used to get the bounding rectangles tries to join
adjacent character bounds into larger rectangles.
</description>
<param name="textSpan">The span to get the bounding rectangles for.</param>
<returns>The bounding rectangles.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.PointToPdf(System.Int32,System.Drawing.Point)">
<summary>
Convert a point from device coordinates to page coordinates.
</summary>
<param name="page">The page number where the point is from.</param>
<param name="point">The point to convert.</param>
<returns>The converted point.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.PointFromPdf(System.Int32,System.Drawing.PointF)">
<summary>
Convert a point from page coordinates to device coordinates.
</summary>
<param name="page">The page number where the point is from.</param>
<param name="point">The point to convert.</param>
<returns>The converted point.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.RectangleToPdf(System.Int32,System.Drawing.Rectangle)">
<summary>
Convert a rectangle from device coordinates to page coordinates.
</summary>
<param name="page">The page where the rectangle is from.</param>
<param name="rect">The rectangle to convert.</param>
<returns>The converted rectangle.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.RectangleFromPdf(System.Int32,System.Drawing.RectangleF)">
<summary>
Convert a rectangle from page coordinates to device coordinates.
</summary>
<param name="page">The page where the rectangle is from.</param>
<param name="rect">The rectangle to convert.</param>
<returns>The converted rectangle.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.CreatePrintDocument">
<summary>
Creates a <see cref="T:System.Drawing.Printing.PrintDocument"/> for the PDF document.
</summary>
<returns></returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.CreatePrintDocument(PdfiumViewer.PdfPrintMode)">
<summary>
Creates a <see cref="T:System.Drawing.Printing.PrintDocument"/> for the PDF document.
</summary>
<param name="printMode">Specifies the mode for printing. The default
value for this parameter is CutMargin.</param>
<returns></returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.CreatePrintDocument(PdfiumViewer.PdfPrintSettings)">
<summary>
Creates a <see cref="T:System.Drawing.Printing.PrintDocument"/> for the PDF document.
</summary>
<param name="settings">The settings used to configure the print document.</param>
<returns></returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.GetPageLinks(System.Int32,System.Drawing.Size)">
<summary>
Returns all links on the PDF page.
</summary>
<param name="page">The page to get the links for.</param>
<param name="size">The size of the page.</param>
<returns>A collection with the links on the page.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.DeletePage(System.Int32)">
<summary>
Delete the page from the PDF document.
</summary>
<param name="page">The page to delete.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.RotatePage(System.Int32,PdfiumViewer.PdfRotation)">
<summary>
Rotate the page.
</summary>
<param name="page">The page to rotate.</param>
<param name="rotation">How to rotate the page.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.GetInformation">
<summary>
Get metadata information from the PDF document.
</summary>
<returns>The PDF metadata.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.Dispose">
<summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
<filterpriority>2</filterpriority>
</member>
<member name="M:PdfiumViewer.PdfDocument.Dispose(System.Boolean)">
<summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
<param name="disposing">Whether this method is called from Dispose.</param>
</member>
<member name="T:PdfiumViewer.PdfInformation">
<summary>
Contains text from metadata of the document.
</summary>
</member>
<member name="T:PdfiumViewer.PdfSearchManager">
<summary>
Helper class for searching through PDF documents.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.Renderer">
<summary>
The renderer associated with the search manager.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.MatchCase">
<summary>
Gets or sets whether to match case.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.MatchWholeWord">
<summary>
Gets or sets whether to match whole words.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.MatchColor">
<summary>
Gets or sets the color of matched search terms.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.MatchBorderColor">
<summary>
Gets or sets the border color of matched search terms.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.MatchBorderWidth">
<summary>
Gets or sets the border width of matched search terms.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.CurrentMatchColor">
<summary>
Gets or sets the color of the current match.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.CurrentMatchBorderColor">
<summary>
Gets or sets the border color of the current match.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.CurrentMatchBorderWidth">
<summary>
Gets or sets the border width of the current match.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.HighlightAllMatches">
<summary>
Gets or sets whether all matches should be highlighted.
</summary>
</member>
<member name="M:PdfiumViewer.PdfSearchManager.#ctor(PdfiumViewer.PdfRenderer)">
<summary>
Creates a new instance of the search manager.
</summary>
<param name="renderer">The renderer to create the search manager for.</param>
</member>
<member name="M:PdfiumViewer.PdfSearchManager.Search(System.String)">
<summary>
Searches for the specified text.
</summary>
<param name="text">The text to search.</param>
<returns>Whether any matches were found.</returns>
</member>
<member name="M:PdfiumViewer.PdfSearchManager.FindNext(System.Boolean)">
<summary>
Find the next matched term.
</summary>
<param name="forward">Whether or not to search forward.</param>
<returns>False when the first match was found again; otherwise true.</returns>
</member>
<member name="M:PdfiumViewer.PdfSearchManager.Reset">
<summary>
Resets the search manager.
</summary>
</member>
<member name="T:PdfiumViewer.PdfPageLink">
<summary>
Describes a link on a page.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPageLink.Bounds">
<summary>
The location of the link.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPageLink.TargetPage">
<summary>
The target of the link.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPageLink.Uri">
<summary>
The target URI of the link.
</summary>
</member>
<member name="M:PdfiumViewer.PdfPageLink.#ctor(System.Drawing.RectangleF,System.Nullable{System.Int32},System.String)">
<summary>
Creates a new instance of the PdfPageLink class.
</summary>
<param name="bounds">The location of the link</param>
<param name="targetPage">The target page of the link</param>
<param name="uri">The target URI of the link</param>
</member>
<member name="T:PdfiumViewer.PdfPageLinks">
<summary>
Describes all links on a page.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPageLinks.Links">
<summary>
All links of the page.
</summary>
</member>
<member name="M:PdfiumViewer.PdfPageLinks.#ctor(System.Collections.Generic.IList{PdfiumViewer.PdfPageLink})">
<summary>
Creates a new instance of the PdfPageLinks class.
</summary>
<param name="links">The links on the PDF page.</param>
</member>
<member name="T:PdfiumViewer.PdfPrintMode">
<summary>
Specifies the mode in which the document should be printed.
</summary>
<remarks>
Printers have a hard margin. This is a (small) margin on which it is not
possible to print. PdfPrintMode specifies whether the page should be
scaled to fit into this margin, or that the margin should be cut off of
the page.
</remarks>
</member>
<member name="F:PdfiumViewer.PdfPrintMode.ShrinkToMargin">
<summary>
Shrink the print area to fall within the hard printer margin.
</summary>
</member>
<member name="F:PdfiumViewer.PdfPrintMode.CutMargin">
<summary>
Cut the hard printer margin from the output.
</summary>
</member>
<member name="T:PdfiumViewer.PdfRenderFlags">
<summary>
Flags that influence the page rendering process.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.None">
<summary>
No flags.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.ForPrinting">
<summary>
Render for printing.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.Annotations">
<summary>
Set if annotations are to be rendered.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.LcdText">
<summary>
Set if using text rendering optimized for LCD display.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.NoNativeText">
<summary>
Don't use the native text output available on some platforms.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.Grayscale">
<summary>
Grayscale output.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.LimitImageCacheSize">
<summary>
Limit image cache size.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.ForceHalftone">
<summary>
Always use halftone for image stretching.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.Transparent">
<summary>
Render with a transparent background.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.CorrectFromDpi">
<summary>
Correct height/width for DPI.
</summary>
</member>
<member name="T:PdfiumViewer.PdfRenderer">
<summary>
Control to render PDF documents.
</summary>
</member>
<member name="P:PdfiumViewer.PdfRenderer.Document">
<summary>
The associated PDF document.
</summary>
</member>
<member name="P:PdfiumViewer.PdfRenderer.TabStop">
<summary>
Gets or sets a value indicating whether the user can give the focus to this control using the TAB key.
</summary>
<returns>
true if the user can give the focus to the control using the TAB key; otherwise, false. The default is true.Note:This property will always return true for an instance of the <see cref="T:System.Windows.Forms.Form"/> class.
</returns>
<filterpriority>1</filterpriority><PermissionSet><IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/><IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence"/><IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/></PermissionSet>
</member>
<member name="P:PdfiumViewer.PdfRenderer.Page">
<summary>
Gets or sets the currently focused page.
</summary>
</member>
<member name="M:PdfiumViewer.PdfRenderer.GetOuterBounds(System.Int32)">
<summary>
Get the outer bounds of the page.
</summary>
<param name="page">The page to get the bounds for.</param>
<returns>The bounds of the page.</returns>
</member>
<member name="P:PdfiumViewer.PdfRenderer.ZoomMode">
<summary>
Gets or sets the way the document should be zoomed initially.
</summary>
</member>
<member name="P:PdfiumViewer.PdfRenderer.Rotation">
<summary>
Gets or sets the current rotation of the PDF document.
</summary>
</member>
<member name="P:PdfiumViewer.PdfRenderer.Markers">
<summary>
Gets a collection with all markers.
</summary>
</member>
<member name="M:PdfiumViewer.PdfRenderer.#ctor">
<summary>
Initializes a new instance of the PdfRenderer class.
</summary>
</member>
<member name="M:PdfiumViewer.PdfRenderer.PointToPdf(System.Drawing.Point)">
<summary>
Converts client coordinates to PDF coordinates.
</summary>
<param name="location">Client coordinates to get the PDF location for.</param>
<returns>The location in a PDF page or a PdfPoint with IsValid false when the coordinates do not match a PDF page.</returns>
</member>
<member name="M:PdfiumViewer.PdfRenderer.PointFromPdf(PdfiumViewer.PdfPoint)">
<summary>
Converts a PDF point to a client point.
</summary>
<param name="point">The PDF point to convert.</param>
<returns>The location of the point in client coordinates.</returns>
</member>
<member name="M:PdfiumViewer.PdfRenderer.BoundsToPdf(System.Drawing.Rectangle)">
<summary>
Converts client coordinates to PDF bounds.
</summary>
<param name="bounds">The client coordinates to convert.</param>
<returns>The PDF bounds.</returns>
</member>
<member name="M:PdfiumViewer.PdfRenderer.BoundsFromPdf(PdfiumViewer.PdfRectangle)">
<summary>
Converts PDF bounds to client bounds.
</summary>
<param name="bounds">The PDF bounds to convert.</param>
<returns>The bounds of the PDF bounds in client coordinates.</returns>
</member>
<member name="M:PdfiumViewer.PdfRenderer.OnLayout(System.Windows.Forms.LayoutEventArgs)">
<summary>
Raises the <see cref="E:System.Windows.Forms.Control.Layout"/> event.
</summary>
<param name="levent">A <see cref="T:System.Windows.Forms.LayoutEventArgs"/> that contains the event data. </param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.OnZoomChanged(System.EventArgs)">
<summary>
Called when the zoom level changes.
</summary>
<param name="e">The event args.</param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.Load(PdfiumViewer.IPdfDocument)">
<summary>
Load a <see cref="T:PdfiumViewer.IPdfDocument"/> into the control.
</summary>
<param name="document">Document to load.</param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.OnPaint(System.Windows.Forms.PaintEventArgs)">
<summary>
Raises the <see cref="E:System.Windows.Forms.Control.Paint"/> event.
</summary>
<param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs"/> that contains the event data. </param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.GetDocumentBounds">
<summary>
Gets the document bounds.
</summary>
<returns>The document bounds.</returns>
</member>
<member name="M:PdfiumViewer.PdfRenderer.OnSetCursor(PdfiumViewer.SetCursorEventArgs)">
<summary>
Called whent he cursor changes.
</summary>
<param name="e">The event args.</param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.OnMouseDown(System.Windows.Forms.MouseEventArgs)">
<summary>Raises the <see cref="E:System.Windows.Forms.Control.MouseDown" /> event.</summary>
<param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs" /> that contains the event data. </param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.OnMouseUp(System.Windows.Forms.MouseEventArgs)">
<summary>Raises the <see cref="E:System.Windows.Forms.Control.MouseUp" /> event.</summary>
<param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs" /> that contains the event data. </param>
</member>
<member name="E:PdfiumViewer.PdfRenderer.LinkClick">
<summary>
Occurs when a link in the pdf document is clicked.
</summary>
</member>
<member name="M:PdfiumViewer.PdfRenderer.OnLinkClick(PdfiumViewer.LinkClickEventArgs)">
<summary>
Called when a link is clicked.
</summary>
<param name="e">The event args.</param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.RotateLeft">
<summary>
Rotate the PDF document left.
</summary>
</member>
<member name="M:PdfiumViewer.PdfRenderer.RotateRight">
<summary>
Rotate the PDF document right.
</summary>
</member>
<member name="M:PdfiumViewer.PdfRenderer.SetZoom(System.Double,System.Nullable{System.Drawing.Point})">
<summary>
Called when the zoom level changes.
</summary>
<param name="zoom">The new zoom level.</param>
<param name="focus">The location to focus on.</param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.ScrollIntoView(PdfiumViewer.PdfRectangle)">
<summary>
Scroll the PDF bounds into view.
</summary>
<param name="bounds">The PDF bounds to scroll into view.</param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.ScrollIntoView(System.Drawing.Rectangle)">
<summary>
Scroll the client rectangle into view.
</summary>
<param name="rectangle">The client rectangle to scroll into view.</param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.Dispose(System.Boolean)">
<summary>
Releases the unmanaged resources used by the <see cref="T:System.Windows.Forms.Control"/> and its child controls and optionally releases the managed resources.
</summary>
<param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources. </param>
</member>
<member name="T:PdfiumViewer.PdfRotation">
<summary>
Specifies the rotation of pages shown in the PDF renderer.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRotation.Rotate0">
<summary>
Rotates the output 0 degrees.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRotation.Rotate90">
<summary>
Rotates the output 90 degrees.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRotation.Rotate180">
<summary>
Rotates the output 180 degrees.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRotation.Rotate270">
<summary>
Rotates the output 270 degrees.
</summary>
</member>
<member name="T:PdfiumViewer.PdfViewer">
<summary>
Control to host PDF documents with support for printing.
</summary>
</member>
<member name="P:PdfiumViewer.PdfViewer.Document">
<summary>
Gets or sets the PDF document.
</summary>
</member>
<member name="P:PdfiumViewer.PdfViewer.Renderer">
<summary>
Get the <see cref="T:PdfiumViewer.PdfRenderer"/> that renders the PDF document.
</summary>
</member>
<member name="P:PdfiumViewer.PdfViewer.DefaultDocumentName">
<summary>
Gets or sets the default document name used when saving the document.
</summary>
</member>
<member name="P:PdfiumViewer.PdfViewer.DefaultPrintMode">
<summary>
Gets or sets the default print mode.
</summary>
</member>
<member name="P:PdfiumViewer.PdfViewer.ZoomMode">
<summary>
Gets or sets the way the document should be zoomed initially.
</summary>
</member>
<member name="P:PdfiumViewer.PdfViewer.ShowToolbar">
<summary>
Gets or sets whether the toolbar should be shown.
</summary>
</member>
<member name="P:PdfiumViewer.PdfViewer.ShowBookmarks">
<summary>
Gets or sets whether the bookmarks panel should be shown.
</summary>
</member>
<member name="P:PdfiumViewer.PdfViewer.DefaultPrinter">
<summary>
Gets or sets the pre-selected printer to be used when the print
dialog shows up.
</summary>
</member>
<member name="E:PdfiumViewer.PdfViewer.LinkClick">
<summary>
Occurs when a link in the pdf document is clicked.
</summary>
</member>
<member name="M:PdfiumViewer.PdfViewer.OnLinkClick(PdfiumViewer.LinkClickEventArgs)">
<summary>
Called when a link is clicked.
</summary>
<param name="e"></param>
</member>
<member name="M:PdfiumViewer.PdfViewer.#ctor">
<summary>
Initializes a new instance of the PdfViewer class.
</summary>
</member>
<member name="F:PdfiumViewer.PdfViewer.components">
<summary>
Required designer variable.
</summary>
</member>
<member name="M:PdfiumViewer.PdfViewer.Dispose(System.Boolean)">
<summary>
Clean up any resources being used.
</summary>
<param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
</member>
<member name="M:PdfiumViewer.PdfViewer.InitializeComponent">
<summary>
Required method for Designer support - do not modify
the contents of this method with the code editor.
</summary>
</member>
<member name="T:PdfiumViewer.Properties.Resources">
<summary>
A strongly-typed resource class, for looking up localized strings, etc.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ResourceManager">
<summary>
Returns the cached ResourceManager instance used by this class.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.Culture">
<summary>
Overrides the current thread's CurrentUICulture property for all
resource lookups using this strongly typed resource class.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.disk_blue">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.PageNumber">
<summary>
Looks up a localized string similar to Page {0}.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.printer">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.SaveAsFailedText">
<summary>
Looks up a localized string similar to Could not save the PDF file to the specified location..
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.SaveAsFailedTitle">
<summary>
Looks up a localized string similar to Could not save file.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.SaveAsFilter">
<summary>
Looks up a localized string similar to PDF Files (*.pdf)|*.pdf|All Files (*.*)|*.*.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.SaveAsTitle">
<summary>
Looks up a localized string similar to Save As.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ShadeBorder_E">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ShadeBorder_N">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ShadeBorder_NE">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ShadeBorder_NW">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ShadeBorder_S">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ShadeBorder_SE">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ShadeBorder_SW">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ShadeBorder_W">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.zoom_in">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.zoom_out">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
</members>
</doc>
param($installPath, $toolsPath, $package, $project)
$DTE.ItemOperations.Navigate("https://github.com/pvginkel/PdfiumViewer/wiki/Installation-instructions")
<?xml version="1.0"?>
<doc>
<assembly>
<name>PdfiumViewer</name>
</assembly>
<members>
<member name="M:PdfiumViewer.CustomScrollControl.IsInputKey(System.Windows.Forms.Keys)">
<summary>
Determines whether the specified key is a regular input key or a special key that requires preprocessing.
</summary>
<returns>
true if the specified key is a regular input key; otherwise, false.
</returns>
<param name="keyData">One of the <see cref="T:System.Windows.Forms.Keys"/> values. </param>
</member>
<member name="T:PdfiumViewer.IPdfDocument">
<summary>
Represents a PDF document.
</summary>
</member>
<member name="P:PdfiumViewer.IPdfDocument.PageCount">
<summary>
Number of pages in the PDF document.
</summary>
</member>
<member name="P:PdfiumViewer.IPdfDocument.Bookmarks">
<summary>
Bookmarks stored in this PdfFile
</summary>
</member>
<member name="P:PdfiumViewer.IPdfDocument.PageSizes">
<summary>
Size of each page in the PDF document.
</summary>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Render(System.Int32,System.Drawing.Graphics,System.Single,System.Single,System.Drawing.Rectangle,System.Boolean)">
<summary>
Renders a page of the PDF document to the provided graphics instance.
</summary>
<param name="page">Number of the page to render.</param>
<param name="graphics">Graphics instance to render the page on.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="bounds">Bounds to render the page in.</param>
<param name="forPrinting">Render the page for printing.</param>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Render(System.Int32,System.Drawing.Graphics,System.Single,System.Single,System.Drawing.Rectangle,PdfiumViewer.PdfRenderFlags)">
<summary>
Renders a page of the PDF document to the provided graphics instance.
</summary>
<param name="page">Number of the page to render.</param>
<param name="graphics">Graphics instance to render the page on.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="bounds">Bounds to render the page in.</param>
<param name="flags">Flags used to influence the rendering.</param>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Render(System.Int32,System.Single,System.Single,System.Boolean)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="forPrinting">Render the page for printing.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Render(System.Int32,System.Single,System.Single,PdfiumViewer.PdfRenderFlags)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="flags">Flags used to influence the rendering.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Render(System.Int32,System.Int32,System.Int32,System.Single,System.Single,System.Boolean)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="width">Width of the rendered image.</param>
<param name="height">Height of the rendered image.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="forPrinting">Render the page for printing.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Render(System.Int32,System.Int32,System.Int32,System.Single,System.Single,PdfiumViewer.PdfRenderFlags)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="width">Width of the rendered image.</param>
<param name="height">Height of the rendered image.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="flags">Flags used to influence the rendering.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Render(System.Int32,System.Int32,System.Int32,System.Single,System.Single,PdfiumViewer.PdfRotation,PdfiumViewer.PdfRenderFlags)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="width">Width of the rendered image.</param>
<param name="height">Height of the rendered image.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="rotate">Rotation.</param>
<param name="flags">Flags used to influence the rendering.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Save(System.String)">
<summary>
Save the PDF document to the specified location.
</summary>
<param name="path">Path to save the PDF document to.</param>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Save(System.IO.Stream)">
<summary>
Save the PDF document to the specified location.
</summary>
<param name="stream">Stream to save the PDF document to.</param>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Search(System.String,System.Boolean,System.Boolean)">
<summary>
Finds all occurences of text.
</summary>
<param name="text">The text to search for.</param>
<param name="matchCase">Whether to match case.</param>
<param name="wholeWord">Whether to match whole words only.</param>
<returns>All matches.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Search(System.String,System.Boolean,System.Boolean,System.Int32)">
<summary>
Finds all occurences of text.
</summary>
<param name="text">The text to search for.</param>
<param name="matchCase">Whether to match case.</param>
<param name="wholeWord">Whether to match whole words only.</param>
<param name="page">The page to search on.</param>
<returns>All matches.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.Search(System.String,System.Boolean,System.Boolean,System.Int32,System.Int32)">
<summary>
Finds all occurences of text.
</summary>
<param name="text">The text to search for.</param>
<param name="matchCase">Whether to match case.</param>
<param name="wholeWord">Whether to match whole words only.</param>
<param name="startPage">The page to start searching.</param>
<param name="endPage">The page to end searching.</param>
<returns>All matches.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.CreatePrintDocument">
<summary>
Creates a <see cref="T:System.Drawing.Printing.PrintDocument"/> for the PDF document.
</summary>
<returns></returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.CreatePrintDocument(PdfiumViewer.PdfPrintMode)">
<summary>
Creates a <see cref="T:System.Drawing.Printing.PrintDocument"/> for the PDF document.
</summary>
<param name="printMode">Specifies the mode for printing. The default
value for this parameter is CutMargin.</param>
<returns></returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.CreatePrintDocument(PdfiumViewer.PdfPrintSettings)">
<summary>
Creates a <see cref="T:System.Drawing.Printing.PrintDocument"/> for the PDF document.
</summary>
<param name="settings">The settings used to configure the print document.</param>
<returns></returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.GetPageLinks(System.Int32,System.Drawing.Size)">
<summary>
Returns all links on the PDF page.
</summary>
<param name="page">The page to get the links for.</param>
<param name="size">The size of the page.</param>
<returns>A collection with the links on the page.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.DeletePage(System.Int32)">
<summary>
Delete the page from the PDF document.
</summary>
<param name="page">The page to delete.</param>
</member>
<member name="M:PdfiumViewer.IPdfDocument.RotatePage(System.Int32,PdfiumViewer.PdfRotation)">
<summary>
Rotate the page.
</summary>
<param name="page">The page to rotate.</param>
<param name="rotation">How to rotate the page.</param>
</member>
<member name="M:PdfiumViewer.IPdfDocument.GetInformation">
<summary>
Get metadata information from the PDF document.
</summary>
<returns>The PDF metadata.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.GetPdfText(System.Int32)">
<summary>
Get all text on the page.
</summary>
<param name="page">The page to get the text for.</param>
<returns>The text on the page.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.GetPdfText(PdfiumViewer.PdfTextSpan)">
<summary>
Get all text matching the text span.
</summary>
<param name="textSpan">The span to get the text for.</param>
<returns>The text matching the span.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.GetTextBounds(PdfiumViewer.PdfTextSpan)">
<summary>
Get all bounding rectangles for the text span.
</summary>
<description>
The algorithm used to get the bounding rectangles tries to join
adjacent character bounds into larger rectangles.
</description>
<param name="textSpan">The span to get the bounding rectangles for.</param>
<returns>The bounding rectangles.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.PointToPdf(System.Int32,System.Drawing.Point)">
<summary>
Convert a point from device coordinates to page coordinates.
</summary>
<param name="page">The page number where the point is from.</param>
<param name="point">The point to convert.</param>
<returns>The converted point.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.PointFromPdf(System.Int32,System.Drawing.PointF)">
<summary>
Convert a point from page coordinates to device coordinates.
</summary>
<param name="page">The page number where the point is from.</param>
<param name="point">The point to convert.</param>
<returns>The converted point.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.RectangleToPdf(System.Int32,System.Drawing.Rectangle)">
<summary>
Convert a rectangle from device coordinates to page coordinates.
</summary>
<param name="page">The page where the rectangle is from.</param>
<param name="rect">The rectangle to convert.</param>
<returns>The converted rectangle.</returns>
</member>
<member name="M:PdfiumViewer.IPdfDocument.RectangleFromPdf(System.Int32,System.Drawing.RectangleF)">
<summary>
Convert a rectangle from page coordinates to device coordinates.
</summary>
<param name="page">The page where the rectangle is from.</param>
<param name="rect">The rectangle to convert.</param>
<returns>The converted rectangle.</returns>
</member>
<member name="T:PdfiumViewer.IPdfMarker">
<summary>
Represents a marker on a PDF page.
</summary>
</member>
<member name="P:PdfiumViewer.IPdfMarker.Page">
<summary>
The page where the marker is drawn on.
</summary>
</member>
<member name="M:PdfiumViewer.IPdfMarker.Draw(PdfiumViewer.PdfRenderer,System.Drawing.Graphics)">
<summary>
Draw the marker.
</summary>
<param name="renderer">The PdfRenderer to draw the marker with.</param>
<param name="graphics">The Graphics to draw the marker with.</param>
</member>
<member name="P:PdfiumViewer.LinkClickEventArgs.Link">
<summary>
Gets the link that was clicked.
</summary>
</member>
<member name="M:PdfiumViewer.NativeMethods.FPDF_LoadCustomDocument(System.IO.Stream,System.String,System.Int32)">
<summary>
Opens a document using a .NET Stream. Allows opening huge
PDFs without loading them into memory first.
</summary>
<param name="input">The input Stream. Don't dispose prior to closing the pdf.</param>
<param name="password">Password, if the PDF is protected. Can be null.</param>
<param name="id">Retrieves an IntPtr to the COM object for the Stream. The caller must release this with Marshal.Release prior to Disposing the Stream.</param>
<returns>An IntPtr to the FPDF_DOCUMENT object.</returns>
</member>
<member name="P:PdfiumViewer.PanningZoomingScrollControl.Zoom">
<summary>
Gets or sets the current zoom level.
</summary>
</member>
<member name="M:PdfiumViewer.PanningZoomingScrollControl.ZoomIn">
<summary>
Zooms the PDF document in one step.
</summary>
</member>
<member name="M:PdfiumViewer.PanningZoomingScrollControl.ZoomOut">
<summary>
Zooms the PDF document out one step.
</summary>
</member>
<member name="M:PdfiumViewer.PanningZoomingScrollControl.OnMouseWheel(System.Windows.Forms.MouseEventArgs)">
<summary>
Raises the <see cref="E:System.Windows.Forms.Control.MouseWheel"/> event.
</summary>
<param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data. </param>
</member>
<member name="M:PdfiumViewer.PanningZoomingScrollControl.IsInputKey(System.Windows.Forms.Keys)">
<summary>
Determines whether the specified key is a regular input key or a special key that requires preprocessing.
</summary>
<returns>
true if the specified key is a regular input key; otherwise, false.
</returns>
<param name="keyData">One of the <see cref="T:System.Windows.Forms.Keys"/> values. </param>
</member>
<member name="F:PdfiumViewer.PasswordForm.components">
<summary>
Required designer variable.
</summary>
</member>
<member name="M:PdfiumViewer.PasswordForm.Dispose(System.Boolean)">
<summary>
Clean up any resources being used.
</summary>
<param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
</member>
<member name="M:PdfiumViewer.PasswordForm.InitializeComponent">
<summary>
Required method for Designer support - do not modify
the contents of this method with the code editor.
</summary>
</member>
<member name="T:PdfiumViewer.PdfPrintMultiplePages">
<summary>
Configuration for printing multiple PDF pages on a single page.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPrintMultiplePages.Horizontal">
<summary>
Gets the number of pages to print horizontally.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPrintMultiplePages.Vertical">
<summary>
Gets the number of pages to print vertically.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPrintMultiplePages.Orientation">
<summary>
Gets the orientation in which PDF pages are layed out on the
physical page.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPrintMultiplePages.Margin">
<summary>
Gets the margin between PDF pages in device units.
</summary>
</member>
<member name="M:PdfiumViewer.PdfPrintMultiplePages.#ctor(System.Int32,System.Int32,System.Windows.Forms.Orientation,System.Single)">
<summary>
Creates a new instance of the PdfPrintMultiplePages class.
</summary>
<param name="horizontal">The number of pages to print horizontally.</param>
<param name="vertical">The number of pages to print vertically.</param>
<param name="orientation">The orientation in which PDF pages are layed out on
the physical page.</param>
<param name="margin">The margin between PDF pages in device units.</param>
</member>
<member name="T:PdfiumViewer.PdfPrintSettings">
<summary>
Configures the print document.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPrintSettings.Mode">
<summary>
Gets the mode used to print margins.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPrintSettings.MultiplePages">
<summary>
Gets configuration for printing multiple PDF pages on a single page.
</summary>
</member>
<member name="M:PdfiumViewer.PdfPrintSettings.#ctor(PdfiumViewer.PdfPrintMode,PdfiumViewer.PdfPrintMultiplePages)">
<summary>
Creates a new instance of the PdfPrintSettings class.
</summary>
<param name="mode">The mode used to print margins.</param>
<param name="multiplePages">Configuration for printing multiple PDF
pages on a single page.</param>
</member>
<member name="T:PdfiumViewer.PdfDocument">
<summary>
Provides functionality to render a PDF document.
</summary>
</member>
<member name="M:PdfiumViewer.PdfDocument.Load(System.String)">
<summary>
Initializes a new instance of the PdfDocument class with the provided path.
</summary>
<param name="path">Path to the PDF document.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Load(System.String,System.String)">
<summary>
Initializes a new instance of the PdfDocument class with the provided path.
</summary>
<param name="path">Path to the PDF document.</param>
<param name="password">Password for the PDF document.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Load(System.Windows.Forms.IWin32Window,System.String)">
<summary>
Initializes a new instance of the PdfDocument class with the provided path.
</summary>
<param name="owner">Window to show any UI for.</param>
<param name="path">Path to the PDF document.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Load(System.Windows.Forms.IWin32Window,System.IO.Stream)">
<summary>
Initializes a new instance of the PdfDocument class with the provided path.
</summary>
<param name="owner">Window to show any UI for.</param>
<param name="stream">Stream for the PDF document.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Load(System.IO.Stream)">
<summary>
Initializes a new instance of the PdfDocument class with the provided stream.
</summary>
<param name="stream">Stream for the PDF document.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Load(System.IO.Stream,System.String)">
<summary>
Initializes a new instance of the PdfDocument class with the provided stream.
</summary>
<param name="stream">Stream for the PDF document.</param>
<param name="password">Password for the PDF document.</param>
</member>
<member name="P:PdfiumViewer.PdfDocument.PageCount">
<summary>
Number of pages in the PDF document.
</summary>
</member>
<member name="P:PdfiumViewer.PdfDocument.Bookmarks">
<summary>
Bookmarks stored in this PdfFile
</summary>
</member>
<member name="P:PdfiumViewer.PdfDocument.PageSizes">
<summary>
Size of each page in the PDF document.
</summary>
</member>
<member name="M:PdfiumViewer.PdfDocument.Render(System.Int32,System.Drawing.Graphics,System.Single,System.Single,System.Drawing.Rectangle,System.Boolean)">
<summary>
Renders a page of the PDF document to the provided graphics instance.
</summary>
<param name="page">Number of the page to render.</param>
<param name="graphics">Graphics instance to render the page on.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="bounds">Bounds to render the page in.</param>
<param name="forPrinting">Render the page for printing.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Render(System.Int32,System.Drawing.Graphics,System.Single,System.Single,System.Drawing.Rectangle,PdfiumViewer.PdfRenderFlags)">
<summary>
Renders a page of the PDF document to the provided graphics instance.
</summary>
<param name="page">Number of the page to render.</param>
<param name="graphics">Graphics instance to render the page on.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="bounds">Bounds to render the page in.</param>
<param name="flags">Flags used to influence the rendering.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Render(System.Int32,System.Single,System.Single,System.Boolean)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="forPrinting">Render the page for printing.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.Render(System.Int32,System.Single,System.Single,PdfiumViewer.PdfRenderFlags)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="flags">Flags used to influence the rendering.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.Render(System.Int32,System.Int32,System.Int32,System.Single,System.Single,System.Boolean)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="width">Width of the rendered image.</param>
<param name="height">Height of the rendered image.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="forPrinting">Render the page for printing.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.Render(System.Int32,System.Int32,System.Int32,System.Single,System.Single,PdfiumViewer.PdfRenderFlags)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="width">Width of the rendered image.</param>
<param name="height">Height of the rendered image.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="flags">Flags used to influence the rendering.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.Render(System.Int32,System.Int32,System.Int32,System.Single,System.Single,PdfiumViewer.PdfRotation,PdfiumViewer.PdfRenderFlags)">
<summary>
Renders a page of the PDF document to an image.
</summary>
<param name="page">Number of the page to render.</param>
<param name="width">Width of the rendered image.</param>
<param name="height">Height of the rendered image.</param>
<param name="dpiX">Horizontal DPI.</param>
<param name="dpiY">Vertical DPI.</param>
<param name="rotate">Rotation.</param>
<param name="flags">Flags used to influence the rendering.</param>
<returns>The rendered image.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.Save(System.String)">
<summary>
Save the PDF document to the specified location.
</summary>
<param name="path">Path to save the PDF document to.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Save(System.IO.Stream)">
<summary>
Save the PDF document to the specified location.
</summary>
<param name="stream">Stream to save the PDF document to.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.Search(System.String,System.Boolean,System.Boolean)">
<summary>
Finds all occurences of text.
</summary>
<param name="text">The text to search for.</param>
<param name="matchCase">Whether to match case.</param>
<param name="wholeWord">Whether to match whole words only.</param>
<returns>All matches.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.Search(System.String,System.Boolean,System.Boolean,System.Int32)">
<summary>
Finds all occurences of text.
</summary>
<param name="text">The text to search for.</param>
<param name="matchCase">Whether to match case.</param>
<param name="wholeWord">Whether to match whole words only.</param>
<param name="page">The page to search on.</param>
<returns>All matches.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.Search(System.String,System.Boolean,System.Boolean,System.Int32,System.Int32)">
<summary>
Finds all occurences of text.
</summary>
<param name="text">The text to search for.</param>
<param name="matchCase">Whether to match case.</param>
<param name="wholeWord">Whether to match whole words only.</param>
<param name="startPage">The page to start searching.</param>
<param name="endPage">The page to end searching.</param>
<returns>All matches.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.GetPdfText(System.Int32)">
<summary>
Get all text on the page.
</summary>
<param name="page">The page to get the text for.</param>
<returns>The text on the page.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.GetPdfText(PdfiumViewer.PdfTextSpan)">
<summary>
Get all text matching the text span.
</summary>
<param name="textSpan">The span to get the text for.</param>
<returns>The text matching the span.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.GetTextBounds(PdfiumViewer.PdfTextSpan)">
<summary>
Get all bounding rectangles for the text span.
</summary>
<description>
The algorithm used to get the bounding rectangles tries to join
adjacent character bounds into larger rectangles.
</description>
<param name="textSpan">The span to get the bounding rectangles for.</param>
<returns>The bounding rectangles.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.PointToPdf(System.Int32,System.Drawing.Point)">
<summary>
Convert a point from device coordinates to page coordinates.
</summary>
<param name="page">The page number where the point is from.</param>
<param name="point">The point to convert.</param>
<returns>The converted point.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.PointFromPdf(System.Int32,System.Drawing.PointF)">
<summary>
Convert a point from page coordinates to device coordinates.
</summary>
<param name="page">The page number where the point is from.</param>
<param name="point">The point to convert.</param>
<returns>The converted point.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.RectangleToPdf(System.Int32,System.Drawing.Rectangle)">
<summary>
Convert a rectangle from device coordinates to page coordinates.
</summary>
<param name="page">The page where the rectangle is from.</param>
<param name="rect">The rectangle to convert.</param>
<returns>The converted rectangle.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.RectangleFromPdf(System.Int32,System.Drawing.RectangleF)">
<summary>
Convert a rectangle from page coordinates to device coordinates.
</summary>
<param name="page">The page where the rectangle is from.</param>
<param name="rect">The rectangle to convert.</param>
<returns>The converted rectangle.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.CreatePrintDocument">
<summary>
Creates a <see cref="T:System.Drawing.Printing.PrintDocument"/> for the PDF document.
</summary>
<returns></returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.CreatePrintDocument(PdfiumViewer.PdfPrintMode)">
<summary>
Creates a <see cref="T:System.Drawing.Printing.PrintDocument"/> for the PDF document.
</summary>
<param name="printMode">Specifies the mode for printing. The default
value for this parameter is CutMargin.</param>
<returns></returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.CreatePrintDocument(PdfiumViewer.PdfPrintSettings)">
<summary>
Creates a <see cref="T:System.Drawing.Printing.PrintDocument"/> for the PDF document.
</summary>
<param name="settings">The settings used to configure the print document.</param>
<returns></returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.GetPageLinks(System.Int32,System.Drawing.Size)">
<summary>
Returns all links on the PDF page.
</summary>
<param name="page">The page to get the links for.</param>
<param name="size">The size of the page.</param>
<returns>A collection with the links on the page.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.DeletePage(System.Int32)">
<summary>
Delete the page from the PDF document.
</summary>
<param name="page">The page to delete.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.RotatePage(System.Int32,PdfiumViewer.PdfRotation)">
<summary>
Rotate the page.
</summary>
<param name="page">The page to rotate.</param>
<param name="rotation">How to rotate the page.</param>
</member>
<member name="M:PdfiumViewer.PdfDocument.GetInformation">
<summary>
Get metadata information from the PDF document.
</summary>
<returns>The PDF metadata.</returns>
</member>
<member name="M:PdfiumViewer.PdfDocument.Dispose">
<summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
<filterpriority>2</filterpriority>
</member>
<member name="M:PdfiumViewer.PdfDocument.Dispose(System.Boolean)">
<summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
<param name="disposing">Whether this method is called from Dispose.</param>
</member>
<member name="T:PdfiumViewer.PdfInformation">
<summary>
Contains text from metadata of the document.
</summary>
</member>
<member name="T:PdfiumViewer.PdfSearchManager">
<summary>
Helper class for searching through PDF documents.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.Renderer">
<summary>
The renderer associated with the search manager.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.MatchCase">
<summary>
Gets or sets whether to match case.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.MatchWholeWord">
<summary>
Gets or sets whether to match whole words.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.MatchColor">
<summary>
Gets or sets the color of matched search terms.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.MatchBorderColor">
<summary>
Gets or sets the border color of matched search terms.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.MatchBorderWidth">
<summary>
Gets or sets the border width of matched search terms.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.CurrentMatchColor">
<summary>
Gets or sets the color of the current match.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.CurrentMatchBorderColor">
<summary>
Gets or sets the border color of the current match.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.CurrentMatchBorderWidth">
<summary>
Gets or sets the border width of the current match.
</summary>
</member>
<member name="P:PdfiumViewer.PdfSearchManager.HighlightAllMatches">
<summary>
Gets or sets whether all matches should be highlighted.
</summary>
</member>
<member name="M:PdfiumViewer.PdfSearchManager.#ctor(PdfiumViewer.PdfRenderer)">
<summary>
Creates a new instance of the search manager.
</summary>
<param name="renderer">The renderer to create the search manager for.</param>
</member>
<member name="M:PdfiumViewer.PdfSearchManager.Search(System.String)">
<summary>
Searches for the specified text.
</summary>
<param name="text">The text to search.</param>
<returns>Whether any matches were found.</returns>
</member>
<member name="M:PdfiumViewer.PdfSearchManager.FindNext(System.Boolean)">
<summary>
Find the next matched term.
</summary>
<param name="forward">Whether or not to search forward.</param>
<returns>False when the first match was found again; otherwise true.</returns>
</member>
<member name="M:PdfiumViewer.PdfSearchManager.Reset">
<summary>
Resets the search manager.
</summary>
</member>
<member name="T:PdfiumViewer.PdfPageLink">
<summary>
Describes a link on a page.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPageLink.Bounds">
<summary>
The location of the link.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPageLink.TargetPage">
<summary>
The target of the link.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPageLink.Uri">
<summary>
The target URI of the link.
</summary>
</member>
<member name="M:PdfiumViewer.PdfPageLink.#ctor(System.Drawing.RectangleF,System.Nullable{System.Int32},System.String)">
<summary>
Creates a new instance of the PdfPageLink class.
</summary>
<param name="bounds">The location of the link</param>
<param name="targetPage">The target page of the link</param>
<param name="uri">The target URI of the link</param>
</member>
<member name="T:PdfiumViewer.PdfPageLinks">
<summary>
Describes all links on a page.
</summary>
</member>
<member name="P:PdfiumViewer.PdfPageLinks.Links">
<summary>
All links of the page.
</summary>
</member>
<member name="M:PdfiumViewer.PdfPageLinks.#ctor(System.Collections.Generic.IList{PdfiumViewer.PdfPageLink})">
<summary>
Creates a new instance of the PdfPageLinks class.
</summary>
<param name="links">The links on the PDF page.</param>
</member>
<member name="T:PdfiumViewer.PdfPrintMode">
<summary>
Specifies the mode in which the document should be printed.
</summary>
<remarks>
Printers have a hard margin. This is a (small) margin on which it is not
possible to print. PdfPrintMode specifies whether the page should be
scaled to fit into this margin, or that the margin should be cut off of
the page.
</remarks>
</member>
<member name="F:PdfiumViewer.PdfPrintMode.ShrinkToMargin">
<summary>
Shrink the print area to fall within the hard printer margin.
</summary>
</member>
<member name="F:PdfiumViewer.PdfPrintMode.CutMargin">
<summary>
Cut the hard printer margin from the output.
</summary>
</member>
<member name="T:PdfiumViewer.PdfRenderFlags">
<summary>
Flags that influence the page rendering process.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.None">
<summary>
No flags.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.ForPrinting">
<summary>
Render for printing.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.Annotations">
<summary>
Set if annotations are to be rendered.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.LcdText">
<summary>
Set if using text rendering optimized for LCD display.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.NoNativeText">
<summary>
Don't use the native text output available on some platforms.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.Grayscale">
<summary>
Grayscale output.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.LimitImageCacheSize">
<summary>
Limit image cache size.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.ForceHalftone">
<summary>
Always use halftone for image stretching.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.Transparent">
<summary>
Render with a transparent background.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRenderFlags.CorrectFromDpi">
<summary>
Correct height/width for DPI.
</summary>
</member>
<member name="T:PdfiumViewer.PdfRenderer">
<summary>
Control to render PDF documents.
</summary>
</member>
<member name="P:PdfiumViewer.PdfRenderer.Document">
<summary>
The associated PDF document.
</summary>
</member>
<member name="P:PdfiumViewer.PdfRenderer.TabStop">
<summary>
Gets or sets a value indicating whether the user can give the focus to this control using the TAB key.
</summary>
<returns>
true if the user can give the focus to the control using the TAB key; otherwise, false. The default is true.Note:This property will always return true for an instance of the <see cref="T:System.Windows.Forms.Form"/> class.
</returns>
<filterpriority>1</filterpriority><PermissionSet><IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/><IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence"/><IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/></PermissionSet>
</member>
<member name="P:PdfiumViewer.PdfRenderer.Page">
<summary>
Gets or sets the currently focused page.
</summary>
</member>
<member name="M:PdfiumViewer.PdfRenderer.GetOuterBounds(System.Int32)">
<summary>
Get the outer bounds of the page.
</summary>
<param name="page">The page to get the bounds for.</param>
<returns>The bounds of the page.</returns>
</member>
<member name="P:PdfiumViewer.PdfRenderer.ZoomMode">
<summary>
Gets or sets the way the document should be zoomed initially.
</summary>
</member>
<member name="P:PdfiumViewer.PdfRenderer.Rotation">
<summary>
Gets or sets the current rotation of the PDF document.
</summary>
</member>
<member name="P:PdfiumViewer.PdfRenderer.Markers">
<summary>
Gets a collection with all markers.
</summary>
</member>
<member name="M:PdfiumViewer.PdfRenderer.#ctor">
<summary>
Initializes a new instance of the PdfRenderer class.
</summary>
</member>
<member name="M:PdfiumViewer.PdfRenderer.PointToPdf(System.Drawing.Point)">
<summary>
Converts client coordinates to PDF coordinates.
</summary>
<param name="location">Client coordinates to get the PDF location for.</param>
<returns>The location in a PDF page or a PdfPoint with IsValid false when the coordinates do not match a PDF page.</returns>
</member>
<member name="M:PdfiumViewer.PdfRenderer.PointFromPdf(PdfiumViewer.PdfPoint)">
<summary>
Converts a PDF point to a client point.
</summary>
<param name="point">The PDF point to convert.</param>
<returns>The location of the point in client coordinates.</returns>
</member>
<member name="M:PdfiumViewer.PdfRenderer.BoundsToPdf(System.Drawing.Rectangle)">
<summary>
Converts client coordinates to PDF bounds.
</summary>
<param name="bounds">The client coordinates to convert.</param>
<returns>The PDF bounds.</returns>
</member>
<member name="M:PdfiumViewer.PdfRenderer.BoundsFromPdf(PdfiumViewer.PdfRectangle)">
<summary>
Converts PDF bounds to client bounds.
</summary>
<param name="bounds">The PDF bounds to convert.</param>
<returns>The bounds of the PDF bounds in client coordinates.</returns>
</member>
<member name="M:PdfiumViewer.PdfRenderer.OnLayout(System.Windows.Forms.LayoutEventArgs)">
<summary>
Raises the <see cref="E:System.Windows.Forms.Control.Layout"/> event.
</summary>
<param name="levent">A <see cref="T:System.Windows.Forms.LayoutEventArgs"/> that contains the event data. </param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.OnZoomChanged(System.EventArgs)">
<summary>
Called when the zoom level changes.
</summary>
<param name="e">The event args.</param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.Load(PdfiumViewer.IPdfDocument)">
<summary>
Load a <see cref="T:PdfiumViewer.IPdfDocument"/> into the control.
</summary>
<param name="document">Document to load.</param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.OnPaint(System.Windows.Forms.PaintEventArgs)">
<summary>
Raises the <see cref="E:System.Windows.Forms.Control.Paint"/> event.
</summary>
<param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs"/> that contains the event data. </param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.GetDocumentBounds">
<summary>
Gets the document bounds.
</summary>
<returns>The document bounds.</returns>
</member>
<member name="M:PdfiumViewer.PdfRenderer.OnSetCursor(PdfiumViewer.SetCursorEventArgs)">
<summary>
Called whent he cursor changes.
</summary>
<param name="e">The event args.</param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.OnMouseDown(System.Windows.Forms.MouseEventArgs)">
<summary>Raises the <see cref="E:System.Windows.Forms.Control.MouseDown" /> event.</summary>
<param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs" /> that contains the event data. </param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.OnMouseUp(System.Windows.Forms.MouseEventArgs)">
<summary>Raises the <see cref="E:System.Windows.Forms.Control.MouseUp" /> event.</summary>
<param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs" /> that contains the event data. </param>
</member>
<member name="E:PdfiumViewer.PdfRenderer.LinkClick">
<summary>
Occurs when a link in the pdf document is clicked.
</summary>
</member>
<member name="M:PdfiumViewer.PdfRenderer.OnLinkClick(PdfiumViewer.LinkClickEventArgs)">
<summary>
Called when a link is clicked.
</summary>
<param name="e">The event args.</param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.RotateLeft">
<summary>
Rotate the PDF document left.
</summary>
</member>
<member name="M:PdfiumViewer.PdfRenderer.RotateRight">
<summary>
Rotate the PDF document right.
</summary>
</member>
<member name="M:PdfiumViewer.PdfRenderer.SetZoom(System.Double,System.Nullable{System.Drawing.Point})">
<summary>
Called when the zoom level changes.
</summary>
<param name="zoom">The new zoom level.</param>
<param name="focus">The location to focus on.</param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.ScrollIntoView(PdfiumViewer.PdfRectangle)">
<summary>
Scroll the PDF bounds into view.
</summary>
<param name="bounds">The PDF bounds to scroll into view.</param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.ScrollIntoView(System.Drawing.Rectangle)">
<summary>
Scroll the client rectangle into view.
</summary>
<param name="rectangle">The client rectangle to scroll into view.</param>
</member>
<member name="M:PdfiumViewer.PdfRenderer.Dispose(System.Boolean)">
<summary>
Releases the unmanaged resources used by the <see cref="T:System.Windows.Forms.Control"/> and its child controls and optionally releases the managed resources.
</summary>
<param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources. </param>
</member>
<member name="T:PdfiumViewer.PdfRotation">
<summary>
Specifies the rotation of pages shown in the PDF renderer.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRotation.Rotate0">
<summary>
Rotates the output 0 degrees.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRotation.Rotate90">
<summary>
Rotates the output 90 degrees.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRotation.Rotate180">
<summary>
Rotates the output 180 degrees.
</summary>
</member>
<member name="F:PdfiumViewer.PdfRotation.Rotate270">
<summary>
Rotates the output 270 degrees.
</summary>
</member>
<member name="T:PdfiumViewer.PdfViewer">
<summary>
Control to host PDF documents with support for printing.
</summary>
</member>
<member name="P:PdfiumViewer.PdfViewer.Document">
<summary>
Gets or sets the PDF document.
</summary>
</member>
<member name="P:PdfiumViewer.PdfViewer.Renderer">
<summary>
Get the <see cref="T:PdfiumViewer.PdfRenderer"/> that renders the PDF document.
</summary>
</member>
<member name="P:PdfiumViewer.PdfViewer.DefaultDocumentName">
<summary>
Gets or sets the default document name used when saving the document.
</summary>
</member>
<member name="P:PdfiumViewer.PdfViewer.DefaultPrintMode">
<summary>
Gets or sets the default print mode.
</summary>
</member>
<member name="P:PdfiumViewer.PdfViewer.ZoomMode">
<summary>
Gets or sets the way the document should be zoomed initially.
</summary>
</member>
<member name="P:PdfiumViewer.PdfViewer.ShowToolbar">
<summary>
Gets or sets whether the toolbar should be shown.
</summary>
</member>
<member name="P:PdfiumViewer.PdfViewer.ShowBookmarks">
<summary>
Gets or sets whether the bookmarks panel should be shown.
</summary>
</member>
<member name="P:PdfiumViewer.PdfViewer.DefaultPrinter">
<summary>
Gets or sets the pre-selected printer to be used when the print
dialog shows up.
</summary>
</member>
<member name="E:PdfiumViewer.PdfViewer.LinkClick">
<summary>
Occurs when a link in the pdf document is clicked.
</summary>
</member>
<member name="M:PdfiumViewer.PdfViewer.OnLinkClick(PdfiumViewer.LinkClickEventArgs)">
<summary>
Called when a link is clicked.
</summary>
<param name="e"></param>
</member>
<member name="M:PdfiumViewer.PdfViewer.#ctor">
<summary>
Initializes a new instance of the PdfViewer class.
</summary>
</member>
<member name="F:PdfiumViewer.PdfViewer.components">
<summary>
Required designer variable.
</summary>
</member>
<member name="M:PdfiumViewer.PdfViewer.Dispose(System.Boolean)">
<summary>
Clean up any resources being used.
</summary>
<param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
</member>
<member name="M:PdfiumViewer.PdfViewer.InitializeComponent">
<summary>
Required method for Designer support - do not modify
the contents of this method with the code editor.
</summary>
</member>
<member name="T:PdfiumViewer.Properties.Resources">
<summary>
A strongly-typed resource class, for looking up localized strings, etc.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ResourceManager">
<summary>
Returns the cached ResourceManager instance used by this class.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.Culture">
<summary>
Overrides the current thread's CurrentUICulture property for all
resource lookups using this strongly typed resource class.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.disk_blue">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.PageNumber">
<summary>
Looks up a localized string similar to Page {0}.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.printer">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.SaveAsFailedText">
<summary>
Looks up a localized string similar to Could not save the PDF file to the specified location..
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.SaveAsFailedTitle">
<summary>
Looks up a localized string similar to Could not save file.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.SaveAsFilter">
<summary>
Looks up a localized string similar to PDF Files (*.pdf)|*.pdf|All Files (*.*)|*.*.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.SaveAsTitle">
<summary>
Looks up a localized string similar to Save As.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ShadeBorder_E">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ShadeBorder_N">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ShadeBorder_NE">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ShadeBorder_NW">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ShadeBorder_S">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ShadeBorder_SE">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ShadeBorder_SW">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.ShadeBorder_W">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.zoom_in">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
<member name="P:PdfiumViewer.Properties.Resources.zoom_out">
<summary>
Looks up a localized resource of type System.Drawing.Bitmap.
</summary>
</member>
</members>
</doc>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Content Include="$(MSBuildThisFileDirectory)x64\pdfium.dll">
<Link>x64\pdfium.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment