Pdf Import Rewrite
Pdf Import rewritten to greatly improve QR Code detection, reduce reliance on iTextSharp and improve thumbnails. Fixes #50
This commit is contained in:
@@ -7,6 +7,7 @@ using Disco.Data.Repository;
|
||||
using Disco.Services.Users;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.BI.DocumentTemplateBI.ManagedGroups;
|
||||
using Disco.Services;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
using Disco.BI.DocumentTemplateBI;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Logging;
|
||||
using Disco.Services.Users;
|
||||
using Exceptionless;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class AttachmentExtensions
|
||||
{
|
||||
|
||||
public static bool ImportPdfAttachment(this DocumentUniqueIdentifier UniqueIdentifier, DiscoDataContext Database, System.IO.Stream PdfContent, byte[] PdfThumbnail)
|
||||
{
|
||||
UniqueIdentifier.LoadComponents(Database);
|
||||
DocumentTemplate documentTemplate = UniqueIdentifier.DocumentTemplate;
|
||||
string filename;
|
||||
string comments;
|
||||
object attachment;
|
||||
|
||||
if (documentTemplate == null)
|
||||
{
|
||||
filename = string.Format("{0}_{1:yyyyMMdd-HHmmss}.pdf", UniqueIdentifier.DataId.Replace('\\', '_'), UniqueIdentifier.TimeStamp);
|
||||
comments = string.Format("Uploaded: {0:s}", UniqueIdentifier.TimeStamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
filename = string.Format("{0}_{1:yyyyMMdd-HHmmss}.pdf", UniqueIdentifier.TemplateTypeId, UniqueIdentifier.TimeStamp);
|
||||
comments = string.Format("Generated: {0:s}", UniqueIdentifier.TimeStamp);
|
||||
}
|
||||
|
||||
User creatorUser = UserService.GetUser(UniqueIdentifier.CreatorId, Database);
|
||||
if (creatorUser == null)
|
||||
{
|
||||
// No Creator User (or Username invalid)
|
||||
creatorUser = UserService.CurrentUser;
|
||||
}
|
||||
switch (UniqueIdentifier.DataScope)
|
||||
{
|
||||
case DocumentTemplate.DocumentTemplateScopes.Device:
|
||||
Device d = (Device)UniqueIdentifier.Data;
|
||||
attachment = d.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
|
||||
break;
|
||||
case DocumentTemplate.DocumentTemplateScopes.Job:
|
||||
Job j = (Job)UniqueIdentifier.Data;
|
||||
attachment = j.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
|
||||
break;
|
||||
case DocumentTemplate.DocumentTemplateScopes.User:
|
||||
User u = (User)UniqueIdentifier.Data;
|
||||
attachment = u.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (documentTemplate != null && !string.IsNullOrWhiteSpace(documentTemplate.OnImportAttachmentExpression))
|
||||
{
|
||||
try
|
||||
{
|
||||
var expressionResult = documentTemplate.EvaluateOnAttachmentImportExpression(attachment, Database, creatorUser, UniqueIdentifier.TimeStamp);
|
||||
DocumentsLog.LogImportAttachmentExpressionEvaluated(documentTemplate, UniqueIdentifier.Data, attachment, expressionResult);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SystemLog.LogException("Document Importer - OnImportAttachmentExpression", ex);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static string RepositoryFilename(this DeviceAttachment da, DiscoDataContext Database)
|
||||
{
|
||||
return Path.Combine(DataStore.CreateLocation(Database, "DeviceAttachments", da.Timestamp), string.Format("{0}_{1}_file", da.DeviceSerialNumber, da.Id));
|
||||
}
|
||||
public static string RepositoryFilename(this JobAttachment ja, DiscoDataContext Database)
|
||||
{
|
||||
return Path.Combine(DataStore.CreateLocation(Database, "JobAttachments", ja.Timestamp), string.Format("{0}_{1}_file", ja.JobId, ja.Id));
|
||||
}
|
||||
public static string RepositoryFilename(this UserAttachment ua, DiscoDataContext Database)
|
||||
{
|
||||
return Path.Combine(DataStore.CreateLocation(Database, "UserAttachments", ua.Timestamp), string.Format("{0}_{1}_file", ua.UserId.Replace('\\', '_'), ua.Id));
|
||||
}
|
||||
|
||||
private static string RepositoryThumbnailFilenameInternal(string DirectoryPath, string Filename)
|
||||
{
|
||||
return Path.Combine(DirectoryPath, Filename);
|
||||
}
|
||||
public static string RepositoryThumbnailFilename(this DeviceAttachment da, DiscoDataContext Database)
|
||||
{
|
||||
return RepositoryThumbnailFilenameInternal(DataStore.CreateLocation(Database, "DeviceAttachments", da.Timestamp), string.Format("{0}_{1}_thumb.jpg", da.DeviceSerialNumber, da.Id));
|
||||
}
|
||||
public static string RepositoryThumbnailFilename(this JobAttachment ja, DiscoDataContext Database)
|
||||
{
|
||||
return RepositoryThumbnailFilenameInternal(DataStore.CreateLocation(Database, "JobAttachments", ja.Timestamp), string.Format("{0}_{1}_thumb.jpg", ja.JobId, ja.Id));
|
||||
}
|
||||
public static string RepositoryThumbnailFilename(this UserAttachment ua, DiscoDataContext Database)
|
||||
{
|
||||
return RepositoryThumbnailFilenameInternal(DataStore.CreateLocation(Database, "UserAttachments", ua.Timestamp), string.Format("{0}_{1}_thumb.jpg", ua.UserId.Replace('\\', '_'), ua.Id));
|
||||
}
|
||||
|
||||
public static void RepositoryDelete(this DeviceAttachment da, DiscoDataContext Database)
|
||||
{
|
||||
RepositoryDelete(da.RepositoryFilename(Database), da.RepositoryThumbnailFilename(Database));
|
||||
}
|
||||
public static void RepositoryDelete(this JobAttachment ja, DiscoDataContext Database)
|
||||
{
|
||||
RepositoryDelete(ja.RepositoryFilename(Database), ja.RepositoryThumbnailFilename(Database));
|
||||
}
|
||||
public static void RepositoryDelete(this UserAttachment ua, DiscoDataContext Database)
|
||||
{
|
||||
RepositoryDelete(ua.RepositoryFilename(Database), ua.RepositoryThumbnailFilename(Database));
|
||||
}
|
||||
private static void RepositoryDelete(params string[] filePaths)
|
||||
{
|
||||
foreach (string filePath in filePaths)
|
||||
{
|
||||
if (File.Exists(filePath))
|
||||
File.Delete(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
public static string SaveAttachment(this DeviceAttachment da, DiscoDataContext Database, Stream FileContent)
|
||||
{
|
||||
string filePath = da.RepositoryFilename(Database);
|
||||
SaveAttachment(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
public static string SaveAttachment(this JobAttachment ja, DiscoDataContext Database, Stream FileContent)
|
||||
{
|
||||
string filePath = ja.RepositoryFilename(Database);
|
||||
SaveAttachment(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
public static string SaveAttachment(this UserAttachment ua, DiscoDataContext Database, Stream FileContent)
|
||||
{
|
||||
string filePath = ua.RepositoryFilename(Database);
|
||||
SaveAttachment(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
public static string SaveThumbnailAttachment(this DeviceAttachment da, DiscoDataContext Database, byte[] FileContent)
|
||||
{
|
||||
string filePath = da.RepositoryThumbnailFilename(Database);
|
||||
File.WriteAllBytes(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
public static string SaveThumbnailAttachment(this JobAttachment ja, DiscoDataContext Database, byte[] FileContent)
|
||||
{
|
||||
string filePath = ja.RepositoryThumbnailFilename(Database);
|
||||
File.WriteAllBytes(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
public static string SaveThumbnailAttachment(this UserAttachment ua, DiscoDataContext Database, byte[] FileContent)
|
||||
{
|
||||
string filePath = ua.RepositoryThumbnailFilename(Database);
|
||||
File.WriteAllBytes(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
private static void SaveAttachment(string FilePath, Stream FileContent)
|
||||
{
|
||||
using (FileStream sw = new FileStream(FilePath, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
FileContent.CopyTo(sw);
|
||||
sw.Flush();
|
||||
sw.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public static string GenerateThumbnail(this DeviceAttachment da, DiscoDataContext Database)
|
||||
{
|
||||
string filePath = da.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(da.RepositoryFilename(Database), da.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
public static string GenerateThumbnail(this JobAttachment ja, DiscoDataContext Database)
|
||||
{
|
||||
string filePath = ja.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(ja.RepositoryFilename(Database), ja.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
public static string GenerateThumbnail(this UserAttachment ua, DiscoDataContext Database)
|
||||
{
|
||||
string filePath = ua.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(ua.RepositoryFilename(Database), ua.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
public static string GenerateThumbnail(this DeviceAttachment da, DiscoDataContext Database, Stream SourceFile)
|
||||
{
|
||||
string filePath = da.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(SourceFile, da.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
public static string GenerateThumbnail(this JobAttachment ja, DiscoDataContext Database, Stream SourceFile)
|
||||
{
|
||||
string filePath = ja.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(SourceFile, ja.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
public static string GenerateThumbnail(this UserAttachment ua, DiscoDataContext Database, Stream SourceFile)
|
||||
{
|
||||
string filePath = ua.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(SourceFile, ua.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Users;
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
using System.Linq;
|
||||
using Disco.Data.Configuration;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.BI.DocumentTemplates;
|
||||
using Disco.Models.Repository;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.IO;
|
||||
using Disco.Services.Users;
|
||||
using Disco.Models.Services.Documents;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Expressions;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Users;
|
||||
using Exceptionless;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
@@ -21,15 +22,15 @@ namespace Disco.BI.Extensions
|
||||
if (Domain == null)
|
||||
throw new ArgumentNullException("Domain");
|
||||
|
||||
DeviceProfile deviceProfile = device.DeviceProfile;
|
||||
Expressions.Expression computerNameTemplateExpression = null;
|
||||
computerNameTemplateExpression = Expressions.ExpressionCache.GetValue(DeviceProfileExtensions.ComputerNameExpressionCacheModule, deviceProfile.Id.ToString(), () =>
|
||||
var deviceProfile = device.DeviceProfile;
|
||||
Expression computerNameTemplateExpression = null;
|
||||
computerNameTemplateExpression = ExpressionCache.GetValue(DeviceProfileExtensions.ComputerNameExpressionCacheModule, deviceProfile.Id.ToString(), () =>
|
||||
{
|
||||
// Removed 2012-06-14 G# - Properties moved to DeviceProfile model & DB Migrated in DBv3.
|
||||
//return Expressions.Expression.TokenizeSingleDynamic(null, deviceProfile.Configuration(context).ComputerNameTemplate, 0);
|
||||
return Expressions.Expression.TokenizeSingleDynamic(null, deviceProfile.ComputerNameTemplate, 0);
|
||||
return Expression.TokenizeSingleDynamic(null, deviceProfile.ComputerNameTemplate, 0);
|
||||
});
|
||||
System.Collections.IDictionary evaluatorVariables = Expressions.Expression.StandardVariables(null, Database, UserService.CurrentUser, System.DateTime.Now, null);
|
||||
var evaluatorVariables = Expression.StandardVariables(null, Database, UserService.CurrentUser, DateTime.Now, null);
|
||||
string rendered;
|
||||
try
|
||||
{
|
||||
@@ -42,53 +43,22 @@ namespace Disco.BI.Extensions
|
||||
}
|
||||
if (rendered == null || rendered.Length > 24)
|
||||
{
|
||||
throw new System.InvalidOperationException("The rendered computer name would be invalid or longer than 24 characters");
|
||||
throw new InvalidOperationException("The rendered computer name would be invalid or longer than 24 characters");
|
||||
}
|
||||
|
||||
return string.Format(@"{0}\{1}", Domain.NetBiosName, rendered);
|
||||
}
|
||||
public static System.Collections.Generic.List<DocumentTemplate> AvailableDocumentTemplates(this Device d, DiscoDataContext Database, User User, System.DateTime TimeStamp)
|
||||
public static List<DocumentTemplate> AvailableDocumentTemplates(this Device d, DiscoDataContext Database, User User, DateTime TimeStamp)
|
||||
{
|
||||
List<DocumentTemplate> ats = Database.DocumentTemplates
|
||||
.Where(at => at.Scope == Disco.Models.Repository.DocumentTemplate.DocumentTemplateScopes.Device).ToList();
|
||||
.Where(at => at.Scope == DocumentTemplate.DocumentTemplateScopes.Device).ToList();
|
||||
|
||||
return ats.Where(at => at.FilterExpressionMatches(d, Database, User, TimeStamp, DocumentState.DefaultState())).ToList();
|
||||
}
|
||||
|
||||
public static bool UpdateLastNetworkLogonDate(this Device Device)
|
||||
{
|
||||
return Disco.Services.Interop.ActiveDirectory.ADNetworkLogonDatesUpdateTask.UpdateLastNetworkLogonDate(Device);
|
||||
}
|
||||
|
||||
public static DeviceAttachment CreateAttachment(this Device Device, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase))
|
||||
MimeType = Interop.MimeTypes.ResolveMimeType(Filename);
|
||||
|
||||
DeviceAttachment da = new DeviceAttachment()
|
||||
{
|
||||
DeviceSerialNumber = Device.SerialNumber,
|
||||
TechUserId = CreatorUser.UserId,
|
||||
Filename = Filename,
|
||||
MimeType = MimeType,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = Comments
|
||||
};
|
||||
|
||||
if (DocumentTemplate != null)
|
||||
da.DocumentTemplateId = DocumentTemplate.Id;
|
||||
|
||||
Database.DeviceAttachments.Add(da);
|
||||
Database.SaveChanges();
|
||||
|
||||
da.SaveAttachment(Database, Content);
|
||||
Content.Position = 0;
|
||||
if (PdfThumbnail == null)
|
||||
da.GenerateThumbnail(Database, Content);
|
||||
else
|
||||
da.SaveThumbnailAttachment(Database, PdfThumbnail);
|
||||
|
||||
return da;
|
||||
return ADNetworkLogonDatesUpdateTask.UpdateLastNetworkLogonDate(Device);
|
||||
}
|
||||
|
||||
public static Device AddOffline(this Device d, DiscoDataContext Database)
|
||||
@@ -189,15 +159,7 @@ namespace Disco.BI.Extensions
|
||||
return newDua;
|
||||
}
|
||||
|
||||
public static ADMachineAccount ActiveDirectoryAccount(this Device Device, params string[] AdditionalProperties)
|
||||
{
|
||||
if (ActiveDirectory.IsValidDomainAccountId(Device.DeviceDomainId))
|
||||
return ActiveDirectory.RetrieveADMachineAccount(Device.DeviceDomainId, AdditionalProperties: AdditionalProperties);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string ReasonMessage(this Disco.Models.Repository.DecommissionReasons r)
|
||||
public static string ReasonMessage(this DecommissionReasons r)
|
||||
{
|
||||
switch (r)
|
||||
{
|
||||
@@ -220,7 +182,7 @@ namespace Disco.BI.Extensions
|
||||
}
|
||||
}
|
||||
|
||||
public static string ReasonMessage(this Disco.Models.Repository.DecommissionReasons? r)
|
||||
public static string ReasonMessage(this DecommissionReasons? r)
|
||||
{
|
||||
if (!r.HasValue)
|
||||
return "Not Decommissioned";
|
||||
|
||||
@@ -1,79 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Services.Users;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Users;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class DeviceModelExtensions
|
||||
{
|
||||
public static bool ImageImport(this DeviceModel deviceModel, Stream ImageStream)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (Bitmap inputBitmap = new Bitmap(ImageStream))
|
||||
{
|
||||
using (Image outputBitmap = inputBitmap.ResizeImage(256, 256))
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
outputBitmap.SavePng(ms);
|
||||
ms.Position = 0;
|
||||
|
||||
var deviceModelImagePath = deviceModel.ImageFilePath();
|
||||
|
||||
|
||||
using (var storeStream = new FileStream(deviceModelImagePath, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
ms.CopyTo(storeStream);
|
||||
}
|
||||
//deviceModel.Image = ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static FileStream Image(this DeviceModel deviceModel)
|
||||
{
|
||||
var deviceModelImagePath = deviceModel.ImageFilePath();
|
||||
|
||||
if (File.Exists(deviceModelImagePath))
|
||||
return new FileStream(deviceModelImagePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string ImageFilePath(this DeviceModel deviceModel)
|
||||
{
|
||||
var configCache = new Disco.Data.Configuration.SystemConfiguration(null);
|
||||
|
||||
var deviceModelImagesDataStore = DataStore.CreateLocation(configCache, "DeviceModelImages");
|
||||
|
||||
return Path.Combine(deviceModelImagesDataStore, string.Format("{0}.png", deviceModel.Id));
|
||||
}
|
||||
|
||||
public static string ImageHash(this DeviceModel deviceModel)
|
||||
{
|
||||
var deviceModelImagePath = deviceModel.ImageFilePath();
|
||||
|
||||
if (File.Exists(deviceModelImagePath))
|
||||
return File.GetLastWriteTimeUtc(deviceModelImagePath).ToBinary().ToString();
|
||||
else
|
||||
return "-1";
|
||||
}
|
||||
|
||||
#region Actions
|
||||
public static bool CanDelete(this DeviceModel dm, DiscoDataContext Database)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using Disco.Models.BI.Config;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Devices.ManagedGroups;
|
||||
using Disco.Services.Expressions;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Users;
|
||||
using System;
|
||||
@@ -16,7 +17,7 @@ namespace Disco.BI.Extensions
|
||||
|
||||
public static void ComputerNameInvalidateCache(this DeviceProfile deviceProfile)
|
||||
{
|
||||
Expressions.ExpressionCache.InvalidateKey(ComputerNameExpressionCacheModule, deviceProfile.Id.ToString());
|
||||
ExpressionCache.InvalidateKey(ComputerNameExpressionCacheModule, deviceProfile.Id.ToString());
|
||||
}
|
||||
|
||||
public static OrganisationAddress DefaultOrganisationAddressDetails(this DeviceProfile deviceProfile, DiscoDataContext Database)
|
||||
|
||||
@@ -1,48 +1,27 @@
|
||||
using Disco.BI.DocumentTemplateBI;
|
||||
using Disco.BI.DocumentTemplateBI.ManagedGroups;
|
||||
using Disco.BI.Expressions;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.BI.DocumentTemplates;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Documents;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Documents;
|
||||
using Disco.Services.Expressions;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using iTextSharp.text.pdf;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class DocumentTemplateExtensions
|
||||
{
|
||||
private const string DocumentTemplateExpressionCacheTemplate = "DocumentTemplate_{0}";
|
||||
|
||||
public static string RepositoryFilename(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
return System.IO.Path.Combine(DataStore.CreateLocation(Database, "DocumentTemplates"), string.Format("{0}.pdf", dt.Id));
|
||||
}
|
||||
public static string SavePdfTemplate(this DocumentTemplate dt, DiscoDataContext Database, Stream TemplateFile)
|
||||
{
|
||||
string filePath = dt.RepositoryFilename(Database);
|
||||
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
TemplateFile.CopyTo(fs);
|
||||
}
|
||||
Expressions.ExpressionCache.InvalidModule(string.Format(DocumentTemplateExpressionCacheTemplate, dt.Id));
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public static DisposableImageCollection PdfPageImages(this PdfReader pdfReader, int PageNumber)
|
||||
{
|
||||
return Interop.Pdf.PdfImporter.GetPageImages(pdfReader, PageNumber);
|
||||
}
|
||||
internal const string CacheTemplate = "DocumentTemplate_{0}";
|
||||
|
||||
public static ConcurrentDictionary<string, Expression> PdfExpressionsFromCache(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
string cacheModuleKey = string.Format(DocumentTemplateExpressionCacheTemplate, dt.Id);
|
||||
var module = Expressions.ExpressionCache.GetModule(cacheModuleKey);
|
||||
string cacheModuleKey = string.Format(CacheTemplate, dt.Id);
|
||||
var module = ExpressionCache.GetModule(cacheModuleKey);
|
||||
if (module == null)
|
||||
{
|
||||
// Cache
|
||||
@@ -52,199 +31,46 @@ namespace Disco.BI.Extensions
|
||||
foreach (string pdfFieldKey in pdfReader.AcroFields.Fields.Keys)
|
||||
{
|
||||
var pdfFieldValue = pdfReader.AcroFields.GetField(pdfFieldKey);
|
||||
Expressions.ExpressionCache.SetValue(cacheModuleKey, pdfFieldKey, Expressions.Expression.Tokenize(pdfFieldKey, pdfFieldValue, pdfFieldOrdinal));
|
||||
ExpressionCache.SetValue(cacheModuleKey, pdfFieldKey, Expression.Tokenize(pdfFieldKey, pdfFieldValue, pdfFieldOrdinal));
|
||||
pdfFieldOrdinal++;
|
||||
}
|
||||
pdfReader.Close();
|
||||
module = Expressions.ExpressionCache.GetModule(cacheModuleKey, true);
|
||||
module = ExpressionCache.GetModule(cacheModuleKey, true);
|
||||
}
|
||||
return module;
|
||||
}
|
||||
|
||||
public static List<BI.Expressions.Expression> ExtractPdfExpressions(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
public static List<Expression> ExtractPdfExpressions(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
return dt.PdfExpressionsFromCache(Database).Values.OrderBy(e => e.Ordinal).ToList();
|
||||
}
|
||||
public static System.IO.Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, System.DateTime Timestamp, params string[] DataObjectsIds)
|
||||
|
||||
public static System.IO.Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, params string[] DataObjectsIds)
|
||||
{
|
||||
return Interop.Pdf.PdfGenerator.GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, DataObjectsIds);
|
||||
}
|
||||
public static System.IO.Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, System.DateTime Timestamp, params object[] DataObjects)
|
||||
public static System.IO.Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, params IAttachmentTarget[] DataObjects)
|
||||
{
|
||||
return Interop.Pdf.PdfGenerator.GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, DataObjects);
|
||||
}
|
||||
public static System.IO.Stream GeneratePdf(this DocumentTemplate dt, DiscoDataContext Database, object Data, User CreatorUser, System.DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
|
||||
public static System.IO.Stream GeneratePdf(this DocumentTemplate dt, DiscoDataContext Database, IAttachmentTarget Target, User CreatorUser, DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
|
||||
{
|
||||
bool generateExpression = !string.IsNullOrEmpty(dt.OnGenerateExpression);
|
||||
string generateExpressionResult = null;
|
||||
|
||||
if (generateExpression)
|
||||
generateExpressionResult = dt.EvaluateOnGenerateExpression(Data, Database, CreatorUser, TimeStamp, State);
|
||||
generateExpressionResult = dt.EvaluateOnGenerateExpression(Target, Database, CreatorUser, TimeStamp, State);
|
||||
|
||||
var pdfStream = Interop.Pdf.PdfGenerator.GenerateFromTemplate(dt, Database, Data, CreatorUser, TimeStamp, State, FlattenFields);
|
||||
var pdfStream = Interop.Pdf.PdfGenerator.GenerateFromTemplate(dt, Database, Target, CreatorUser, TimeStamp, State, FlattenFields);
|
||||
|
||||
if (generateExpression)
|
||||
DocumentsLog.LogDocumentGenerated(dt, Data, CreatorUser, generateExpressionResult);
|
||||
DocumentsLog.LogDocumentGenerated(dt, Target, CreatorUser, generateExpressionResult);
|
||||
else
|
||||
DocumentsLog.LogDocumentGenerated(dt, Data, CreatorUser);
|
||||
DocumentsLog.LogDocumentGenerated(dt, Target, CreatorUser);
|
||||
|
||||
return pdfStream;
|
||||
}
|
||||
|
||||
public static Expression FilterExpressionFromCache(this DocumentTemplate dt)
|
||||
{
|
||||
return ExpressionCache.GetValue("DocumentTemplate_FilterExpression", dt.Id, () => { return Expression.TokenizeSingleDynamic(null, dt.FilterExpression, 0); });
|
||||
}
|
||||
public static void FilterExpressionInvalidateCache(this DocumentTemplate dt)
|
||||
{
|
||||
ExpressionCache.InvalidateKey("DocumentTemplate_FilterExpression", dt.Id);
|
||||
}
|
||||
public static bool FilterExpressionMatches(this DocumentTemplate dt, object Data, DiscoDataContext Database, User User, System.DateTime TimeStamp, DocumentState State)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(dt.FilterExpression))
|
||||
{
|
||||
Expression compiledExpression = dt.FilterExpressionFromCache();
|
||||
System.Collections.IDictionary evaluatorVariables = Expression.StandardVariables(dt, Database, User, TimeStamp, State);
|
||||
try
|
||||
{
|
||||
object er = compiledExpression.EvaluateFirst<object>(Data, evaluatorVariables);
|
||||
if (er is bool)
|
||||
{
|
||||
return (bool)er;
|
||||
}
|
||||
bool erBool;
|
||||
if (bool.TryParse(er.ToString(), out erBool))
|
||||
{
|
||||
return erBool;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Expression OnImportAttachmentExpressionFromCache(this DocumentTemplate dt)
|
||||
{
|
||||
return ExpressionCache.GetValue("DocumentTemplate_OnImportExpression", dt.Id, () => { return Expression.TokenizeSingleDynamic(null, dt.OnImportAttachmentExpression, 0); });
|
||||
}
|
||||
public static void OnImportAttachmentExpressionInvalidateCache(this DocumentTemplate dt)
|
||||
{
|
||||
ExpressionCache.InvalidateKey("DocumentTemplate_OnImportExpression", dt.Id);
|
||||
}
|
||||
public static string EvaluateOnAttachmentImportExpression(this DocumentTemplate dt, object Data, DiscoDataContext Database, User User, System.DateTime TimeStamp)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(dt.OnImportAttachmentExpression))
|
||||
{
|
||||
Expression compiledExpression = dt.OnImportAttachmentExpressionFromCache();
|
||||
System.Collections.IDictionary evaluatorVariables = Expression.StandardVariables(dt, Database, User, TimeStamp, null);
|
||||
try
|
||||
{
|
||||
object result = compiledExpression.EvaluateFirst<object>(Data, evaluatorVariables);
|
||||
if (result == null)
|
||||
return null;
|
||||
else
|
||||
return result.ToString();
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Expression OnGenerateExpressionFromCache(this DocumentTemplate dt)
|
||||
{
|
||||
return ExpressionCache.GetValue("DocumentTemplate_OnGenerateExpression", dt.Id, () => { return Expression.TokenizeSingleDynamic(null, dt.OnGenerateExpression, 0); });
|
||||
}
|
||||
public static void OnGenerateExpressionInvalidateCache(this DocumentTemplate dt)
|
||||
{
|
||||
ExpressionCache.InvalidateKey("DocumentTemplate_OnGenerateExpression", dt.Id);
|
||||
}
|
||||
public static string EvaluateOnGenerateExpression(this DocumentTemplate dt, object Data, DiscoDataContext Database, User User, System.DateTime TimeStamp, DocumentState State)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(dt.OnGenerateExpression))
|
||||
{
|
||||
Expression compiledExpression = dt.OnGenerateExpressionFromCache();
|
||||
System.Collections.IDictionary evaluatorVariables = Expression.StandardVariables(dt, Database, User, TimeStamp, State);
|
||||
try
|
||||
{
|
||||
object result = compiledExpression.EvaluateFirst<object>(Data, evaluatorVariables);
|
||||
return result.ToString();
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetDataId(this DocumentTemplate dt, object Data)
|
||||
{
|
||||
if (Data is string)
|
||||
{
|
||||
return (string)Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (dt.Scope)
|
||||
{
|
||||
case Models.Repository.DocumentTemplate.DocumentTemplateScopes.Device:
|
||||
if (!(Data is Device))
|
||||
throw new ArgumentException("This Document Template is configured for Devices only", "Data");
|
||||
Device d = (Device)Data;
|
||||
return d.SerialNumber;
|
||||
case Models.Repository.DocumentTemplate.DocumentTemplateScopes.Job:
|
||||
if (!(Data is Job))
|
||||
throw new ArgumentException("This Document Template is configured for Jobs only", "Data");
|
||||
Job d2 = (Job)Data;
|
||||
return d2.Id.ToString();
|
||||
case Models.Repository.DocumentTemplate.DocumentTemplateScopes.User:
|
||||
if (!(Data is User))
|
||||
throw new ArgumentException("This Document Template is configured for Users only", "Data");
|
||||
User d3 = (User)Data;
|
||||
return d3.UserId;
|
||||
default:
|
||||
throw new InvalidOperationException("Invalid Document Template Scope");
|
||||
}
|
||||
}
|
||||
}
|
||||
public static string UniqueIdentifier(string DocumentTemplateId, string DataId, string CreatorId, System.DateTime Timestamp)
|
||||
{
|
||||
return string.Format("Disco|1|{0}|{1}|{2}|{3:s}",
|
||||
DocumentTemplateId,
|
||||
DataId,
|
||||
CreatorId,
|
||||
Timestamp
|
||||
);
|
||||
}
|
||||
public static string UniqueIdentifier(this DocumentTemplate dt, object Data, string CreatorId, System.DateTime Timestamp)
|
||||
{
|
||||
return string.Format("Disco|1|{0}|{1}|{2}|{3:s}",
|
||||
dt.Id,
|
||||
dt.GetDataId(System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Data)),
|
||||
CreatorId,
|
||||
Timestamp
|
||||
);
|
||||
}
|
||||
public static string UniquePageIdentifier(this DocumentTemplate dt, object Data, string CreatorId, System.DateTime Timestamp, int Page)
|
||||
{
|
||||
return string.Format("Disco|1|{0}|{1}|{2}|{3:s}|{4}",
|
||||
dt.Id,
|
||||
dt.GetDataId(System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Data)),
|
||||
CreatorId,
|
||||
Timestamp,
|
||||
Page
|
||||
);
|
||||
}
|
||||
public static List<RectangleF> QRCodeLocations(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
return DocumentTemplateBI.DocumentTemplateQRCodeLocationCache.GetLocations(dt, Database);
|
||||
}
|
||||
|
||||
public static void Delete(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
// Find & Rename all references
|
||||
|
||||
@@ -13,6 +13,7 @@ using Disco.Services.Plugins.Features.RepairProvider;
|
||||
|
||||
using PublishJobResult = Disco.Models.Services.Interop.DiscoServices.PublishJobResult;
|
||||
using DiscoServicesJobs = Disco.Services.Interop.DiscoServices.Jobs;
|
||||
using Disco.Services;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
@@ -176,7 +177,7 @@ namespace Disco.BI.Extensions
|
||||
null,
|
||||
FaultDescription,
|
||||
SendAttachments,
|
||||
Disco.BI.Extensions.AttachmentExtensions.RepositoryFilename);
|
||||
AttachmentDataStoreExtensions.RepositoryFilename);
|
||||
|
||||
if (!publishJobResult.Success)
|
||||
throw new Exception(string.Format("Disco ICT Online Services failed with the following message: ", publishJobResult.ErrorMessage));
|
||||
@@ -398,7 +399,7 @@ namespace Disco.BI.Extensions
|
||||
null,
|
||||
RepairDescription,
|
||||
SendAttachments,
|
||||
Disco.BI.Extensions.AttachmentExtensions.RepositoryFilename);
|
||||
AttachmentDataStoreExtensions.RepositoryFilename);
|
||||
|
||||
if (!publishJobResult.Success)
|
||||
throw new Exception(string.Format("Disco ICT Online Services failed with the following message: ", publishJobResult.ErrorMessage));
|
||||
|
||||
@@ -1,50 +1,18 @@
|
||||
using System;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Documents;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Plugins;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Data.Repository;
|
||||
using System.IO;
|
||||
using Disco.Models.BI.DocumentTemplates;
|
||||
using Disco.Services.Plugins;
|
||||
using Disco.Models.BI.Job;
|
||||
using Disco.Services.Authorization;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class JobExtensions
|
||||
{
|
||||
public static JobAttachment CreateAttachment(this Job Job, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase))
|
||||
MimeType = Interop.MimeTypes.ResolveMimeType(Filename);
|
||||
|
||||
JobAttachment ja = new JobAttachment()
|
||||
{
|
||||
JobId = Job.Id,
|
||||
TechUserId = CreatorUser.UserId,
|
||||
Filename = Filename,
|
||||
MimeType = MimeType,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = Comments
|
||||
};
|
||||
|
||||
if (DocumentTemplate != null)
|
||||
ja.DocumentTemplateId = DocumentTemplate.Id;
|
||||
|
||||
Database.JobAttachments.Add(ja);
|
||||
Database.SaveChanges();
|
||||
|
||||
ja.SaveAttachment(Database, Content);
|
||||
Content.Position = 0;
|
||||
if (PdfThumbnail == null)
|
||||
ja.GenerateThumbnail(Database, Content);
|
||||
else
|
||||
ja.SaveThumbnailAttachment(Database, PdfThumbnail);
|
||||
|
||||
return ja;
|
||||
}
|
||||
|
||||
public static List<DocumentTemplate> AvailableDocumentTemplates(this Job j, DiscoDataContext Database, User User, DateTime TimeStamp)
|
||||
{
|
||||
var dts = Database.DocumentTemplates.Include("JobSubTypes")
|
||||
|
||||
@@ -1,48 +1,15 @@
|
||||
using System;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Documents;
|
||||
using Disco.Services;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Data.Repository;
|
||||
using System.IO;
|
||||
using Disco.Models.BI.DocumentTemplates;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class UserExtensions
|
||||
{
|
||||
public static UserAttachment CreateAttachment(this User User, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase))
|
||||
MimeType = Interop.MimeTypes.ResolveMimeType(Filename);
|
||||
|
||||
UserAttachment ua = new UserAttachment()
|
||||
{
|
||||
UserId = User.UserId,
|
||||
TechUserId = CreatorUser.UserId,
|
||||
Filename = Filename,
|
||||
MimeType = MimeType,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = Comments
|
||||
};
|
||||
|
||||
if (DocumentTemplate != null)
|
||||
ua.DocumentTemplateId = DocumentTemplate.Id;
|
||||
|
||||
Database.UserAttachments.Add(ua);
|
||||
Database.SaveChanges();
|
||||
|
||||
ua.SaveAttachment(Database, Content);
|
||||
Content.Position = 0;
|
||||
if (PdfThumbnail == null)
|
||||
ua.GenerateThumbnail(Database, Content);
|
||||
else
|
||||
ua.SaveThumbnailAttachment(Database, PdfThumbnail);
|
||||
|
||||
return ua;
|
||||
}
|
||||
|
||||
public static List<DocumentTemplate> AvailableDocumentTemplates(this User u, DiscoDataContext Database, User User, DateTime TimeStamp)
|
||||
{
|
||||
var dts = Database.DocumentTemplates.Include("JobSubTypes")
|
||||
@@ -57,10 +24,6 @@ namespace Disco.BI.Extensions
|
||||
{
|
||||
return u.DeviceUserAssignments.Where(dua => !dua.UnassignedDate.HasValue).ToList();
|
||||
}
|
||||
public static ADUserAccount ActiveDirectoryAccount(this User User, params string[] AdditionalProperties)
|
||||
{
|
||||
return ActiveDirectory.RetrieveADUserAccount(User.UserId, AdditionalProperties);
|
||||
}
|
||||
|
||||
public static bool CanCreateJob(this User u)
|
||||
{
|
||||
|
||||
@@ -22,240 +22,6 @@ namespace Disco.BI.Extensions
|
||||
return sr.ReadToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
#region Image Extensions
|
||||
|
||||
public static Bitmap RotateImage(this Image Source, float Angle, Brush BackgroundColor = null, bool ResizeIfOver45Deg = true)
|
||||
{
|
||||
int destWidth = Source.Width;
|
||||
int destHeight = Source.Height;
|
||||
bool resizedDest = false;
|
||||
|
||||
if (ResizeIfOver45Deg && ((Angle > 45 && Angle < 135) || (Angle < -45 && Angle > -135)))
|
||||
{
|
||||
destWidth = Source.Height;
|
||||
destHeight = Source.Width;
|
||||
resizedDest = true;
|
||||
}
|
||||
|
||||
Bitmap destination = new Bitmap(destWidth, destHeight);
|
||||
destination.SetResolution(Source.HorizontalResolution, Source.VerticalResolution);
|
||||
|
||||
using (Graphics destinationGraphics = Graphics.FromImage(destination))
|
||||
{
|
||||
destinationGraphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
destinationGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
destinationGraphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
|
||||
if (BackgroundColor != null)
|
||||
destinationGraphics.FillRectangle(BackgroundColor, destinationGraphics.VisibleClipBounds);
|
||||
|
||||
float offsetWidth = destWidth / 2;
|
||||
float offsetHeight = destHeight / 2;
|
||||
|
||||
destinationGraphics.TranslateTransform(offsetWidth, offsetHeight);
|
||||
destinationGraphics.RotateTransform(Angle);
|
||||
|
||||
RectangleF destinationLocation;
|
||||
|
||||
if (resizedDest)
|
||||
destinationLocation = new RectangleF(
|
||||
offsetHeight * -1, offsetWidth * -1,
|
||||
destHeight, destWidth);
|
||||
else
|
||||
destinationLocation = new RectangleF(
|
||||
offsetWidth * -1, offsetHeight * -1,
|
||||
destWidth, destHeight);
|
||||
|
||||
destinationGraphics.DrawImage(Source, destinationLocation, new RectangleF(0, 0, Source.Width, Source.Height), GraphicsUnit.Pixel);
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
|
||||
public static Bitmap ResizeImage(this Image Source, int Width, int Height, Brush BackgroundColor = null)
|
||||
{
|
||||
Bitmap destination = new Bitmap(Width, Height);
|
||||
destination.SetResolution(72, 72);
|
||||
using (Graphics destinationGraphics = Graphics.FromImage(destination))
|
||||
{
|
||||
destinationGraphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
destinationGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
destinationGraphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
|
||||
if (BackgroundColor != null)
|
||||
destinationGraphics.FillRectangle(BackgroundColor, destinationGraphics.VisibleClipBounds);
|
||||
|
||||
float ratio = Math.Min((float)(destination.Width) / (float)(Source.Width), (float)(destination.Height) / (float)(Source.Height));
|
||||
|
||||
destinationGraphics.DrawImageResized(Source, ratio);
|
||||
}
|
||||
|
||||
return destination;
|
||||
}
|
||||
public static void DrawImageResized(this Graphics graphics, Image SourceImage, float? Scale = null, float LocationX = -1, float LocationY = -1)
|
||||
{
|
||||
RectangleF clipBounds = graphics.VisibleClipBounds;
|
||||
if (Scale == null) // Calculate Scale
|
||||
Scale = Math.Min(clipBounds.Width / SourceImage.Width, clipBounds.Height / SourceImage.Height);
|
||||
float newWidth = SourceImage.Width * Scale.Value;
|
||||
float newHeight = SourceImage.Height * Scale.Value;
|
||||
float newLeft = LocationX;
|
||||
float newTop = LocationY;
|
||||
|
||||
if (newLeft < 0 || newTop < 0)
|
||||
{
|
||||
if (newWidth < clipBounds.Width)
|
||||
newLeft = (clipBounds.Width - newWidth) / 2;
|
||||
else
|
||||
newLeft = 0;
|
||||
if (newHeight < clipBounds.Height)
|
||||
newTop = (clipBounds.Height - newHeight) / 2;
|
||||
else
|
||||
newTop = 0;
|
||||
}
|
||||
newLeft += clipBounds.Left;
|
||||
newTop += clipBounds.Top;
|
||||
|
||||
graphics.DrawImage(SourceImage, new RectangleF(newLeft, newTop, newWidth, newHeight), new RectangleF(0, 0, SourceImage.Width, SourceImage.Height), GraphicsUnit.Pixel);
|
||||
}
|
||||
public static void EmbedIconOverlay(this Image Source, Image Icon)
|
||||
{
|
||||
int top = Math.Max(0, Source.Height - Icon.Height);
|
||||
int left = Math.Max(0, Source.Width - Icon.Width);
|
||||
|
||||
using (Graphics sourceGraphics = Graphics.FromImage(Source))
|
||||
{
|
||||
sourceGraphics.DrawImage(Icon, left, top);
|
||||
}
|
||||
}
|
||||
public static void SavePng(this Image Source, string Filename)
|
||||
{
|
||||
using (FileStream outStream = new FileStream(Filename, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
SavePng(Source, outStream);
|
||||
outStream.Flush();
|
||||
outStream.Close();
|
||||
}
|
||||
}
|
||||
public static void SavePng(this Image Source, Stream OutStream)
|
||||
{
|
||||
Source.Save(OutStream, ImageFormat.Png);
|
||||
}
|
||||
public static Stream SavePng(this Image Source)
|
||||
{
|
||||
MemoryStream outStream = new MemoryStream();
|
||||
Source.SavePng(outStream);
|
||||
outStream.Position = 0;
|
||||
return outStream;
|
||||
}
|
||||
public static Stream SaveJpg(this Image Source, int Quality)
|
||||
{
|
||||
MemoryStream outStream = new MemoryStream();
|
||||
Source.SaveJpg(Quality, outStream);
|
||||
outStream.Position = 0;
|
||||
return outStream;
|
||||
}
|
||||
public static void SaveJpg(this Image Source, int Quality, string Filename)
|
||||
{
|
||||
using (FileStream outStream = new FileStream(Filename, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
SaveJpg(Source, Quality, outStream);
|
||||
outStream.Flush();
|
||||
outStream.Close();
|
||||
}
|
||||
}
|
||||
public static void SaveJpg(this Image Source, int Quality, Stream OutStream)
|
||||
{
|
||||
ImageCodecInfo jpgCodec = ImageCodecInfo.GetImageEncoders().Where(c => c.MimeType.Equals("image/jpeg", StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
|
||||
if (jpgCodec != null)
|
||||
{
|
||||
if (Quality < 0 || Quality > 100)
|
||||
throw new ArgumentOutOfRangeException("Quality", "Quality must be a positive integer <= 100");
|
||||
using (EncoderParameters ep = new EncoderParameters(1))
|
||||
{
|
||||
ep.Param[0] = new EncoderParameter(Encoder.Quality, Quality);
|
||||
Source.Save(OutStream, jpgCodec, ep);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback
|
||||
Source.Save(OutStream, ImageFormat.Jpeg);
|
||||
}
|
||||
}
|
||||
public static ImageMontage BuildImageMontage(this IEnumerable<Image> Images, int MaxHeight = -1, int MaxWidth = -1, bool EnforceDimensions = false)
|
||||
{
|
||||
if (EnforceDimensions && (MaxHeight < 0 || MaxWidth < 0))
|
||||
throw new ArgumentOutOfRangeException("EnforceDimensions", "Dimensions can only be enforced when a MaxHeight and MaxWidth is supplied");
|
||||
|
||||
Dictionary<Image, int> imageLocations = new Dictionary<Image, int>();
|
||||
double imageScale = 1.0;
|
||||
int totalHeight = Images.Max(i => i.Height);
|
||||
int totalWidth = Images.Sum(i => i.Width);
|
||||
if (MaxHeight > 0 && totalHeight > MaxHeight)
|
||||
{
|
||||
imageScale = (double)MaxHeight / (double)totalHeight;
|
||||
}
|
||||
if (MaxWidth > 0 && totalWidth > MaxWidth)
|
||||
{
|
||||
imageScale = System.Math.Min(imageScale, (double)MaxWidth / (double)totalWidth);
|
||||
}
|
||||
int scaledHeight = EnforceDimensions ? MaxHeight : (int)System.Math.Round((double)totalHeight * imageScale);
|
||||
int scaledWidth = EnforceDimensions ? MaxWidth : (int)System.Math.Round((double)totalWidth * imageScale);
|
||||
System.Drawing.Bitmap imageResult = new System.Drawing.Bitmap(scaledWidth, scaledHeight);
|
||||
imageResult.SetResolution(72f, 72f);
|
||||
|
||||
using (Graphics g = Graphics.FromImage(imageResult))
|
||||
{
|
||||
g.FillRectangle(Brushes.White, new Rectangle(Point.Empty, imageResult.Size));
|
||||
|
||||
int imageResultNextOffset = 0;
|
||||
foreach (Image i in Images)
|
||||
{
|
||||
Rectangle imagePosition = new Rectangle(imageResultNextOffset, 0, (int)System.Math.Round((double)i.Width * imageScale), (int)System.Math.Round((double)i.Height * imageScale));
|
||||
System.Drawing.Rectangle imageSize = new System.Drawing.Rectangle(0, 0, i.Width, i.Height);
|
||||
g.DrawImage(i, imagePosition, imageSize, System.Drawing.GraphicsUnit.Pixel);
|
||||
imageLocations[i] = imageResultNextOffset;
|
||||
imageResultNextOffset += imagePosition.Width;
|
||||
}
|
||||
}
|
||||
|
||||
return new ImageMontage() { Montage = imageResult, MontageScale = imageScale, MontageSourceImageOffsets = imageLocations };
|
||||
}
|
||||
public class ImageMontage : IDisposable
|
||||
{
|
||||
|
||||
public Image Montage { get; set; }
|
||||
public double MontageScale { get; set; }
|
||||
public Dictionary<Image, int> MontageSourceImageOffsets { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Montage != null)
|
||||
{
|
||||
Montage.Dispose();
|
||||
Montage = null;
|
||||
}
|
||||
if (MontageSourceImageOffsets != null)
|
||||
{
|
||||
MontageSourceImageOffsets.Clear();
|
||||
MontageSourceImageOffsets = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Color InterpolateColours(this Color Start, Color End, double Progress)
|
||||
{
|
||||
if (Progress > 1 || Progress < 0)
|
||||
throw new ArgumentOutOfRangeException("Progress", "Progress must be >= 0 && <= 1");
|
||||
|
||||
return Color.FromArgb(
|
||||
(byte)(Start.A * (1 - Progress) + (End.A * Progress)),
|
||||
(byte)(Start.R * (1 - Progress) + (End.R * Progress)),
|
||||
(byte)(Start.G * (1 - Progress) + (End.G * Progress)),
|
||||
(byte)(Start.B * (1 - Progress) + (End.B * Progress))
|
||||
);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user