20using System.Runtime.InteropServices;
22using System.Threading;
23using System.Threading.Tasks;
35 internal double ImageXRes =
double.NaN;
40 internal double ImageYRes =
double.NaN;
45 private static readonly
string[] FileTypeMagics =
new[]
66 private static IDisposable NullDataHolder =
null;
76 internal readonly IntPtr NativeDocument;
81 private readonly IntPtr NativeStream = IntPtr.Zero;
86 private int PageCount;
91 private readonly IDisposable DataHolder =
null;
96 private GCHandle? DataHandle =
null;
101 private MuPDFDisplayList[] DisplayLists;
149 bool isImage = fileType == InputFileTypes.BMP || fileType == InputFileTypes.GIF || fileType == InputFileTypes.JPEG || fileType == InputFileTypes.PAM || fileType == InputFileTypes.PNG || fileType == InputFileTypes.PNM || fileType ==
InputFileTypes.TIFF;
151 this.OwnerContext = context;
156 ExitCodes result = (
ExitCodes)NativeMethods.CreateDocumentFromStream(context.NativeContext, dataAddress, (ulong)dataLength, FileTypeMagics[(int)fileType], isImage ? 1 : 0, ref NativeDocument, ref NativeStream, ref PageCount, ref xRes, ref yRes);
160 this.ImageXRes = xRes;
169 this.ImageYRes = yRes;
176 this.DataHolder = dataHolder;
192 if (NativeMethods.CheckIfPasswordNeeded(context.NativeContext,
this.NativeDocument) != 0)
201 int permissions = NativeMethods.GetPermissions(context.NativeContext,
this.NativeDocument);
203 int restrictions = 0;
205 if ((permissions & 1) == 0)
210 if ((permissions & 2) == 0)
215 if ((permissions & 4) == 0)
220 if ((permissions & 8) == 0)
225 if (restrictions == 0)
237 DisplayLists =
new MuPDFDisplayList[PageCount];
249 bool isImage = fileType == InputFileTypes.BMP || fileType == InputFileTypes.GIF || fileType == InputFileTypes.JPEG || fileType == InputFileTypes.PAM || fileType == InputFileTypes.PNG || fileType == InputFileTypes.PNM || fileType ==
InputFileTypes.TIFF;
251 this.OwnerContext = context;
253 DataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
254 IntPtr dataAddress = DataHandle.Value.AddrOfPinnedObject();
255 ulong dataLength = (ulong)data.Length;
260 ExitCodes result = (
ExitCodes)NativeMethods.CreateDocumentFromStream(context.NativeContext, dataAddress, dataLength, FileTypeMagics[(
int)fileType], isImage ? 1 : 0, ref NativeDocument, ref NativeStream, ref PageCount, ref xRes, ref yRes);
264 this.ImageXRes = xRes;
273 this.ImageYRes = yRes;
294 if (NativeMethods.CheckIfPasswordNeeded(context.NativeContext,
this.NativeDocument) != 0)
303 int permissions = NativeMethods.GetPermissions(context.NativeContext,
this.NativeDocument);
305 int restrictions = 0;
307 if ((permissions & 1) == 0)
312 if ((permissions & 2) == 0)
317 if ((permissions & 4) == 0)
322 if ((permissions & 8) == 0)
327 if (restrictions == 0)
339 DisplayLists =
new MuPDFDisplayList[PageCount];
351 bool isImage = fileType == InputFileTypes.BMP || fileType == InputFileTypes.GIF || fileType == InputFileTypes.JPEG || fileType == InputFileTypes.PAM || fileType == InputFileTypes.PNG || fileType == InputFileTypes.PNM || fileType ==
InputFileTypes.TIFF;
353 this.OwnerContext = context;
355 int origin = (int)data.Seek(0, SeekOrigin.Begin);
356 ulong dataLength = (ulong)data.Length;
357 byte[] dataBytes = data.GetBuffer();
359 DataHandle = GCHandle.Alloc(dataBytes, GCHandleType.Pinned);
360 IntPtr dataAddress = IntPtr.Add(DataHandle.Value.AddrOfPinnedObject(), origin);
367 ExitCodes result = (
ExitCodes)NativeMethods.CreateDocumentFromStream(context.NativeContext, dataAddress, dataLength, FileTypeMagics[(
int)fileType], isImage ? 1 : 0, ref NativeDocument, ref NativeStream, ref PageCount, ref xRes, ref yRes);
371 this.ImageXRes = xRes;
380 this.ImageYRes = yRes;
402 if (NativeMethods.CheckIfPasswordNeeded(context.NativeContext,
this.NativeDocument) != 0)
411 int permissions = NativeMethods.GetPermissions(context.NativeContext,
this.NativeDocument);
413 int restrictions = 0;
415 if ((permissions & 1) == 0)
420 if ((permissions & 2) == 0)
425 if ((permissions & 4) == 0)
430 if ((permissions & 8) == 0)
435 if (restrictions == 0)
447 DisplayLists =
new MuPDFDisplayList[PageCount];
459 string extension = Path.GetExtension(fileName).ToLowerInvariant();
493 this.OwnerContext = context;
500 using (UTF8EncodedString encodedFileName =
new UTF8EncodedString(fileName))
502 result = (
ExitCodes)NativeMethods.CreateDocumentFromFile(context.NativeContext, encodedFileName.Address, isImage ? 1 : 0, ref NativeDocument, ref PageCount, ref xRes, ref yRes);
507 this.ImageXRes = xRes;
516 this.ImageYRes = yRes;
535 if (NativeMethods.CheckIfPasswordNeeded(context.NativeContext,
this.NativeDocument) != 0)
544 int permissions = NativeMethods.GetPermissions(context.NativeContext,
this.NativeDocument);
546 int restrictions = 0;
548 if ((permissions & 1) == 0)
553 if ((permissions & 2) == 0)
558 if ((permissions & 4) == 0)
563 if ((permissions & 8) == 0)
568 if (restrictions == 0)
580 DisplayLists =
new MuPDFDisplayList[PageCount];
588 for (
int i = 0; i < PageCount; i++)
590 DisplayLists[i]?.Dispose();
591 DisplayLists[i] =
null;
601 public void Layout(
float width,
float height,
float em)
605 throw new ArgumentOutOfRangeException(nameof(width), width,
"The page width must be greater than 0!");
610 throw new ArgumentOutOfRangeException(nameof(height), height,
"The page height must be greater than 0!");
614 this.
Pages.Dispose();
616 NativeMethods.LayoutDocument(this.OwnerContext.NativeContext,
this.NativeDocument, width, height, em, out
int pageCount);
618 this.PageCount = pageCount;
620 this.DisplayLists =
new MuPDFDisplayList[PageCount];
633 throw new ArgumentOutOfRangeException(nameof(width), width,
"The page width must be greater than 0!");
637 this.
Pages.Dispose();
639 NativeMethods.LayoutDocument(this.OwnerContext.NativeContext,
this.NativeDocument, width, 0, em, out
int pageCount);
641 this.PageCount = pageCount;
643 this.DisplayLists =
new MuPDFDisplayList[PageCount];
664 byte[] buffer =
new byte[bufferSize];
666 GCHandle bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
667 IntPtr bufferPointer = bufferHandle.AddrOfPinnedObject();
671 Render(pageNumber, region, zoom, pixelFormat, bufferPointer, includeAnnotations);
689 public byte[]
Render(
int pageNumber,
double zoom,
PixelFormats pixelFormat,
bool includeAnnotations =
true)
697 return Render(pageNumber, region, zoom, pixelFormat, includeAnnotations);
716 if (DisplayLists[pageNumber] ==
null)
718 DisplayLists[pageNumber] =
new MuPDFDisplayList(this.OwnerContext, this.
Pages[pageNumber], includeAnnotations);
721 if (zoom < 0.000001 | zoom * region.
Width <= 0.001 || zoom * region.
Height <= 0.001)
723 throw new ArgumentOutOfRangeException(nameof(zoom), zoom,
"The zoom factor is too small!");
726 if (this.ImageXRes != 72 || this.ImageYRes != 72)
728 zoom *= Math.Sqrt(this.ImageXRes * this.ImageYRes) / 72;
729 region =
new Rectangle(region.
X0 * 72 /
this.ImageXRes, region.
Y0 * 72 /
this.ImageYRes, region.
X1 * 72 /
this.ImageXRes, region.
Y1 * 72 /
this.ImageYRes);
732 float fzoom = (float)zoom;
734 ExitCodes result = (
ExitCodes)NativeMethods.RenderSubDisplayList(OwnerContext.NativeContext, DisplayLists[pageNumber].NativeDisplayList, region.
X0, region.
Y0, region.
X1, region.
Y1, fzoom, (
int)pixelFormat, destination, IntPtr.Zero);
751 Utils.UnpremultiplyAlpha(destination, roundedSize);
754 if (this.
ClipToPageBounds && !
Pages[pageNumber].Bounds.Contains(DisplayLists[pageNumber].Bounds.Intersect(region)))
756 Utils.ClipImage(destination, roundedSize, region,
Pages[pageNumber].Bounds, pixelFormat);
768 public void Render(
int pageNumber,
double zoom,
PixelFormats pixelFormat, IntPtr destination,
bool includeAnnotations =
true)
776 Render(pageNumber, region, zoom, pixelFormat, destination, includeAnnotations);
788 public Span<byte>
Render(
int pageNumber,
Rectangle region,
double zoom,
PixelFormats pixelFormat, out IDisposable disposable,
bool includeAnnotations =
true)
797 IntPtr destination = Marshal.AllocHGlobal(dataSize);
800 this.
Render(pageNumber, region, zoom, pixelFormat, destination, includeAnnotations);
804 return new Span<byte>((
void*)destination, dataSize);
816 public Span<byte>
Render(
int pageNumber,
double zoom,
PixelFormats pixelFormat, out IDisposable disposable,
bool includeAnnotations =
true)
824 return Render(pageNumber, region, zoom, pixelFormat, out disposable, includeAnnotations);
842 if (DisplayLists[pageNumber] ==
null)
844 DisplayLists[pageNumber] =
new MuPDFDisplayList(this.OwnerContext, this.
Pages[pageNumber], includeAnnotations);
876 float x0 = region.X0 * (float)zoom;
877 float y0 = region.Y0 * (float)zoom;
878 float x1 = region.X1 * (float)zoom;
879 float y1 = region.Y1 * (float)zoom;
884 int width = bounds.
Width;
885 int height = bounds.
Height;
891 return width * height * 3;
894 return width * height * 4;
919 throw new ArgumentException(
"Cannot save an image with alpha channel in PNM format!", nameof(fileType));
924 throw new ArgumentException(
"The JPEG format only supports RGB pixel data without an alpha channel!", nameof(fileType));
929 throw new ArgumentException(
"The PNG format only supports RGB or RGBA pixel data!", nameof(fileType));
932 if (DisplayLists[pageNumber] ==
null)
934 DisplayLists[pageNumber] =
new MuPDFDisplayList(this.OwnerContext, this.
Pages[pageNumber], includeAnnotations);
937 if (zoom < 0.000001 | zoom * region.
Width <= 0.001 || zoom * region.
Height <= 0.001)
939 throw new ArgumentOutOfRangeException(nameof(zoom), zoom,
"The zoom factor is too small!");
942 if (this.ImageXRes != 72 || this.ImageYRes != 72)
944 zoom *= Math.Sqrt(this.ImageXRes * this.ImageYRes) / 72;
945 region =
new Rectangle(region.
X0 * 72 /
this.ImageXRes, region.
Y0 * 72 /
this.ImageYRes, region.
X1 * 72 /
this.ImageXRes, region.
Y1 * 72 /
this.ImageYRes);
948 float fzoom = (float)zoom;
952 using (UTF8EncodedString encodedFileName =
new UTF8EncodedString(fileName))
954 result = (
ExitCodes)NativeMethods.SaveImage(OwnerContext.NativeContext, DisplayLists[pageNumber].NativeDisplayList, region.
X0, region.
Y0, region.
X1, region.
Y1, fzoom, (
int)pixelFormat, encodedFileName.Address, (int)fileType, 90);
964 throw new MuPDFException(
"Cannot save to the output file", result);
979 public void SaveImageAsJPEG(
int pageNumber,
Rectangle region,
double zoom,
string fileName,
int quality,
bool includeAnnotations =
true)
986 if (quality < 0 || quality > 100)
988 throw new ArgumentOutOfRangeException(nameof(quality), quality,
"The JPEG quality must range between 0 and 100 (inclusive)!");
991 if (DisplayLists[pageNumber] ==
null)
993 DisplayLists[pageNumber] =
new MuPDFDisplayList(this.OwnerContext, this.
Pages[pageNumber], includeAnnotations);
996 if (zoom < 0.000001 | zoom * region.
Width <= 0.001 || zoom * region.
Height <= 0.001)
998 throw new ArgumentOutOfRangeException(nameof(zoom), zoom,
"The zoom factor is too small!");
1001 if (this.ImageXRes != 72 || this.ImageYRes != 72)
1003 zoom *= Math.Sqrt(this.ImageXRes * this.ImageYRes) / 72;
1004 region =
new Rectangle(region.
X0 * 72 /
this.ImageXRes, region.
Y0 * 72 /
this.ImageYRes, region.
X1 * 72 /
this.ImageXRes, region.
Y1 * 72 /
this.ImageYRes);
1007 float fzoom = (float)zoom;
1011 using (UTF8EncodedString encodedFileName =
new UTF8EncodedString(fileName))
1013 result = (
ExitCodes)NativeMethods.SaveImage(OwnerContext.NativeContext, DisplayLists[pageNumber].NativeDisplayList, region.
X0, region.
Y0, region.
X1, region.
Y1, fzoom, (
int)
PixelFormats.RGB, encodedFileName.Address, (int)
RasterOutputFileTypes.JPEG, quality);
1023 throw new MuPDFException(
"Cannot save to the output file", result);
1046 SaveImage(pageNumber, region, zoom, pixelFormat, fileName, fileType, includeAnnotations);
1057 public void SaveImageAsJPEG(
int pageNumber,
double zoom,
string fileName,
int quality,
bool includeAnnotations =
true)
1065 SaveImageAsJPEG(pageNumber, region, zoom, fileName, quality, includeAnnotations);
1087 throw new ArgumentException(
"Cannot save an image with alpha channel in PNM format!", nameof(fileType));
1092 throw new ArgumentException(
"The JPEG format only supports RGB pixel data without an alpha channel!", nameof(fileType));
1097 throw new ArgumentException(
"The PNG format only supports RGB or RGBA pixel data!", nameof(fileType));
1100 if (DisplayLists[pageNumber] ==
null)
1102 DisplayLists[pageNumber] =
new MuPDFDisplayList(this.OwnerContext, this.
Pages[pageNumber], includeAnnotations);
1105 if (zoom < 0.000001 | zoom * region.
Width <= 0.001 || zoom * region.
Height <= 0.001)
1107 throw new ArgumentOutOfRangeException(nameof(zoom), zoom,
"The zoom factor is too small!");
1110 if (this.ImageXRes != 72 || this.ImageYRes != 72)
1112 zoom *= Math.Sqrt(this.ImageXRes * this.ImageYRes) / 72;
1113 region =
new Rectangle(region.
X0 * 72 /
this.ImageXRes, region.
Y0 * 72 /
this.ImageYRes, region.
X1 * 72 /
this.ImageXRes, region.
Y1 * 72 /
this.ImageYRes);
1116 float fzoom = (float)zoom;
1118 IntPtr outputBuffer = IntPtr.Zero;
1119 IntPtr outputData = IntPtr.Zero;
1120 ulong outputDataLength = 0;
1122 ExitCodes result = (
ExitCodes)NativeMethods.WriteImage(OwnerContext.NativeContext, DisplayLists[pageNumber].NativeDisplayList, region.
X0, region.
Y0, region.
X1, region.
Y1, fzoom, (
int)pixelFormat, (int)fileType, 90, ref outputBuffer, ref outputData, ref outputDataLength);
1130 case ExitCodes.ERR_CANNOT_CREATE_CONTEXT:
1131 throw new MuPDFException(
"Cannot create the output buffer", result);
1136 byte[] buffer =
new byte[1024];
1138 while (outputDataLength > 0)
1140 int bytesToCopy = (int)Math.Min(buffer.Length, (
long)outputDataLength);
1141 Marshal.Copy(outputData, buffer, 0, bytesToCopy);
1142 outputData = IntPtr.Add(outputData, bytesToCopy);
1143 outputStream.Write(buffer, 0, bytesToCopy);
1144 outputDataLength -= (ulong)bytesToCopy;
1147 NativeMethods.DisposeBuffer(OwnerContext.NativeContext, outputBuffer);
1160 public void WriteImageAsJPEG(
int pageNumber,
Rectangle region,
double zoom, Stream outputStream,
int quality,
bool includeAnnotations =
true)
1167 if (quality < 0 || quality > 100)
1169 throw new ArgumentOutOfRangeException(nameof(quality), quality,
"The JPEG quality must range between 0 and 100 (inclusive)!");
1172 if (DisplayLists[pageNumber] ==
null)
1174 DisplayLists[pageNumber] =
new MuPDFDisplayList(this.OwnerContext, this.
Pages[pageNumber], includeAnnotations);
1177 if (zoom < 0.000001 | zoom * region.
Width <= 0.001 || zoom * region.
Height <= 0.001)
1179 throw new ArgumentOutOfRangeException(nameof(zoom), zoom,
"The zoom factor is too small!");
1182 if (this.ImageXRes != 72 || this.ImageYRes != 72)
1184 zoom *= Math.Sqrt(this.ImageXRes * this.ImageYRes) / 72;
1185 region =
new Rectangle(region.
X0 * 72 /
this.ImageXRes, region.
Y0 * 72 /
this.ImageYRes, region.
X1 * 72 /
this.ImageXRes, region.
Y1 * 72 /
this.ImageYRes);
1188 float fzoom = (float)zoom;
1190 IntPtr outputBuffer = IntPtr.Zero;
1191 IntPtr outputData = IntPtr.Zero;
1192 ulong outputDataLength = 0;
1194 ExitCodes result = (
ExitCodes)NativeMethods.WriteImage(OwnerContext.NativeContext, DisplayLists[pageNumber].NativeDisplayList, region.
X0, region.
Y0, region.
X1, region.
Y1, fzoom, (
int)
PixelFormats.RGB, (int)
RasterOutputFileTypes.JPEG, quality, ref outputBuffer, ref outputData, ref outputDataLength);
1202 case ExitCodes.ERR_CANNOT_CREATE_CONTEXT:
1203 throw new MuPDFException(
"Cannot create the output buffer", result);
1208 byte[] buffer =
new byte[1024];
1210 while (outputDataLength > 0)
1212 int bytesToCopy = (int)Math.Min(buffer.Length, (
long)outputDataLength);
1213 Marshal.Copy(outputData, buffer, 0, bytesToCopy);
1214 outputData = IntPtr.Add(outputData, bytesToCopy);
1215 outputStream.Write(buffer, 0, bytesToCopy);
1216 outputDataLength -= (ulong)bytesToCopy;
1219 NativeMethods.DisposeBuffer(OwnerContext.NativeContext, outputBuffer);
1239 WriteImage(pageNumber, region, zoom, pixelFormat, outputStream, fileType, includeAnnotations);
1250 public void WriteImageAsJPEG(
int pageNumber,
double zoom, Stream outputStream,
int quality,
bool includeAnnotations =
true)
1258 WriteImageAsJPEG(pageNumber, region, zoom, outputStream, quality, includeAnnotations);
1275 throw new ArgumentException(
"You cannot create an SVG document with more than one page!", nameof(pages));
1278 string originalFileName = fileName;
1283 fileName = Path.GetTempFileName();
1286 IntPtr documentWriter = IntPtr.Zero;
1291 using (UTF8EncodedString encodedFileName =
new UTF8EncodedString(fileName))
1294 result = (
ExitCodes)NativeMethods.CreateDocumentWriter(context.NativeContext, encodedFileName.Address, (
int)fileType, ref documentWriter);
1301 case ExitCodes.ERR_CANNOT_CREATE_WRITER:
1302 throw new MuPDFException(
"Cannot create the document writer", result);
1308 for (
int i = 0; i < pages.Length; i++)
1311 int pageNum = pages[i].page.PageNumber;
1313 if (doc.DisplayLists[pageNum] ==
null)
1315 doc.DisplayLists[pageNum] =
new MuPDFDisplayList(doc.OwnerContext, doc.
Pages[pageNum], includeAnnotations);
1319 double zoom = pages[i].zoom;
1321 if (pages[i].page.OwnerDocument.ImageXRes != 72 || pages[i].page.OwnerDocument.ImageYRes != 72)
1323 zoom *= Math.Sqrt(pages[i].page.OwnerDocument.ImageXRes * pages[i].page.OwnerDocument.ImageYRes) / 72;
1324 region =
new Rectangle(region.
X0 * 72 / pages[i].page.OwnerDocument.ImageXRes, region.
Y0 * 72 / pages[i].page.OwnerDocument.ImageYRes, region.
X1 * 72 / pages[i].page.OwnerDocument.ImageXRes, region.
Y1 * 72 / pages[i].page.OwnerDocument.ImageYRes);
1327 result = (
ExitCodes)NativeMethods.WriteSubDisplayListAsPage(context.NativeContext, doc.DisplayLists[pageNum].NativeDisplayList, region.
X0, region.
Y0, region.
X1, region.
Y1, (
float)zoom, documentWriter);
1334 throw new MuPDFException(
"Cannot render page " + i.ToString(), result);
1341 result = (
ExitCodes)NativeMethods.FinalizeDocumentWriter(context.NativeContext, documentWriter);
1347 case ExitCodes.ERR_CANNOT_CLOSE_DOCUMENT:
1348 throw new MuPDFException(
"Cannot finalise the document", result);
1357 string tempFileName = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) +
"1" + Path.GetExtension(fileName));
1360 if (File.Exists(originalFileName))
1362 File.Delete(originalFileName);
1365 File.Move(tempFileName, originalFileName);
1381 for (
int i = 0; i < pages.Length; i++)
1383 boundedPages[i] = (pages[i], pages[i].Bounds, 1);
1386 CreateDocument(context, fileName, fileType, includeAnnotations, boundedPages);
1403 if (DisplayLists[pageNumber] ==
null)
1405 DisplayLists[pageNumber] =
new MuPDFDisplayList(this.OwnerContext, this.
Pages[pageNumber], includeAnnotations);
1427 if (DisplayLists[pageNumber] ==
null)
1429 DisplayLists[pageNumber] =
new MuPDFDisplayList(this.OwnerContext, this.
Pages[pageNumber], includeAnnotations);
1435 if (this.ImageXRes != 72 || this.ImageYRes != 72)
1437 zoom *= Math.Sqrt(this.ImageXRes * this.ImageYRes) / 72;
1438 region =
new Rectangle(region.
X0 * 72 /
this.ImageXRes, region.
Y0 * 72 /
this.ImageYRes, region.
X1 * 72 /
this.ImageXRes, region.
Y1 * 72 /
this.ImageYRes);
1441 return new MuPDFStructuredTextPage(this.OwnerContext, this.DisplayLists[pageNumber], ocrLanguage, zoom, region, cancellationToken, progress);
1453 public async Task<MuPDFStructuredTextPage>
GetStructuredTextPageAsync(
int pageNumber,
TesseractLanguage ocrLanguage,
bool includeAnnotations =
true, CancellationToken cancellationToken =
default, IProgress<OCRProgressInfo> progress =
null)
1460 if (DisplayLists[pageNumber] ==
null)
1462 DisplayLists[pageNumber] =
new MuPDFDisplayList(this.OwnerContext, this.
Pages[pageNumber], includeAnnotations);
1468 if (this.ImageXRes != 72 || this.ImageYRes != 72)
1470 zoom *= Math.Sqrt(this.ImageXRes * this.ImageYRes) / 72;
1471 region =
new Rectangle(region.
X0 * 72 /
this.ImageXRes, region.
Y0 * 72 /
this.ImageYRes, region.
X1 * 72 /
this.ImageXRes, region.
Y1 * 72 /
this.ImageYRes);
1474 return await Task.Run(() =>
new MuPDFStructuredTextPage(this.OwnerContext, this.DisplayLists[pageNumber], ocrLanguage, zoom, region, cancellationToken, progress));
1483 public string ExtractText(
string separator =
null,
bool includeAnnotations =
true)
1490 separator = separator ?? Environment.NewLine;
1492 var text =
new StringBuilder();
1493 bool started =
false;
1500 var numLines = textBlock.
Count;
1501 for (var j = 0; j < numLines; j++)
1503 if (!
string.IsNullOrWhiteSpace(textBlock[j].Text))
1507 text.Append(separator);
1514 text.Append(textBlock[j].Text);
1520 return text.ToString();
1537 separator = separator ?? Environment.NewLine;
1539 var text =
new StringBuilder();
1540 bool started =
false;
1547 var numLines = textBlock.
Count;
1548 for (var j = 0; j < numLines; j++)
1550 if (!
string.IsNullOrWhiteSpace(textBlock[j].Text))
1554 text.Append(separator);
1561 text.Append(textBlock[j].Text);
1567 return text.ToString();
1579 public async Task<string>
ExtractTextAsync(
TesseractLanguage ocrLanguage,
string separator =
null,
bool includeAnnotations =
true, CancellationToken cancellationToken =
default, IProgress<OCRProgressInfo> progress =
null)
1586 separator = separator ?? Environment.NewLine;
1588 var text =
new StringBuilder();
1589 bool started =
false;
1596 var numLines = textBlock.
Count;
1597 for (var j = 0; j < numLines; j++)
1599 if (!
string.IsNullOrWhiteSpace(textBlock[j].Text))
1603 text.Append(separator);
1610 text.Append(textBlock[j].Text);
1616 return text.ToString();
1640 int result = NativeMethods.UnlockWithPassword(this.OwnerContext.NativeContext,
this.NativeDocument, password);
1660 return !(this.EncryptionState == EncryptionState.Encrypted || this.RestrictionState ==
RestrictionState.Restricted);
1695 throw new ArgumentOutOfRangeException(
"Unexpected return value when unlocking the document: " + result.ToString());
1700 private bool disposedValue;
1703 protected virtual void Dispose(
bool disposing)
1710 foreach (MuPDFDisplayList list
in DisplayLists)
1715 DataHolder?.Dispose();
1718 NativeMethods.DisposeDocument(OwnerContext.NativeContext, NativeDocument);
1720 if (NativeStream != IntPtr.Zero)
1722 NativeMethods.DisposeStream(OwnerContext.NativeContext, NativeStream);
1725 disposedValue =
true;
1732 Dispose(disposing:
false);
1736 public void Dispose()
1738 Dispose(disposing:
true);
1739 GC.SuppressFinalize(
this);
An IDisposable wrapper around an IntPtr that frees the allocated memory when it is disposed.
The exception that is thrown when an attempt is made to render an encrypted document without supplyin...
A wrapper around a MuPDF context object, which contains the exception stack and the resource cache st...
A wrapper over a MuPDF document object, which contains possibly multiple pages.
void SaveImage(int pageNumber, double zoom, PixelFormats pixelFormat, string fileName, RasterOutputFileTypes fileType, bool includeAnnotations=true)
Save a page to an image file in the specified format.
byte[] Render(int pageNumber, Rectangle region, double zoom, PixelFormats pixelFormat, bool includeAnnotations=true)
Render (part of) a page to an array of bytes.
static int GetRenderedSize(Rectangle region, double zoom, PixelFormats pixelFormat)
Determine how many bytes will be necessary to render the specified region in page units at the specif...
void Layout(float width, float height, float em)
Sets the document layout for reflowable document types (e.g., HTML, MOBI). Does not have any effect f...
int GetRenderedSize(int pageNumber, double zoom, PixelFormats pixelFormat)
Determine how many bytes will be necessary to render the specified page at the specified zoom level,...
void ClearCache()
Discard all the display lists that have been loaded from the document, possibly freeing some memory i...
void WriteImageAsJPEG(int pageNumber, Rectangle region, double zoom, Stream outputStream, int quality, bool includeAnnotations=true)
Write (part of) a page to an image stream in JPEG format, with the specified quality.
void SaveImageAsJPEG(int pageNumber, Rectangle region, double zoom, string fileName, int quality, bool includeAnnotations=true)
Save (part of) a page to an image file in JPEG format, with the specified quality.
bool TryUnlock(string password)
Attempts to unlock the document with the supplied password.
MuPDFStructuredTextPage GetStructuredTextPage(int pageNumber, TesseractLanguage ocrLanguage, bool includeAnnotations=true, CancellationToken cancellationToken=default, IProgress< OCRProgressInfo > progress=null)
Creates a new MuPDFStructuredTextPage from the specified page, using optical character recognition (O...
Span< byte > Render(int pageNumber, Rectangle region, double zoom, PixelFormats pixelFormat, out IDisposable disposable, bool includeAnnotations=true)
Render (part of) a page to a Span<byte>.
void Render(int pageNumber, Rectangle region, double zoom, PixelFormats pixelFormat, IntPtr destination, bool includeAnnotations=true)
Render (part of) a page to the specified destination.
bool ClipToPageBounds
Defines whether the images resulting from rendering operations should be clipped to the page boundari...
void SaveImage(int pageNumber, Rectangle region, double zoom, PixelFormats pixelFormat, string fileName, RasterOutputFileTypes fileType, bool includeAnnotations=true)
Save (part of) a page to an image file in the specified format.
MuPDFDocument(MuPDFContext context, ref MemoryStream data, InputFileTypes fileType)
Create a new MuPDFDocument from a MemoryStream.
MuPDFMultiThreadedPageRenderer GetMultiThreadedRenderer(int pageNumber, int threadCount, bool includeAnnotations=true)
Create a new MuPDFMultiThreadedPageRenderer that renders the specified page with the specified number...
MuPDFDocument(MuPDFContext context, string fileName)
Create a new MuPDFDocument from a file.
static void CreateDocument(MuPDFContext context, string fileName, DocumentOutputFileTypes fileType, bool includeAnnotations=true, params(MuPDFPage page, Rectangle region, float zoom)[] pages)
Create a new document containing the specified (parts of) pages from other documents.
MuPDFStructuredTextPage GetStructuredTextPage(int pageNumber, bool includeAnnotations=true)
Creates a new MuPDFStructuredTextPage from the specified page. This contains information about the te...
async Task< string > ExtractTextAsync(TesseractLanguage ocrLanguage, string separator=null, bool includeAnnotations=true, CancellationToken cancellationToken=default, IProgress< OCRProgressInfo > progress=null)
Extracts all the text from the document and returns it as a string, using optical character recogniti...
string ExtractText(string separator=null, bool includeAnnotations=true)
Extracts all the text from the document and returns it as a string. The reading order is taken from t...
void SaveImageAsJPEG(int pageNumber, double zoom, string fileName, int quality, bool includeAnnotations=true)
Save a page to an image file in JPEG format, with the specified quality.
void LayoutSinglePage(float width, float em)
Sets the document layout for reflowable document types (e.g., HTML, MOBI), so that the document is re...
byte[] Render(int pageNumber, double zoom, PixelFormats pixelFormat, bool includeAnnotations=true)
Render a page to an array of bytes.
void WriteImageAsJPEG(int pageNumber, double zoom, Stream outputStream, int quality, bool includeAnnotations=true)
Write a page to an image stream in JPEG format, with the specified quality.
MuPDFDocument(MuPDFContext context, byte[] data, InputFileTypes fileType)
Create a new MuPDFDocument from an array of bytes.
MuPDFDocument(MuPDFContext context, IntPtr dataAddress, long dataLength, InputFileTypes fileType, ref IDisposable dataHolder)
Create a new MuPDFDocument from data bytes accessible through the specified pointer.
void WriteImage(int pageNumber, double zoom, PixelFormats pixelFormat, Stream outputStream, RasterOutputFileTypes fileType, bool includeAnnotations=true)
Write a page to an image stream in the specified format.
Span< byte > Render(int pageNumber, double zoom, PixelFormats pixelFormat, out IDisposable disposable, bool includeAnnotations=true)
Render a page to a Span<byte>.
async Task< MuPDFStructuredTextPage > GetStructuredTextPageAsync(int pageNumber, TesseractLanguage ocrLanguage, bool includeAnnotations=true, CancellationToken cancellationToken=default, IProgress< OCRProgressInfo > progress=null)
Creates a new MuPDFStructuredTextPage from the specified page, using optical character recognition (O...
void WriteImage(int pageNumber, Rectangle region, double zoom, PixelFormats pixelFormat, Stream outputStream, RasterOutputFileTypes fileType, bool includeAnnotations=true)
Write (part of) a page to an image stream in the specified format.
MuPDFDocument(MuPDFContext context, IntPtr dataAddress, long dataLength, InputFileTypes fileType)
Create a new MuPDFDocument from data bytes accessible through the specified pointer.
MuPDFPageCollection Pages
The pages contained in the document.
void Render(int pageNumber, double zoom, PixelFormats pixelFormat, IntPtr destination, bool includeAnnotations=true)
Render a page to the specified destination.
bool TryUnlock(string password, out PasswordTypes passwordType)
Attempts to unlock the document with the supplied password.
string ExtractText(TesseractLanguage ocrLanguage, string separator=null, bool includeAnnotations=true)
Extracts all the text from the document and returns it as a string, using optical character recogniti...
static void CreateDocument(MuPDFContext context, string fileName, DocumentOutputFileTypes fileType, bool includeAnnotations=true, params MuPDFPage[] pages)
Create a new document containing the specified pages from other documents.
DocumentRestrictions Restrictions
Describes the operations that are restricted on the document. This is not actually enforced by the li...
The exception that is thrown when a MuPDF operation fails.
A class that holds the necessary resources to render a page of a MuPDF document using multiple thread...
A lazy collection of MuPDFPages. Each page is loaded from the document as it is requested for the fir...
int Count
The number of pages in the collection.
A wrapper over a MuPDF page object, which contains information about the page's boundaries.
Represents a structured text block containing text or an image.
abstract int Count
The number of lines in the block.
Represents a structured representation of the text contained in a page.
Represents a language used by Tesseract OCR.
DocumentOutputFileTypes
Document file types supported in output by the library.
InputFileTypes
File types supported in input by the library.
EncryptionState
Possible document encryption states.
RestrictionState
Possible document restriction states.
ExitCodes
Exit codes returned by native methods describing various errors that can occur.
DocumentRestrictions
Document restrictions.
PixelFormats
Pixel formats supported by the library.
PasswordTypes
Password types.
RasterOutputFileTypes
Raster image file types supported in output by the library.
RoundedRectangle Round()
Round the rectangle's coordinates to the closest integers.
float Width
The width of the rectangle.
float Height
The height of the rectangle.
float Y0
The top coordinate of the rectangle.
float X1
The right coordinate of the rectangle.
float X0
The left coordinate of the rectangle.
float Y1
The bottom coordinate of the rectangle.
Represents a rectangle using only integer numbers.
int Width
The width of the rectangle.
int Height
The height of the rectangle.
Represents the size of a rectangle using only integer numbers.