mirror of
https://github.com/greenshot/greenshot
synced 2025-08-22 22:34:27 -07:00
Code Quality changes and dependency updates.
This commit is contained in:
parent
1a23227c68
commit
6b6bcb99bb
123 changed files with 3092 additions and 3781 deletions
|
@ -58,11 +58,11 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="!$(MSBuildProjectName.Contains('Tests')) And $(MSBuildProjectName.StartsWith('Greenshot'))">
|
<ItemGroup Condition="!$(MSBuildProjectName.Contains('Tests')) And $(MSBuildProjectName.StartsWith('Greenshot'))">
|
||||||
<PackageReference Include="Nerdbank.GitVersioning" Version="3.0.26">
|
<PackageReference Include="Nerdbank.GitVersioning" Version="3.0.28">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta2-19351-01" PrivateAssets="All"/>
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="PostBuild" BeforeTargets="PostBuildEvent" Condition="'$(BuildingInsideVisualStudio)' == 'true' And $(MSBuildProjectName.Contains('Addon.')) And !$(MSBuildProjectName.Contains('Test')) And !$(MSBuildProjectName.Contains('Demo'))">
|
<Target Name="PostBuild" BeforeTargets="PostBuildEvent" Condition="'$(BuildingInsideVisualStudio)' == 'true' And $(MSBuildProjectName.Contains('Addon.')) And !$(MSBuildProjectName.Contains('Test')) And !$(MSBuildProjectName.Contains('Demo'))">
|
||||||
|
|
|
@ -117,13 +117,11 @@ namespace Greenshot.Addon.Box
|
||||||
public override IBitmapWithNativeSupport DisplayIcon
|
public override IBitmapWithNativeSupport DisplayIcon
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
// TODO: Optimize this
|
// TODO: Optimize this
|
||||||
using (var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "box.png"))
|
using var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "box.png");
|
||||||
{
|
return BitmapHelper.FromStream(bitmapStream);
|
||||||
return BitmapHelper.FromStream(bitmapStream);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
@ -163,12 +161,10 @@ namespace Greenshot.Addon.Box
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url != null && _boxConfiguration.AfterUploadLinkToClipBoard)
|
if (url != null && _boxConfiguration.AfterUploadLinkToClipBoard)
|
||||||
{
|
{
|
||||||
using (var clipboardAccessToken = ClipboardNative.Access())
|
using var clipboardAccessToken = ClipboardNative.Access();
|
||||||
{
|
clipboardAccessToken.ClearContents();
|
||||||
clipboardAccessToken.ClearContents();
|
clipboardAccessToken.SetAsUrl(url);
|
||||||
clipboardAccessToken.SetAsUrl(url);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return url;
|
return url;
|
||||||
|
@ -206,58 +202,56 @@ namespace Greenshot.Addon.Box
|
||||||
oauthHttpBehaviour.OnHttpMessageHandlerCreated = httpMessageHandler => new OAuth2HttpMessageHandler(_oauth2Settings, oauthHttpBehaviour, httpMessageHandler);
|
oauthHttpBehaviour.OnHttpMessageHandlerCreated = httpMessageHandler => new OAuth2HttpMessageHandler(_oauth2Settings, oauthHttpBehaviour, httpMessageHandler);
|
||||||
|
|
||||||
// TODO: See if the PostAsync<Bitmap> can be used? Or at least the HttpContentFactory?
|
// TODO: See if the PostAsync<Bitmap> can be used? Or at least the HttpContentFactory?
|
||||||
using (var imageStream = new MemoryStream())
|
using var imageStream = new MemoryStream();
|
||||||
|
var multiPartContent = new MultipartFormDataContent();
|
||||||
|
var parentIdContent = new StringContent(_boxConfiguration.FolderId);
|
||||||
|
parentIdContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
|
||||||
{
|
{
|
||||||
var multiPartContent = new MultipartFormDataContent();
|
Name = "\"parent_id\""
|
||||||
var parentIdContent = new StringContent(_boxConfiguration.FolderId);
|
};
|
||||||
parentIdContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
|
multiPartContent.Add(parentIdContent);
|
||||||
|
surface.WriteToStream(imageStream, CoreConfiguration, _boxConfiguration);
|
||||||
|
imageStream.Position = 0;
|
||||||
|
|
||||||
|
BoxFile response;
|
||||||
|
using (var streamContent = new StreamContent(imageStream))
|
||||||
|
{
|
||||||
|
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); //"image/" + outputSettings.Format);
|
||||||
|
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
|
||||||
{
|
{
|
||||||
Name = "\"parent_id\""
|
Name = "\"file\"",
|
||||||
};
|
FileName = "\"" + filename + "\""
|
||||||
multiPartContent.Add(parentIdContent);
|
}; // the extra quotes are important here
|
||||||
surface.WriteToStream(imageStream, CoreConfiguration, _boxConfiguration);
|
multiPartContent.Add(streamContent);
|
||||||
imageStream.Position = 0;
|
|
||||||
|
|
||||||
BoxFile response;
|
oauthHttpBehaviour.MakeCurrent();
|
||||||
using (var streamContent = new StreamContent(imageStream))
|
response = await UploadFileUri.PostAsync<BoxFile>(multiPartContent, cancellationToken).ConfigureAwait(false);
|
||||||
{
|
|
||||||
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); //"image/" + outputSettings.Format);
|
|
||||||
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
|
|
||||||
{
|
|
||||||
Name = "\"file\"",
|
|
||||||
FileName = "\"" + filename + "\""
|
|
||||||
}; // the extra quotes are important here
|
|
||||||
multiPartContent.Add(streamContent);
|
|
||||||
|
|
||||||
oauthHttpBehaviour.MakeCurrent();
|
|
||||||
response = await UploadFileUri.PostAsync<BoxFile>(multiPartContent, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_boxConfiguration.UseSharedLink)
|
|
||||||
{
|
|
||||||
if (response.SharedLink?.Url == null)
|
|
||||||
{
|
|
||||||
var uriForSharedLink = FilesUri.AppendSegments(response.Id);
|
|
||||||
var updateAccess = new
|
|
||||||
{
|
|
||||||
shared_link = new
|
|
||||||
{
|
|
||||||
access = "open"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
oauthHttpBehaviour.MakeCurrent();
|
|
||||||
response = await uriForSharedLink.PostAsync<BoxFile>(updateAccess, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.SharedLink.Url;
|
|
||||||
}
|
|
||||||
return $"http://www.box.com/files/0/f/0/1/f_{response.Id}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (response == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_boxConfiguration.UseSharedLink)
|
||||||
|
{
|
||||||
|
if (response.SharedLink?.Url == null)
|
||||||
|
{
|
||||||
|
var uriForSharedLink = FilesUri.AppendSegments(response.Id);
|
||||||
|
var updateAccess = new
|
||||||
|
{
|
||||||
|
shared_link = new
|
||||||
|
{
|
||||||
|
access = "open"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
oauthHttpBehaviour.MakeCurrent();
|
||||||
|
response = await uriForSharedLink.PostAsync<BoxFile>(updateAccess, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.SharedLink.Url;
|
||||||
|
}
|
||||||
|
return $"http://www.box.com/files/0/f/0/1/f_{response.Id}";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,12 +123,10 @@ namespace Greenshot.Addon.Dropbox
|
||||||
public override IBitmapWithNativeSupport DisplayIcon
|
public override IBitmapWithNativeSupport DisplayIcon
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
// TODO: Optimize this by caching
|
// TODO: Optimize this by caching
|
||||||
using (var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "Dropbox.gif"))
|
using var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "Dropbox.gif");
|
||||||
{
|
return BitmapHelper.FromStream(bitmapStream);
|
||||||
return BitmapHelper.FromStream(bitmapStream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,12 +143,10 @@ namespace Greenshot.Addon.Dropbox
|
||||||
exportInformation.Uri = uploadUrl;
|
exportInformation.Uri = uploadUrl;
|
||||||
exportInformation.ExportMade = true;
|
exportInformation.ExportMade = true;
|
||||||
if (_dropboxPluginConfiguration.AfterUploadLinkToClipBoard)
|
if (_dropboxPluginConfiguration.AfterUploadLinkToClipBoard)
|
||||||
{
|
{
|
||||||
using (var clipboardAccessToken = ClipboardNative.Access())
|
using var clipboardAccessToken = ClipboardNative.Access();
|
||||||
{
|
clipboardAccessToken.ClearContents();
|
||||||
clipboardAccessToken.ClearContents();
|
clipboardAccessToken.SetAsUrl(uploadUrl);
|
||||||
clipboardAccessToken.SetAsUrl(uploadUrl);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_exportNotification.NotifyOfExport(this, exportInformation, surface);
|
_exportNotification.NotifyOfExport(this, exportInformation, surface);
|
||||||
|
@ -166,30 +162,24 @@ namespace Greenshot.Addon.Dropbox
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var cancellationTokenSource = new CancellationTokenSource();
|
var cancellationTokenSource = new CancellationTokenSource();
|
||||||
using (var ownedPleaseWaitForm = _pleaseWaitFormFactory(cancellationTokenSource))
|
using var ownedPleaseWaitForm = _pleaseWaitFormFactory(cancellationTokenSource);
|
||||||
{
|
ownedPleaseWaitForm.Value.SetDetails("Dropbox", _dropboxLanguage.CommunicationWait);
|
||||||
ownedPleaseWaitForm.Value.SetDetails("Dropbox", _dropboxLanguage.CommunicationWait);
|
ownedPleaseWaitForm.Value.Show();
|
||||||
ownedPleaseWaitForm.Value.Show();
|
try
|
||||||
try
|
{
|
||||||
{
|
var filename = surfaceToUpload.GenerateFilename(CoreConfiguration, _dropboxPluginConfiguration);
|
||||||
var filename = surfaceToUpload.GenerateFilename(CoreConfiguration, _dropboxPluginConfiguration);
|
using var imageStream = new MemoryStream();
|
||||||
using (var imageStream = new MemoryStream())
|
surfaceToUpload.WriteToStream(imageStream, CoreConfiguration, _dropboxPluginConfiguration);
|
||||||
{
|
imageStream.Position = 0;
|
||||||
surfaceToUpload.WriteToStream(imageStream, CoreConfiguration, _dropboxPluginConfiguration);
|
using var streamContent = new StreamContent(imageStream);
|
||||||
imageStream.Position = 0;
|
streamContent.Headers.ContentType = new MediaTypeHeaderValue(surfaceToUpload.GenerateMimeType(CoreConfiguration, _dropboxPluginConfiguration));
|
||||||
using (var streamContent = new StreamContent(imageStream))
|
dropboxUrl = await UploadAsync(filename, streamContent, null, cancellationToken).ConfigureAwait(false);
|
||||||
{
|
}
|
||||||
streamContent.Headers.ContentType = new MediaTypeHeaderValue(surfaceToUpload.GenerateMimeType(CoreConfiguration, _dropboxPluginConfiguration));
|
finally
|
||||||
dropboxUrl = await UploadAsync(filename, streamContent, null, cancellationToken).ConfigureAwait(false);
|
{
|
||||||
}
|
ownedPleaseWaitForm.Value.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
ownedPleaseWaitForm.Value.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Log.Error().WriteLine(e);
|
Log.Error().WriteLine(e);
|
||||||
|
|
|
@ -89,12 +89,10 @@ namespace Greenshot.Addon.ExternalCommand
|
||||||
{
|
{
|
||||||
exportInformation.Uri = uriMatches[0].Groups[1].Value;
|
exportInformation.Uri = uriMatches[0].Groups[1].Value;
|
||||||
|
|
||||||
using (var clipboardAccessToken = ClipboardNative.Access())
|
using var clipboardAccessToken = ClipboardNative.Access();
|
||||||
{
|
clipboardAccessToken.ClearContents();
|
||||||
clipboardAccessToken.ClearContents();
|
clipboardAccessToken.SetAsUrl(exportInformation.Uri);
|
||||||
clipboardAccessToken.SetAsUrl(exportInformation.Uri);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_externalCommandDefinition.CommandBehavior.HasFlag(CommandBehaviors.DeleteOnExit))
|
if (_externalCommandDefinition.CommandBehavior.HasFlag(CommandBehaviors.DeleteOnExit))
|
||||||
|
|
|
@ -19,6 +19,6 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CliWrap" Version="2.4.0" />
|
<PackageReference Include="CliWrap" Version="2.5.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -123,12 +123,10 @@ namespace Greenshot.Addon.Flickr
|
||||||
public override IBitmapWithNativeSupport DisplayIcon
|
public override IBitmapWithNativeSupport DisplayIcon
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
// TODO: Optimize this by caching
|
// TODO: Optimize this by caching
|
||||||
using (var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "flickr.png"))
|
using var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "flickr.png");
|
||||||
{
|
return BitmapHelper.FromStream(bitmapStream);
|
||||||
return BitmapHelper.FromStream(bitmapStream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,12 +172,10 @@ namespace Greenshot.Addon.Flickr
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (_flickrConfiguration.AfterUploadLinkToClipBoard)
|
if (_flickrConfiguration.AfterUploadLinkToClipBoard)
|
||||||
{
|
{
|
||||||
using (var clipboardAccessToken = ClipboardNative.Access())
|
using var clipboardAccessToken = ClipboardNative.Access();
|
||||||
{
|
clipboardAccessToken.ClearContents();
|
||||||
clipboardAccessToken.ClearContents();
|
clipboardAccessToken.SetAsUrl(uploadUrl);
|
||||||
clipboardAccessToken.SetAsUrl(uploadUrl);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -222,23 +218,21 @@ namespace Greenshot.Addon.Flickr
|
||||||
{
|
{
|
||||||
surfaceToUpload.WriteToStream(stream, CoreConfiguration, _flickrConfiguration);
|
surfaceToUpload.WriteToStream(stream, CoreConfiguration, _flickrConfiguration);
|
||||||
stream.Position = 0;
|
stream.Position = 0;
|
||||||
using (var streamContent = new StreamContent(stream))
|
using var streamContent = new StreamContent(stream);
|
||||||
|
streamContent.Headers.ContentType = new MediaTypeHeaderValue(surfaceToUpload.GenerateMimeType(CoreConfiguration, _flickrConfiguration));
|
||||||
|
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
|
||||||
{
|
{
|
||||||
streamContent.Headers.ContentType = new MediaTypeHeaderValue(surfaceToUpload.GenerateMimeType(CoreConfiguration, _flickrConfiguration));
|
Name = "\"photo\"",
|
||||||
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
|
FileName = "\"" + filename + "\""
|
||||||
{
|
};
|
||||||
Name = "\"photo\"",
|
HttpBehaviour.Current.SetConfig(new HttpRequestMessageConfiguration
|
||||||
FileName = "\"" + filename + "\""
|
{
|
||||||
};
|
Properties = signedParameters
|
||||||
HttpBehaviour.Current.SetConfig(new HttpRequestMessageConfiguration
|
});
|
||||||
{
|
var response = await FlickrUploadUri.PostAsync<XDocument>(streamContent, token).ConfigureAwait(false);
|
||||||
Properties = signedParameters
|
photoId = (from element in response?.Root?.Elements() ?? Enumerable.Empty<XElement>()
|
||||||
});
|
where element.Name == "photoid"
|
||||||
var response = await FlickrUploadUri.PostAsync<XDocument>(streamContent, token).ConfigureAwait(false);
|
select element.Value).FirstOrDefault();
|
||||||
photoId = (from element in response?.Root?.Elements() ?? Enumerable.Empty<XElement>()
|
|
||||||
where element.Name == "photoid"
|
|
||||||
select element.Value).FirstOrDefault();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Photo Info
|
// Get Photo Info
|
||||||
|
|
|
@ -101,13 +101,11 @@ namespace Greenshot.Addon.GooglePhotos
|
||||||
public override IBitmapWithNativeSupport DisplayIcon
|
public override IBitmapWithNativeSupport DisplayIcon
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
// TODO: Optimize this by caching
|
// TODO: Optimize this by caching
|
||||||
using (var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "GooglePhotos.png"))
|
using var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "GooglePhotos.png");
|
||||||
{
|
return BitmapHelper.FromStream(bitmapStream);
|
||||||
return BitmapHelper.FromStream(bitmapStream);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
@ -144,12 +142,10 @@ namespace Greenshot.Addon.GooglePhotos
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url != null && _googlePhotosConfiguration.AfterUploadLinkToClipBoard)
|
if (url != null && _googlePhotosConfiguration.AfterUploadLinkToClipBoard)
|
||||||
{
|
{
|
||||||
using (var clipboardAccessToken = ClipboardNative.Access())
|
using var clipboardAccessToken = ClipboardNative.Access();
|
||||||
{
|
clipboardAccessToken.ClearContents();
|
||||||
clipboardAccessToken.ClearContents();
|
clipboardAccessToken.SetAsUrl(url);
|
||||||
clipboardAccessToken.SetAsUrl(url);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
@ -191,13 +187,11 @@ namespace Greenshot.Addon.GooglePhotos
|
||||||
{
|
{
|
||||||
surface.WriteToStream(imageStream, CoreConfiguration, _googlePhotosConfiguration);
|
surface.WriteToStream(imageStream, CoreConfiguration, _googlePhotosConfiguration);
|
||||||
imageStream.Position = 0;
|
imageStream.Position = 0;
|
||||||
using (var content = new StreamContent(imageStream))
|
using var content = new StreamContent(imageStream);
|
||||||
{
|
content.Headers.Add("Content-Type", surface.GenerateMimeType(CoreConfiguration, _googlePhotosConfiguration));
|
||||||
content.Headers.Add("Content-Type", surface.GenerateMimeType(CoreConfiguration, _googlePhotosConfiguration));
|
|
||||||
|
|
||||||
oAuthHttpBehaviour.MakeCurrent();
|
oAuthHttpBehaviour.MakeCurrent();
|
||||||
response = await uploadUri.PostAsync<string>(content, token).ConfigureAwait(true);
|
response = await uploadUri.PostAsync<string>(content, token).ConfigureAwait(true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ParseResponse(response);
|
return ParseResponse(response);
|
||||||
|
|
|
@ -104,17 +104,13 @@ namespace Greenshot.Addon.Imgur
|
||||||
localBehaviour.UploadProgress = percent => Execute.OnUIThread(() => progress.Report((int)(percent * 100)));
|
localBehaviour.UploadProgress = percent => Execute.OnUIThread(() => progress.Report((int)(percent * 100)));
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var imageStream = new MemoryStream())
|
using var imageStream = new MemoryStream();
|
||||||
{
|
surfaceToUpload.WriteToStream(imageStream, _coreConfiguration, _imgurConfiguration);
|
||||||
surfaceToUpload.WriteToStream(imageStream, _coreConfiguration, _imgurConfiguration);
|
imageStream.Position = 0;
|
||||||
imageStream.Position = 0;
|
using var content = new StreamContent(imageStream);
|
||||||
using (var content = new StreamContent(imageStream))
|
content.Headers.Add("Content-Type", surfaceToUpload.GenerateMimeType(_coreConfiguration, _imgurConfiguration));
|
||||||
{
|
localBehaviour.MakeCurrent();
|
||||||
content.Headers.Add("Content-Type", surfaceToUpload.GenerateMimeType(_coreConfiguration, _imgurConfiguration));
|
return await uploadUri.PostAsync<ImgurImage>(content, token).ConfigureAwait(false);
|
||||||
localBehaviour.MakeCurrent();
|
|
||||||
return await uploadUri.PostAsync<ImgurImage>(content, token).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -135,17 +131,13 @@ namespace Greenshot.Addon.Imgur
|
||||||
localBehaviour.UploadProgress = percent => Execute.OnUIThread(() => progress.Report((int) (percent * 100)));
|
localBehaviour.UploadProgress = percent => Execute.OnUIThread(() => progress.Report((int) (percent * 100)));
|
||||||
}
|
}
|
||||||
var oauthHttpBehaviour = OAuth2HttpBehaviourFactory.Create(oAuth2Settings, localBehaviour);
|
var oauthHttpBehaviour = OAuth2HttpBehaviourFactory.Create(oAuth2Settings, localBehaviour);
|
||||||
using (var imageStream = new MemoryStream())
|
using var imageStream = new MemoryStream();
|
||||||
{
|
surfaceToUpload.WriteToStream(imageStream, _coreConfiguration, _imgurConfiguration);
|
||||||
surfaceToUpload.WriteToStream(imageStream, _coreConfiguration, _imgurConfiguration);
|
imageStream.Position = 0;
|
||||||
imageStream.Position = 0;
|
using var content = new StreamContent(imageStream);
|
||||||
using (var content = new StreamContent(imageStream))
|
content.Headers.Add("Content-Type", surfaceToUpload.GenerateMimeType(_coreConfiguration, _imgurConfiguration));
|
||||||
{
|
oauthHttpBehaviour.MakeCurrent();
|
||||||
content.Headers.Add("Content-Type", surfaceToUpload.GenerateMimeType(_coreConfiguration, _imgurConfiguration));
|
return await uploadUri.PostAsync<ImgurImage>(content, token).ConfigureAwait(false);
|
||||||
oauthHttpBehaviour.MakeCurrent();
|
|
||||||
return await uploadUri.PostAsync<ImgurImage>(content, token).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -187,27 +179,25 @@ namespace Greenshot.Addon.Imgur
|
||||||
{
|
{
|
||||||
var creditsUri = new Uri($"{_imgurConfiguration.ApiUrl}/credits.json");
|
var creditsUri = new Uri($"{_imgurConfiguration.ApiUrl}/credits.json");
|
||||||
Behaviour.MakeCurrent();
|
Behaviour.MakeCurrent();
|
||||||
using (var client = HttpClientFactory.Create(creditsUri))
|
using var client = HttpClientFactory.Create(creditsUri);
|
||||||
|
var response = await client.GetAsync(creditsUri, token).ConfigureAwait(false);
|
||||||
|
await response.HandleErrorAsync().ConfigureAwait(false);
|
||||||
|
var creditsJson = await response.GetAsAsync<dynamic>(token).ConfigureAwait(false);
|
||||||
|
if ((creditsJson != null) && creditsJson.ContainsKey("data"))
|
||||||
{
|
{
|
||||||
var response = await client.GetAsync(creditsUri, token).ConfigureAwait(false);
|
dynamic data = creditsJson.data;
|
||||||
await response.HandleErrorAsync().ConfigureAwait(false);
|
int credits = 0;
|
||||||
var creditsJson = await response.GetAsAsync<dynamic>(token).ConfigureAwait(false);
|
if (data.ContainsKey("ClientRemaining"))
|
||||||
if ((creditsJson != null) && creditsJson.ContainsKey("data"))
|
|
||||||
{
|
{
|
||||||
dynamic data = creditsJson.data;
|
credits = (int)data.ClientRemaining;
|
||||||
int credits = 0;
|
Log.Debug().WriteLine("{0}={1}", "ClientRemaining", (int)data.ClientRemaining);
|
||||||
if (data.ContainsKey("ClientRemaining"))
|
|
||||||
{
|
|
||||||
credits = (int)data.ClientRemaining;
|
|
||||||
Log.Debug().WriteLine("{0}={1}", "ClientRemaining", (int)data.ClientRemaining);
|
|
||||||
}
|
|
||||||
if (data.ContainsKey("UserRemaining"))
|
|
||||||
{
|
|
||||||
credits = Math.Min(credits, (int)data.UserRemaining);
|
|
||||||
Log.Debug().WriteLine("{0}={1}", "UserRemaining", (int)data.UserRemaining);
|
|
||||||
}
|
|
||||||
_imgurConfiguration.Credits = credits;
|
|
||||||
}
|
}
|
||||||
|
if (data.ContainsKey("UserRemaining"))
|
||||||
|
{
|
||||||
|
credits = Math.Min(credits, (int)data.UserRemaining);
|
||||||
|
Log.Debug().WriteLine("{0}={1}", "UserRemaining", (int)data.UserRemaining);
|
||||||
|
}
|
||||||
|
_imgurConfiguration.Credits = credits;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,17 +214,15 @@ namespace Greenshot.Addon.Imgur
|
||||||
Log.Debug().WriteLine("Retrieving Imgur info for {0} with url {1}", id, imageUri);
|
Log.Debug().WriteLine("Retrieving Imgur info for {0} with url {1}", id, imageUri);
|
||||||
|
|
||||||
Behaviour.MakeCurrent();
|
Behaviour.MakeCurrent();
|
||||||
using (var client = HttpClientFactory.Create(imageUri))
|
using var client = HttpClientFactory.Create(imageUri);
|
||||||
|
var response = await client.GetAsync(imageUri, token).ConfigureAwait(false);
|
||||||
|
// retrieving image data seems to throw a 403 (Unauthorized) if it has been deleted
|
||||||
|
if ((response.StatusCode == HttpStatusCode.NotFound) || (response.StatusCode == HttpStatusCode.Redirect) || (response.StatusCode == HttpStatusCode.Unauthorized))
|
||||||
{
|
{
|
||||||
var response = await client.GetAsync(imageUri, token).ConfigureAwait(false);
|
return null;
|
||||||
// retrieving image data seems to throw a 403 (Unauthorized) if it has been deleted
|
|
||||||
if ((response.StatusCode == HttpStatusCode.NotFound) || (response.StatusCode == HttpStatusCode.Redirect) || (response.StatusCode == HttpStatusCode.Unauthorized))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
await response.HandleErrorAsync().ConfigureAwait(false);
|
|
||||||
return await response.GetAsAsync<ImgurImage>(token).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
|
await response.HandleErrorAsync().ConfigureAwait(false);
|
||||||
|
return await response.GetAsAsync<ImgurImage>(token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -81,12 +81,10 @@ namespace Greenshot.Addon.Imgur
|
||||||
public override IBitmapWithNativeSupport DisplayIcon
|
public override IBitmapWithNativeSupport DisplayIcon
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
// TODO: Optimize this, by caching
|
// TODO: Optimize this, by caching
|
||||||
using (var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "Imgur.png"))
|
using var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "Imgur.png");
|
||||||
{
|
return BitmapHelper.FromStream(bitmapStream);
|
||||||
return BitmapHelper.FromStream(bitmapStream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,10 +126,11 @@ namespace Greenshot.Addon.Imgur
|
||||||
{
|
{
|
||||||
// Create thumbnail
|
// Create thumbnail
|
||||||
using (var tmpImage = surfaceToUpload.GetBitmapForExport())
|
using (var tmpImage = surfaceToUpload.GetBitmapForExport())
|
||||||
using (var thumbnail = tmpImage.CreateThumbnail(90, 90))
|
|
||||||
{
|
{
|
||||||
|
using var thumbnail = tmpImage.CreateThumbnail(90, 90);
|
||||||
imgurImage.Image = thumbnail;
|
imgurImage.Image = thumbnail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_imgurConfiguration.AnonymousAccess && _imgurConfiguration.TrackHistory)
|
if (_imgurConfiguration.AnonymousAccess && _imgurConfiguration.TrackHistory)
|
||||||
{
|
{
|
||||||
Log.Debug().WriteLine("Storing imgur upload for hash {0} and delete hash {1}", imgurImage.Data.Id, imgurImage.Data.Deletehash);
|
Log.Debug().WriteLine("Storing imgur upload for hash {0} and delete hash {1}", imgurImage.Data.Id, imgurImage.Data.Deletehash);
|
||||||
|
@ -159,11 +158,9 @@ namespace Greenshot.Addon.Imgur
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var clipboardAccessToken = ClipboardNative.Access())
|
using var clipboardAccessToken = ClipboardNative.Access();
|
||||||
{
|
clipboardAccessToken.ClearContents();
|
||||||
clipboardAccessToken.ClearContents();
|
clipboardAccessToken.SetAsUrl(uploadUrl.AbsoluteUri);
|
||||||
clipboardAccessToken.SetAsUrl(uploadUrl.AbsoluteUri);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
@ -120,10 +120,8 @@ namespace Greenshot.Addon.Imgur.ViewModels
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void ShowHistory()
|
public void ShowHistory()
|
||||||
{
|
{
|
||||||
using (var imgurHistoryViewModel = ImgurHistoryViewModelFactory())
|
using var imgurHistoryViewModel = ImgurHistoryViewModelFactory();
|
||||||
{
|
WindowManager.ShowDialog(imgurHistoryViewModel.Value);
|
||||||
WindowManager.ShowDialog(imgurHistoryViewModel.Value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -177,11 +177,9 @@ namespace Greenshot.Addon.Imgur.ViewModels
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void CopyToClipboard()
|
public void CopyToClipboard()
|
||||||
{
|
{
|
||||||
using (var clipboardAccessToken = ClipboardNative.Access())
|
using var clipboardAccessToken = ClipboardNative.Access();
|
||||||
{
|
clipboardAccessToken.ClearContents();
|
||||||
clipboardAccessToken.ClearContents();
|
clipboardAccessToken.SetAsUrl(SelectedImgur.Data.Link?.AbsoluteUri);
|
||||||
clipboardAccessToken.SetAsUrl(SelectedImgur.Data.Link?.AbsoluteUri);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -392,7 +392,7 @@ namespace Greenshot.Addon.InternetExplorer
|
||||||
windowToCapture = InteropWindowQuery.GetForegroundWindow();
|
windowToCapture = InteropWindowQuery.GetForegroundWindow();
|
||||||
}
|
}
|
||||||
// Show backgroundform after retrieving the active window..
|
// Show backgroundform after retrieving the active window..
|
||||||
var backgroundForm = new BackgroundForm("Internet Explorer", "Please wait while the page in Internet Explorer is captured...");
|
using var backgroundForm = new BackgroundForm("Internet Explorer", "Please wait while the page in Internet Explorer is captured...");
|
||||||
backgroundForm.Show();
|
backgroundForm.Show();
|
||||||
//BackgroundForm backgroundForm = BackgroundForm.ShowAndWait(language.GetString(LangKey.contextmenu_captureie), language.GetString(LangKey.wait_ie_capture));
|
//BackgroundForm backgroundForm = BackgroundForm.ShowAndWait(language.GetString(LangKey.contextmenu_captureie), language.GetString(LangKey.wait_ie_capture));
|
||||||
try
|
try
|
||||||
|
@ -658,12 +658,10 @@ namespace Greenshot.Addon.InternetExplorer
|
||||||
|
|
||||||
// Loop over the frames and clear their source area so we don't see any artifacts
|
// Loop over the frames and clear their source area so we don't see any artifacts
|
||||||
foreach (var frameDocument in documentContainer.Frames)
|
foreach (var frameDocument in documentContainer.Frames)
|
||||||
{
|
{
|
||||||
using (var brush = new SolidBrush(clearColor))
|
using var brush = new SolidBrush(clearColor);
|
||||||
{
|
graphicsTarget.FillRectangle(brush, frameDocument.SourceRectangle);
|
||||||
graphicsTarget.FillRectangle(brush, frameDocument.SourceRectangle);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
// Loop over the frames and capture their content
|
// Loop over the frames and capture their content
|
||||||
foreach (var frameDocument in documentContainer.Frames)
|
foreach (var frameDocument in documentContainer.Frames)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Dapplo.Log;
|
|
||||||
using Dapplo.Windows.Desktop;
|
using Dapplo.Windows.Desktop;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
@ -31,8 +30,6 @@ namespace Greenshot.Addon.InternetExplorer {
|
||||||
/// Util code for Internet Explorer
|
/// Util code for Internet Explorer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class InternetExplorerHelper {
|
public class InternetExplorerHelper {
|
||||||
private static readonly LogSource Log = new LogSource();
|
|
||||||
|
|
||||||
// Internet explorer Registry key
|
// Internet explorer Registry key
|
||||||
private const string IeKey = @"Software\Microsoft\Internet Explorer";
|
private const string IeKey = @"Software\Microsoft\Internet Explorer";
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,6 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Dapplo.Jira" Version="0.9.2" />
|
<PackageReference Include="Dapplo.Jira" Version="0.9.2" />
|
||||||
<PackageReference Include="DynamicData" Version="6.13.13" />
|
<PackageReference Include="DynamicData" Version="6.14.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -91,7 +91,11 @@ namespace Greenshot.Addon.Jira
|
||||||
{
|
{
|
||||||
if (_jiraClient != null)
|
if (_jiraClient != null)
|
||||||
{
|
{
|
||||||
Task.Run(async () => await LogoutAsync()).Wait();
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await LogoutAsync();
|
||||||
|
_issueTypeBitmapCache.Dispose();
|
||||||
|
}).Wait();
|
||||||
}
|
}
|
||||||
FavIcon?.Dispose();
|
FavIcon?.Dispose();
|
||||||
}
|
}
|
||||||
|
@ -251,14 +255,12 @@ namespace Greenshot.Addon.Jira
|
||||||
public async Task AttachAsync(string issueKey, ISurface surface, string filename = null, CancellationToken cancellationToken = default)
|
public async Task AttachAsync(string issueKey, ISurface surface, string filename = null, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
await CheckCredentialsAsync(cancellationToken).ConfigureAwait(true);
|
await CheckCredentialsAsync(cancellationToken).ConfigureAwait(true);
|
||||||
using (var memoryStream = new MemoryStream())
|
using var memoryStream = new MemoryStream();
|
||||||
{
|
surface.WriteToStream(memoryStream, _coreConfiguration, _jiraConfiguration);
|
||||||
surface.WriteToStream(memoryStream, _coreConfiguration, _jiraConfiguration);
|
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
var contentType = surface.GenerateMimeType(_coreConfiguration, _jiraConfiguration);
|
||||||
var contentType = surface.GenerateMimeType(_coreConfiguration, _jiraConfiguration);
|
await _jiraClient.Attachment.AttachAsync(issueKey, memoryStream, filename ?? surface.GenerateFilename(_coreConfiguration, _jiraConfiguration), contentType, cancellationToken).ConfigureAwait(false);
|
||||||
await _jiraClient.Attachment.AttachAsync(issueKey, memoryStream, filename ?? surface.GenerateFilename(_coreConfiguration, _jiraConfiguration), contentType, cancellationToken).ConfigureAwait(false);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add a comment to the supplied issue
|
/// Add a comment to the supplied issue
|
||||||
|
|
|
@ -136,16 +136,12 @@ namespace Greenshot.Addon.Jira
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (displayIcon == null)
|
if (displayIcon == null)
|
||||||
{
|
{
|
||||||
using (var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "jira.svgz"))
|
using var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "jira.svgz");
|
||||||
{
|
using var gzStream = new GZipStream(bitmapStream, CompressionMode.Decompress);
|
||||||
using (var gzStream = new GZipStream(bitmapStream, CompressionMode.Decompress))
|
displayIcon = SvgBitmap.FromStream(gzStream);
|
||||||
{
|
//displayIcon = BitmapHelper.FromStream(bitmapStream);
|
||||||
displayIcon = SvgBitmap.FromStream(gzStream);
|
}
|
||||||
}
|
|
||||||
//displayIcon = BitmapHelper.FromStream(bitmapStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return displayIcon;
|
return displayIcon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,43 +188,41 @@ namespace Greenshot.Addon.Jira
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO: set filename
|
// TODO: set filename
|
||||||
// _jiraViewModel.SetFilename(filename);
|
// _jiraViewModel.SetFilename(filename);
|
||||||
using (var jiraViewModel = _jiraViewModelFactory())
|
using var jiraViewModel = _jiraViewModelFactory();
|
||||||
{
|
if (_windowManager.ShowDialog(jiraViewModel.Value) == true)
|
||||||
if (_windowManager.ShowDialog(jiraViewModel.Value) == true)
|
{
|
||||||
{
|
try
|
||||||
try
|
{
|
||||||
{
|
surface.UploadUrl = _jiraConnector.JiraBaseUri.AppendSegments("browse", jiraViewModel.Value.JiraIssue.Key).AbsoluteUri;
|
||||||
surface.UploadUrl = _jiraConnector.JiraBaseUri.AppendSegments("browse", jiraViewModel.Value.JiraIssue.Key).AbsoluteUri;
|
// Run upload in the background
|
||||||
// Run upload in the background
|
using (var ownedPleaseWaitForm = _pleaseWaitFormFactory())
|
||||||
using (var ownedPleaseWaitForm = _pleaseWaitFormFactory())
|
{
|
||||||
{
|
ownedPleaseWaitForm.Value.ShowAndWait(Description, _jiraLanguage.CommunicationWait,
|
||||||
ownedPleaseWaitForm.Value.ShowAndWait(Description, _jiraLanguage.CommunicationWait,
|
async () =>
|
||||||
async () =>
|
{
|
||||||
{
|
await _jiraConnector.AttachAsync(jiraViewModel.Value.JiraIssue.Key, surface,
|
||||||
await _jiraConnector.AttachAsync(jiraViewModel.Value.JiraIssue.Key, surface,
|
jiraViewModel.Value.Filename).ConfigureAwait(true);
|
||||||
jiraViewModel.Value.Filename).ConfigureAwait(true);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(jiraViewModel.Value.Comment))
|
if (!string.IsNullOrEmpty(jiraViewModel.Value.Comment))
|
||||||
{
|
{
|
||||||
await _jiraConnector.AddCommentAsync(jiraViewModel.Value.JiraIssue.Key,
|
await _jiraConnector.AddCommentAsync(jiraViewModel.Value.JiraIssue.Key,
|
||||||
jiraViewModel.Value.Comment).ConfigureAwait(true);
|
jiraViewModel.Value.Comment).ConfigureAwait(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Debug().WriteLine("Uploaded to Jira {0}", jiraViewModel.Value.JiraIssue.Key);
|
Log.Debug().WriteLine("Uploaded to Jira {0}", jiraViewModel.Value.JiraIssue.Key);
|
||||||
exportInformation.ExportMade = true;
|
exportInformation.ExportMade = true;
|
||||||
exportInformation.Uri = surface.UploadUrl;
|
exportInformation.Uri = surface.UploadUrl;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MessageBox.Show(_jiraLanguage.UploadFailure + " " + e.Message);
|
MessageBox.Show(_jiraLanguage.UploadFailure + " " + e.Message);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_exportNotification.NotifyOfExport(this, exportInformation, surface);
|
_exportNotification.NotifyOfExport(this, exportInformation, surface);
|
||||||
|
|
|
@ -52,19 +52,15 @@ namespace Greenshot.Addon.LegacyEditor.Controls
|
||||||
_selectedColor = value;
|
_selectedColor = value;
|
||||||
|
|
||||||
if (Image != null)
|
if (Image != null)
|
||||||
{
|
{
|
||||||
using (var brush = value != Color.Transparent ? new SolidBrush(value) : (Brush) new HatchBrush(HatchStyle.Percent50, Color.White, Color.Gray))
|
using var brush = value != Color.Transparent ? new SolidBrush(value) : (Brush) new HatchBrush(HatchStyle.Percent50, Color.White, Color.Gray);
|
||||||
{
|
using var graphics = Graphics.FromImage(Image);
|
||||||
using (var graphics = Graphics.FromImage(Image))
|
int verticalOffset = Image.Height / 3;
|
||||||
{
|
int horizontalOffset = (Image.Width / 3) / 2;
|
||||||
int verticalOffset = Image.Height / 3;
|
int width = Image.Width - (Image.Width / 3);
|
||||||
int horizontalOffset = (Image.Width / 3) / 2;
|
int height = (Image.Height / 3) / 2;
|
||||||
int width = Image.Width - (Image.Width / 3);
|
graphics.FillRectangle(brush, new Rectangle(horizontalOffset, verticalOffset, width, height));
|
||||||
int height = (Image.Height / 3) / 2;
|
}
|
||||||
graphics.FillRectangle(brush, new Rectangle(horizontalOffset, verticalOffset, width, height));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Invalidate();
|
Invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,24 +73,22 @@ namespace Greenshot.Addon.LegacyEditor.Controls
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
private void ColorButtonClick(object sender, EventArgs e)
|
private void ColorButtonClick(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
using (var ownedColorDialog = _colorDialogFactory())
|
using var ownedColorDialog = _colorDialogFactory();
|
||||||
|
var colorDialog = ownedColorDialog.Value;
|
||||||
|
colorDialog.Color = SelectedColor;
|
||||||
|
// Using the parent to make sure the dialog doesn't show on another window
|
||||||
|
colorDialog.ShowDialog(Parent.Parent);
|
||||||
|
if (colorDialog.DialogResult == DialogResult.Cancel)
|
||||||
{
|
{
|
||||||
var colorDialog = ownedColorDialog.Value;
|
return;
|
||||||
colorDialog.Color = SelectedColor;
|
|
||||||
// Using the parent to make sure the dialog doesn't show on another window
|
|
||||||
colorDialog.ShowDialog(Parent.Parent);
|
|
||||||
if (colorDialog.DialogResult == DialogResult.Cancel)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (colorDialog.Color.Equals(SelectedColor))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SelectedColor = colorDialog.Color;
|
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedColor"));
|
|
||||||
}
|
}
|
||||||
}
|
if (colorDialog.Color.Equals(SelectedColor))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SelectedColor = colorDialog.Color;
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedColor"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -39,7 +39,8 @@ namespace Greenshot.Addon.LegacyEditor.Controls {
|
||||||
if (components != null) {
|
if (components != null) {
|
||||||
components.Dispose();
|
components.Dispose();
|
||||||
}
|
}
|
||||||
}
|
_toolTip.Dispose();
|
||||||
|
}
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,52 +51,42 @@ namespace Greenshot.Addon.LegacyEditor.Controls
|
||||||
}
|
}
|
||||||
var graphics = e.Graphics;
|
var graphics = e.Graphics;
|
||||||
var dropDownRect = e.ArrowRectangle;
|
var dropDownRect = e.ArrowRectangle;
|
||||||
using (var brush = new SolidBrush(e.ArrowColor))
|
using var brush = new SolidBrush(e.ArrowColor);
|
||||||
|
int halfHeight = e.ArrowRectangle.Height / 2;
|
||||||
|
int halfWidth = e.ArrowRectangle.Width / 2;
|
||||||
|
var middle = new Point(dropDownRect.Left + halfWidth, dropDownRect.Top + halfHeight);
|
||||||
|
|
||||||
|
Point[] arrow;
|
||||||
|
|
||||||
|
int verticalArrowStart = middle.Y - halfHeight / 3;
|
||||||
|
int verticalArrowEnd = middle.Y + halfHeight / 3;
|
||||||
|
int horizontalArrowStart = middle.X - halfWidth;
|
||||||
|
int horizontalArrowEnd = middle.X + halfWidth;
|
||||||
|
|
||||||
|
arrow = e.Direction switch
|
||||||
{
|
{
|
||||||
int halfHeight = e.ArrowRectangle.Height / 2;
|
ArrowDirection.Up => new[]
|
||||||
int halfWidth = e.ArrowRectangle.Width / 2;
|
|
||||||
var middle = new Point(dropDownRect.Left + halfWidth, dropDownRect.Top + halfHeight);
|
|
||||||
|
|
||||||
Point[] arrow;
|
|
||||||
|
|
||||||
int verticalArrowStart = middle.Y - halfHeight / 3;
|
|
||||||
int verticalArrowEnd = middle.Y + halfHeight / 3;
|
|
||||||
int horizontalArrowStart = middle.X - halfWidth;
|
|
||||||
int horizontalArrowEnd = middle.X + halfWidth;
|
|
||||||
|
|
||||||
switch (e.Direction)
|
|
||||||
{
|
{
|
||||||
case ArrowDirection.Up:
|
new Point(horizontalArrowStart, verticalArrowEnd),
|
||||||
|
new Point(horizontalArrowEnd, verticalArrowEnd), new Point(middle.X, verticalArrowStart)
|
||||||
arrow = new[] {
|
},
|
||||||
new Point(horizontalArrowStart, verticalArrowEnd),
|
ArrowDirection.Left => new[]
|
||||||
new Point(horizontalArrowEnd, verticalArrowEnd),
|
{
|
||||||
new Point(middle.X, verticalArrowStart)};
|
new Point(horizontalArrowEnd, verticalArrowStart),
|
||||||
|
new Point(horizontalArrowEnd, verticalArrowEnd), new Point(horizontalArrowStart, middle.Y)
|
||||||
break;
|
},
|
||||||
case ArrowDirection.Left:
|
ArrowDirection.Right => new[]
|
||||||
arrow = new[] {
|
{
|
||||||
new Point(horizontalArrowEnd, verticalArrowStart),
|
new Point(horizontalArrowStart, verticalArrowStart),
|
||||||
new Point(horizontalArrowEnd, verticalArrowEnd),
|
new Point(horizontalArrowStart, verticalArrowEnd), new Point(horizontalArrowEnd, middle.Y)
|
||||||
new Point(horizontalArrowStart, middle.Y)};
|
},
|
||||||
|
_ => new[]
|
||||||
break;
|
{
|
||||||
case ArrowDirection.Right:
|
new Point(horizontalArrowStart, verticalArrowStart),
|
||||||
arrow = new[] {
|
new Point(horizontalArrowEnd, verticalArrowStart), new Point(middle.X, verticalArrowEnd)
|
||||||
new Point(horizontalArrowStart, verticalArrowStart),
|
|
||||||
new Point(horizontalArrowStart, verticalArrowEnd),
|
|
||||||
new Point(horizontalArrowEnd, middle.Y)};
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
arrow = new[] {
|
|
||||||
new Point(horizontalArrowStart, verticalArrowStart),
|
|
||||||
new Point(horizontalArrowEnd, verticalArrowStart),
|
|
||||||
new Point(middle.X, verticalArrowEnd) };
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
graphics.FillPolygon(brush, arrow);
|
};
|
||||||
}
|
graphics.FillPolygon(brush, arrow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -116,17 +116,12 @@ namespace Greenshot.Addon.LegacyEditor.Controls
|
||||||
/// <param name="bounds"></param>
|
/// <param name="bounds"></param>
|
||||||
/// <param name="text"></param>
|
/// <param name="text"></param>
|
||||||
private void DrawText(Graphics graphics, FontFamily fontFamily, FontStyle fontStyle, Rectangle bounds, string text)
|
private void DrawText(Graphics graphics, FontFamily fontFamily, FontStyle fontStyle, Rectangle bounds, string text)
|
||||||
{
|
{
|
||||||
using (var font = new Font(fontFamily, Font.Size + 5, fontStyle, GraphicsUnit.Pixel))
|
using var font = new Font(fontFamily, Font.Size + 5, fontStyle, GraphicsUnit.Pixel);
|
||||||
{
|
// Make sure the text is visible by centering it in the line
|
||||||
// Make sure the text is visible by centering it in the line
|
using var stringFormat = new StringFormat {LineAlignment = StringAlignment.Center};
|
||||||
using (var stringFormat = new StringFormat())
|
graphics.DrawString(text, font, Brushes.Black, bounds, stringFormat);
|
||||||
{
|
}
|
||||||
stringFormat.LineAlignment = StringAlignment.Center;
|
|
||||||
graphics.DrawString(text, font, Brushes.Black, bounds, stringFormat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void BindableToolStripComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
private void BindableToolStripComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace Greenshot.Addon.LegacyEditor.Controls
|
||||||
{
|
{
|
||||||
private const int VkEsc = 27;
|
private const int VkEsc = 27;
|
||||||
private readonly IBitmapWithNativeSupport _image;
|
private readonly IBitmapWithNativeSupport _image;
|
||||||
private Cursor _cursor;
|
private readonly Cursor _cursor;
|
||||||
private bool _dragging;
|
private bool _dragging;
|
||||||
private MovableShowColorForm _movableShowColorForm;
|
private MovableShowColorForm _movableShowColorForm;
|
||||||
|
|
||||||
|
@ -87,16 +87,14 @@ namespace Greenshot.Addon.LegacyEditor.Controls
|
||||||
/// <param name="hotspotY">Hotspot Y coordinate</param>
|
/// <param name="hotspotY">Hotspot Y coordinate</param>
|
||||||
/// <returns>Cursor</returns>
|
/// <returns>Cursor</returns>
|
||||||
private static Cursor CreateCursor(IBitmapWithNativeSupport bitmap, int hotspotX, int hotspotY)
|
private static Cursor CreateCursor(IBitmapWithNativeSupport bitmap, int hotspotX, int hotspotY)
|
||||||
{
|
{
|
||||||
using (var iconHandle = new SafeIconHandle(bitmap.NativeBitmap.GetHicon()))
|
using var iconHandle = new SafeIconHandle(bitmap.NativeBitmap.GetHicon());
|
||||||
{
|
NativeIconMethods.GetIconInfo(iconHandle, out var iconInfo);
|
||||||
NativeIconMethods.GetIconInfo(iconHandle, out var iconInfo);
|
iconInfo.Hotspot = new NativePoint(hotspotX, hotspotY);
|
||||||
iconInfo.Hotspot = new NativePoint(hotspotX, hotspotY);
|
iconInfo.IsIcon = false;
|
||||||
iconInfo.IsIcon = false;
|
var icon = NativeIconMethods.CreateIconIndirect(ref iconInfo);
|
||||||
var icon = NativeIconMethods.CreateIconIndirect(ref iconInfo);
|
return new Cursor(icon);
|
||||||
return new Cursor(icon);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This Dispose is called from the Dispose and the Destructor.
|
/// This Dispose is called from the Dispose and the Destructor.
|
||||||
|
@ -106,15 +104,12 @@ namespace Greenshot.Addon.LegacyEditor.Controls
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
if (_cursor != null)
|
_cursor.Dispose();
|
||||||
{
|
|
||||||
_cursor.Dispose();
|
|
||||||
}
|
|
||||||
_movableShowColorForm?.Dispose();
|
_movableShowColorForm?.Dispose();
|
||||||
|
_image.Dispose();
|
||||||
}
|
}
|
||||||
_movableShowColorForm = null;
|
_movableShowColorForm = null;
|
||||||
_cursor = null;
|
base.Dispose(disposing);
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -60,14 +60,12 @@ namespace Greenshot.Addon.LegacyEditor.Controls
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Image != null)
|
if (Image != null)
|
||||||
{
|
{
|
||||||
using (var graphics = Graphics.FromImage(Image))
|
using var graphics = Graphics.FromImage(Image);
|
||||||
{
|
int quarterSize = Image.Height / 4;
|
||||||
int quarterSize = Image.Height / 4;
|
var colorArea = new Rectangle(0, Image.Height - quarterSize, Image.Width, quarterSize);
|
||||||
var colorArea = new Rectangle(0, Image.Height - quarterSize, Image.Width, quarterSize);
|
graphics.FillRectangle(brush, colorArea);
|
||||||
graphics.FillRectangle(brush, colorArea);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanup GDI Object
|
// cleanup GDI Object
|
||||||
brush.Dispose();
|
brush.Dispose();
|
||||||
|
@ -84,7 +82,7 @@ namespace Greenshot.Addon.LegacyEditor.Controls
|
||||||
|
|
||||||
private void ColorButtonClick(object sender, EventArgs e)
|
private void ColorButtonClick(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
var colorDialog = new ColorDialog(_editorConfiguration, _greenshotLanguage)
|
using var colorDialog = new ColorDialog(_editorConfiguration, _greenshotLanguage)
|
||||||
{
|
{
|
||||||
Color = SelectedColor
|
Color = SelectedColor
|
||||||
};
|
};
|
||||||
|
|
|
@ -99,11 +99,8 @@ namespace Greenshot.Addon.LegacyEditor.Drawing.Adorners
|
||||||
var targetGraphics = paintEventArgs.Graphics;
|
var targetGraphics = paintEventArgs.Graphics;
|
||||||
|
|
||||||
var bounds = Bounds;
|
var bounds = Bounds;
|
||||||
using (var brush = new SolidBrush(_color))
|
using var brush = new SolidBrush(_color);
|
||||||
{
|
targetGraphics.FillRectangle(brush, bounds.X, bounds.Y, bounds.Width, bounds.Height);
|
||||||
targetGraphics.FillRectangle(brush, bounds.X, bounds.Y, bounds.Width, bounds.Height);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -57,21 +57,14 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
return NativeRect.Empty;
|
return NativeRect.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var pen = new Pen(Color.White))
|
using var pen = new Pen(Color.White) {Width = lineThickness};
|
||||||
{
|
SetArrowHeads((ArrowHeadCombination) GetFieldValue(FieldTypes.ARROWHEADS), pen);
|
||||||
pen.Width = lineThickness;
|
using var path = new GraphicsPath();
|
||||||
SetArrowHeads((ArrowHeadCombination) GetFieldValue(FieldTypes.ARROWHEADS), pen);
|
path.AddLine(Left, Top, Left + Width, Top + Height);
|
||||||
using (var path = new GraphicsPath())
|
using var matrix = new Matrix();
|
||||||
{
|
NativeRectFloat drawingBounds = path.GetBounds(matrix, pen);
|
||||||
path.AddLine(Left, Top, Left + Width, Top + Height);
|
return drawingBounds.Inflate(2, 2).Round();
|
||||||
using (var matrix = new Matrix())
|
}
|
||||||
{
|
|
||||||
NativeRectFloat drawingBounds = path.GetBounds(matrix, pen);
|
|
||||||
return drawingBounds.Inflate(2, 2).Round();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -109,28 +102,25 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
var steps = 5;
|
var steps = 5;
|
||||||
var currentStep = 1;
|
var currentStep = 1;
|
||||||
while (currentStep <= steps)
|
while (currentStep <= steps)
|
||||||
{
|
{
|
||||||
using (var shadowCapPen = new Pen(Color.FromArgb(alpha, 100, 100, 100), lineThickness))
|
using var shadowCapPen = new Pen(Color.FromArgb(alpha, 100, 100, 100), lineThickness);
|
||||||
{
|
SetArrowHeads(heads, shadowCapPen);
|
||||||
SetArrowHeads(heads, shadowCapPen);
|
|
||||||
|
|
||||||
graphics.DrawLine(shadowCapPen,
|
graphics.DrawLine(shadowCapPen,
|
||||||
Left + currentStep,
|
Left + currentStep,
|
||||||
Top + currentStep,
|
Top + currentStep,
|
||||||
Left + currentStep + Width,
|
Left + currentStep + Width,
|
||||||
Top + currentStep + Height);
|
Top + currentStep + Height);
|
||||||
|
|
||||||
currentStep++;
|
currentStep++;
|
||||||
alpha = alpha - basealpha / steps;
|
alpha = alpha - basealpha / steps;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
using (var pen = new Pen(lineColor, lineThickness))
|
|
||||||
{
|
using var pen = new Pen(lineColor, lineThickness);
|
||||||
SetArrowHeads(heads, pen);
|
SetArrowHeads(heads, pen);
|
||||||
graphics.DrawLine(pen, Left, Top, Left + Width, Top + Height);
|
graphics.DrawLine(pen, Left, Top, Left + Width, Top + Height);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,18 +140,13 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
{
|
{
|
||||||
var lineThickness = GetFieldValueAsInt(FieldTypes.LINE_THICKNESS) + 10;
|
var lineThickness = GetFieldValueAsInt(FieldTypes.LINE_THICKNESS) + 10;
|
||||||
if (lineThickness > 0)
|
if (lineThickness > 0)
|
||||||
{
|
{
|
||||||
using (var pen = new Pen(Color.White))
|
using var pen = new Pen(Color.White) {Width = lineThickness};
|
||||||
{
|
SetArrowHeads((ArrowHeadCombination) GetFieldValue(FieldTypes.ARROWHEADS), pen);
|
||||||
pen.Width = lineThickness;
|
using var path = new GraphicsPath();
|
||||||
SetArrowHeads((ArrowHeadCombination) GetFieldValue(FieldTypes.ARROWHEADS), pen);
|
path.AddLine(Left, Top, Left + Width, Top + Height);
|
||||||
using (var path = new GraphicsPath())
|
return path.IsOutlineVisible(x, y, pen);
|
||||||
{
|
}
|
||||||
path.AddLine(Left, Top, Left + Width, Top + Height);
|
|
||||||
return path.IsOutlineVisible(x, y, pen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,14 +109,12 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
{
|
{
|
||||||
Log.Debug().WriteLine("Rotating element with {0} degrees.", rotateAngle);
|
Log.Debug().WriteLine("Rotating element with {0} degrees.", rotateAngle);
|
||||||
DisposeShadow();
|
DisposeShadow();
|
||||||
using (var tmpMatrix = new Matrix())
|
using var tmpMatrix = new Matrix();
|
||||||
{
|
using (_bitmap)
|
||||||
using (_bitmap)
|
{
|
||||||
{
|
_bitmap = _bitmap.ApplyEffect(new RotateEffect(rotateAngle), tmpMatrix);
|
||||||
_bitmap = _bitmap.ApplyEffect(new RotateEffect(rotateAngle), tmpMatrix);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
base.Transform(matrix);
|
base.Transform(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,12 +223,10 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
private void CheckShadow(bool shadow)
|
private void CheckShadow(bool shadow)
|
||||||
{
|
{
|
||||||
if (shadow && _shadowBitmap == null)
|
if (shadow && _shadowBitmap == null)
|
||||||
{
|
{
|
||||||
using (var matrix = new Matrix())
|
using var matrix = new Matrix();
|
||||||
{
|
_shadowBitmap = _bitmap.ApplyEffect(new DropShadowEffect(), matrix);
|
||||||
_shadowBitmap = _bitmap.ApplyEffect(new DropShadowEffect(), matrix);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -79,23 +79,22 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
using (Brush cropBrush = new SolidBrush(Color.FromArgb(100, 150, 150, 100)))
|
|
||||||
{
|
|
||||||
var cropRectangle = new NativeRect(Left, Top, Width, Height).Normalize();
|
|
||||||
var selectionRect = new NativeRect(cropRectangle.Left - 1, cropRectangle.Top - 1, cropRectangle.Width + 1, cropRectangle.Height + 1);
|
|
||||||
|
|
||||||
DrawSelectionBorder(g, selectionRect);
|
using Brush cropBrush = new SolidBrush(Color.FromArgb(100, 150, 150, 100));
|
||||||
|
var cropRectangle = new NativeRect(Left, Top, Width, Height).Normalize();
|
||||||
|
var selectionRect = new NativeRect(cropRectangle.Left - 1, cropRectangle.Top - 1, cropRectangle.Width + 1, cropRectangle.Height + 1);
|
||||||
|
|
||||||
// top
|
DrawSelectionBorder(g, selectionRect);
|
||||||
g.FillRectangle(cropBrush, new NativeRect(0, 0, _parent.Width, cropRectangle.Top));
|
|
||||||
// left
|
// top
|
||||||
g.FillRectangle(cropBrush, new NativeRect(0, cropRectangle.Top, cropRectangle.Left, cropRectangle.Height));
|
g.FillRectangle(cropBrush, new NativeRect(0, 0, _parent.Width, cropRectangle.Top));
|
||||||
// right
|
// left
|
||||||
g.FillRectangle(cropBrush,
|
g.FillRectangle(cropBrush, new NativeRect(0, cropRectangle.Top, cropRectangle.Left, cropRectangle.Height));
|
||||||
new NativeRect(cropRectangle.Left + cropRectangle.Width, cropRectangle.Top, _parent.Width - (cropRectangle.Left + cropRectangle.Width), cropRectangle.Height));
|
// right
|
||||||
// bottom
|
g.FillRectangle(cropBrush,
|
||||||
g.FillRectangle(cropBrush, new NativeRect(0, cropRectangle.Top + cropRectangle.Height, _parent.Width, _parent.Height - (cropRectangle.Top + cropRectangle.Height)));
|
new NativeRect(cropRectangle.Left + cropRectangle.Width, cropRectangle.Top, _parent.Width - (cropRectangle.Left + cropRectangle.Width), cropRectangle.Height));
|
||||||
}
|
// bottom
|
||||||
}
|
g.FillRectangle(cropBrush, new NativeRect(0, cropRectangle.Top + cropRectangle.Height, _parent.Width, _parent.Height - (cropRectangle.Top + cropRectangle.Height)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -75,12 +75,11 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
using (var fileCursor = new Cursor(filename))
|
|
||||||
{
|
using var fileCursor = new Cursor(filename);
|
||||||
Cursor = fileCursor;
|
Cursor = fileCursor;
|
||||||
Log.Debug().WriteLine("Loaded file: " + filename + " with resolution: " + Height + "," + Width);
|
Log.Debug().WriteLine("Loaded file: " + filename + " with resolution: " + Height + "," + Width);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnDeserialized(StreamingContext streamingContext)
|
protected override void OnDeserialized(StreamingContext streamingContext)
|
||||||
{
|
{
|
||||||
|
|
|
@ -602,14 +602,14 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void DrawSelectionBorder(Graphics g, NativeRect rect)
|
protected void DrawSelectionBorder(Graphics g, NativeRect rect)
|
||||||
{
|
{
|
||||||
using (var pen = new Pen(Color.MediumSeaGreen))
|
using var pen = new Pen(Color.MediumSeaGreen)
|
||||||
{
|
{
|
||||||
pen.DashPattern = new float[] {1, 2};
|
DashPattern = new float[] {1, 2},
|
||||||
pen.Width = 1;
|
Width = 1
|
||||||
g.DrawRectangle(pen, rect);
|
};
|
||||||
}
|
g.DrawRectangle(pen, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void ResizeTo(int width, int height)
|
public void ResizeTo(int width, int height)
|
||||||
|
|
|
@ -82,32 +82,28 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
var steps = 5;
|
var steps = 5;
|
||||||
var currentStep = lineVisible ? 1 : 0;
|
var currentStep = lineVisible ? 1 : 0;
|
||||||
while (currentStep <= steps)
|
while (currentStep <= steps)
|
||||||
{
|
{
|
||||||
using (var shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100)))
|
using var shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100))
|
||||||
{
|
{
|
||||||
shadowPen.Width = lineVisible ? lineThickness : 1;
|
Width = lineVisible ? lineThickness : 1
|
||||||
var shadowRect = new NativeRect(rect.Left + currentStep, rect.Top + currentStep, rect.Width, rect.Height).Normalize();
|
};
|
||||||
graphics.DrawEllipse(shadowPen, shadowRect);
|
var shadowRect = new NativeRect(rect.Left + currentStep, rect.Top + currentStep, rect.Width, rect.Height).Normalize();
|
||||||
currentStep++;
|
graphics.DrawEllipse(shadowPen, shadowRect);
|
||||||
alpha = alpha - basealpha / steps;
|
currentStep++;
|
||||||
}
|
alpha = alpha - basealpha / steps;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//draw the original shape
|
//draw the original shape
|
||||||
if (Colors.IsVisible(fillColor))
|
if (Colors.IsVisible(fillColor))
|
||||||
{
|
{
|
||||||
using (Brush brush = new SolidBrush(fillColor))
|
using Brush brush = new SolidBrush(fillColor);
|
||||||
{
|
graphics.FillEllipse(brush, rect);
|
||||||
graphics.FillEllipse(brush, rect);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
if (lineVisible)
|
if (lineVisible)
|
||||||
{
|
{
|
||||||
using (var pen = new Pen(lineColor, lineThickness))
|
using var pen = new Pen(lineColor, lineThickness);
|
||||||
{
|
graphics.DrawEllipse(pen, rect);
|
||||||
graphics.DrawEllipse(pen, rect);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Contains(int x, int y)
|
public override bool Contains(int x, int y)
|
||||||
|
@ -151,16 +147,12 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
|
|
||||||
// check the rest of the lines
|
// check the rest of the lines
|
||||||
if (lineThickness > 0)
|
if (lineThickness > 0)
|
||||||
{
|
{
|
||||||
using (var pen = new Pen(Color.White, lineThickness))
|
using var pen = new Pen(Color.White, lineThickness);
|
||||||
{
|
using var path = new GraphicsPath();
|
||||||
using (var path = new GraphicsPath())
|
path.AddEllipse(rect);
|
||||||
{
|
return path.IsOutlineVisible(x, y, pen);
|
||||||
path.AddEllipse(rect);
|
}
|
||||||
return path.IsOutlineVisible(x, y, pen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,24 +85,20 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
var steps = 5;
|
var steps = 5;
|
||||||
var currentStep = lineVisible ? 1 : 0;
|
var currentStep = lineVisible ? 1 : 0;
|
||||||
while (currentStep <= steps)
|
while (currentStep <= steps)
|
||||||
{
|
{
|
||||||
using (var shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100), lineThickness))
|
using var shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100), lineThickness);
|
||||||
{
|
var shadowRect = new NativeRect(Left + currentStep, Top + currentStep, Width, Height).Normalize();
|
||||||
var shadowRect = new NativeRect(Left + currentStep, Top + currentStep, Width, Height).Normalize();
|
graphics.DrawRectangle(shadowPen, shadowRect);
|
||||||
graphics.DrawRectangle(shadowPen, shadowRect);
|
currentStep++;
|
||||||
currentStep++;
|
alpha = alpha - baseAlpha / steps;
|
||||||
alpha = alpha - baseAlpha / steps;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
var rect = new NativeRect(Left, Top, Width, Height).Normalize();
|
var rect = new NativeRect(Left, Top, Width, Height).Normalize();
|
||||||
if (lineThickness > 0)
|
if (lineThickness > 0)
|
||||||
{
|
{
|
||||||
using (var pen = new Pen(lineColor, lineThickness))
|
using var pen = new Pen(lineColor, lineThickness);
|
||||||
{
|
graphics.DrawRectangle(pen, rect);
|
||||||
graphics.DrawRectangle(pen, rect);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,59 +57,58 @@ namespace Greenshot.Addon.LegacyEditor.Drawing.Filters
|
||||||
{
|
{
|
||||||
pixelSize = rect.Height;
|
pixelSize = rect.Height;
|
||||||
}
|
}
|
||||||
using (var dest = FastBitmapFactory.CreateCloneOf(applyBitmap, area: rect))
|
|
||||||
|
using var dest = FastBitmapFactory.CreateCloneOf(applyBitmap, area: rect);
|
||||||
|
using (var src = FastBitmapFactory.Create(applyBitmap, rect))
|
||||||
{
|
{
|
||||||
using (var src = FastBitmapFactory.Create(applyBitmap, rect))
|
var halbPixelSize = pixelSize / 2;
|
||||||
|
// Create a list of x values
|
||||||
|
var xValues = new List<int>();
|
||||||
|
for (var x = src.Left - halbPixelSize; x <= src.Right + halbPixelSize; x = x + pixelSize)
|
||||||
{
|
{
|
||||||
var halbPixelSize = pixelSize / 2;
|
xValues.Add(x);
|
||||||
// Create a list of x values
|
}
|
||||||
var xValues = new List<int>();
|
for (var y = src.Top - halbPixelSize; y < src.Bottom + halbPixelSize; y = y + pixelSize)
|
||||||
for (var x = src.Left - halbPixelSize; x <= src.Right + halbPixelSize; x = x + pixelSize)
|
{
|
||||||
{
|
Parallel.ForEach(xValues, x =>
|
||||||
xValues.Add(x);
|
{
|
||||||
}
|
// TODO: Use stackalloc, or byte[]?
|
||||||
for (var y = src.Top - halbPixelSize; y < src.Bottom + halbPixelSize; y = y + pixelSize)
|
var colors = new List<Color>();
|
||||||
{
|
for (var yy = y; yy < y + pixelSize; yy++)
|
||||||
Parallel.ForEach(xValues, x =>
|
{
|
||||||
{
|
if (yy < src.Top || yy >= src.Bottom)
|
||||||
// TODO: Use stackalloc, or byte[]?
|
{
|
||||||
var colors = new List<Color>();
|
continue;
|
||||||
for (var yy = y; yy < y + pixelSize; yy++)
|
}
|
||||||
{
|
for (var xx = x; xx < x + pixelSize; xx++)
|
||||||
if (yy < src.Top || yy >= src.Bottom)
|
{
|
||||||
{
|
if (xx < src.Left || xx >= src.Right)
|
||||||
continue;
|
{
|
||||||
}
|
continue;
|
||||||
for (var xx = x; xx < x + pixelSize; xx++)
|
}
|
||||||
{
|
colors.Add(src.GetColorAt(xx, yy));
|
||||||
if (xx < src.Left || xx >= src.Right)
|
}
|
||||||
{
|
}
|
||||||
continue;
|
var currentAvgColor = Colors.Mix(colors);
|
||||||
}
|
for (var yy = y; yy <= y + pixelSize; yy++)
|
||||||
colors.Add(src.GetColorAt(xx, yy));
|
{
|
||||||
}
|
if (yy < src.Top || yy >= src.Bottom)
|
||||||
}
|
{
|
||||||
var currentAvgColor = Colors.Mix(colors);
|
continue;
|
||||||
for (var yy = y; yy <= y + pixelSize; yy++)
|
}
|
||||||
{
|
for (var xx = x; xx <= x + pixelSize; xx++)
|
||||||
if (yy < src.Top || yy >= src.Bottom)
|
{
|
||||||
{
|
if (xx < src.Left || xx >= src.Right)
|
||||||
continue;
|
{
|
||||||
}
|
continue;
|
||||||
for (var xx = x; xx <= x + pixelSize; xx++)
|
}
|
||||||
{
|
dest.SetColorAt(xx, yy, ref currentAvgColor);
|
||||||
if (xx < src.Left || xx >= src.Right)
|
}
|
||||||
{
|
}
|
||||||
continue;
|
});
|
||||||
}
|
|
||||||
dest.SetColorAt(xx, yy, ref currentAvgColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
dest.DrawTo(graphics, rect.Location);
|
|
||||||
}
|
}
|
||||||
|
dest.DrawTo(graphics, rect.Location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -186,31 +186,29 @@ namespace Greenshot.Addon.LegacyEditor.Drawing {
|
||||||
|
|
||||||
int lineThickness = GetFieldValueAsInt(FieldTypes.LINE_THICKNESS);
|
int lineThickness = GetFieldValueAsInt(FieldTypes.LINE_THICKNESS);
|
||||||
var lineColor = GetFieldValueAsColor(FieldTypes.LINE_COLOR);
|
var lineColor = GetFieldValueAsColor(FieldTypes.LINE_COLOR);
|
||||||
using (var pen = new Pen(lineColor)) {
|
using var pen = new Pen(lineColor) {Width = lineThickness};
|
||||||
pen.Width = lineThickness;
|
if (!(pen.Width > 0))
|
||||||
if (!(pen.Width > 0))
|
{
|
||||||
{
|
return;
|
||||||
return;
|
}
|
||||||
}
|
// Make sure the lines are nicely rounded
|
||||||
// Make sure the lines are nicely rounded
|
pen.EndCap = LineCap.Round;
|
||||||
pen.EndCap = LineCap.Round;
|
pen.StartCap = LineCap.Round;
|
||||||
pen.StartCap = LineCap.Round;
|
pen.LineJoin = LineJoin.Round;
|
||||||
pen.LineJoin = LineJoin.Round;
|
// Move to where we need to draw
|
||||||
// Move to where we need to draw
|
graphics.TranslateTransform(Left, Top);
|
||||||
graphics.TranslateTransform(Left, Top);
|
lock (_freehandPathLock)
|
||||||
lock (_freehandPathLock)
|
{
|
||||||
{
|
if (_isRecalculated && Selected && renderMode == RenderMode.Edit)
|
||||||
if (_isRecalculated && Selected && renderMode == RenderMode.Edit)
|
{
|
||||||
{
|
DrawSelectionBorder(graphics, pen, _freehandPath);
|
||||||
DrawSelectionBorder(graphics, pen, _freehandPath);
|
}
|
||||||
}
|
graphics.DrawPath(pen, _freehandPath);
|
||||||
graphics.DrawPath(pen, _freehandPath);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Move back, otherwise everything is shifted
|
// Move back, otherwise everything is shifted
|
||||||
graphics.TranslateTransform(-Left,-Top);
|
graphics.TranslateTransform(-Left,-Top);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draw a selectionborder around the freehand path
|
/// Draw a selectionborder around the freehand path
|
||||||
|
@ -218,20 +216,19 @@ namespace Greenshot.Addon.LegacyEditor.Drawing {
|
||||||
/// <param name="graphics">Graphics</param>
|
/// <param name="graphics">Graphics</param>
|
||||||
/// <param name="linePen">Pen</param>
|
/// <param name="linePen">Pen</param>
|
||||||
/// <param name="path">GraphicsPath</param>
|
/// <param name="path">GraphicsPath</param>
|
||||||
protected static void DrawSelectionBorder(Graphics graphics, Pen linePen, GraphicsPath path) {
|
protected static void DrawSelectionBorder(Graphics graphics, Pen linePen, GraphicsPath path)
|
||||||
using (var selectionPen = (Pen) linePen.Clone()) {
|
{
|
||||||
using (var selectionPath = (GraphicsPath)path.Clone()) {
|
using var selectionPen = (Pen) linePen.Clone();
|
||||||
selectionPen.Width += 5;
|
using var selectionPath = (GraphicsPath)path.Clone();
|
||||||
selectionPen.Color = Color.FromArgb(120, Color.LightSeaGreen);
|
selectionPen.Width += 5;
|
||||||
graphics.DrawPath(selectionPen, selectionPath);
|
selectionPen.Color = Color.FromArgb(120, Color.LightSeaGreen);
|
||||||
selectionPath.Widen(selectionPen);
|
graphics.DrawPath(selectionPen, selectionPath);
|
||||||
selectionPen.DashPattern = new float[]{2,2};
|
selectionPath.Widen(selectionPen);
|
||||||
selectionPen.Color = Color.LightSeaGreen;
|
selectionPen.DashPattern = new float[]{2,2};
|
||||||
selectionPen.Width = 1;
|
selectionPen.Color = Color.LightSeaGreen;
|
||||||
graphics.DrawPath(selectionPen, selectionPath);
|
selectionPen.Width = 1;
|
||||||
}
|
graphics.DrawPath(selectionPen, selectionPath);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the bounds in which we have something drawn, plus safety margin, these are not the normal bounds...
|
/// Get the bounds in which we have something drawn, plus safety margin, these are not the normal bounds...
|
||||||
|
@ -276,14 +273,12 @@ namespace Greenshot.Addon.LegacyEditor.Drawing {
|
||||||
bool returnValue = base.ClickableAt(x, y);
|
bool returnValue = base.ClickableAt(x, y);
|
||||||
if (returnValue) {
|
if (returnValue) {
|
||||||
int lineThickness = GetFieldValueAsInt(FieldTypes.LINE_THICKNESS);
|
int lineThickness = GetFieldValueAsInt(FieldTypes.LINE_THICKNESS);
|
||||||
using (var pen = new Pen(Color.White)) {
|
using var pen = new Pen(Color.White) {Width = lineThickness + 10};
|
||||||
pen.Width = lineThickness + 10;
|
lock (_freehandPathLock)
|
||||||
lock (_freehandPathLock)
|
{
|
||||||
{
|
returnValue = _freehandPath.IsOutlineVisible(x - Left, y - Top, pen);
|
||||||
returnValue = _freehandPath.IsOutlineVisible(x - Left, y - Top, pen);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,12 +69,11 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
using (var fileIcon = new Icon(filename))
|
|
||||||
{
|
using var fileIcon = new Icon(filename);
|
||||||
Icon = fileIcon;
|
Icon = fileIcon;
|
||||||
Log.Debug().WriteLine("Loaded file: " + filename + " with resolution: " + Height + "," + Width);
|
Log.Debug().WriteLine("Loaded file: " + filename + " with resolution: " + Height + "," + Width);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnDeserialized(StreamingContext streamingContext)
|
protected override void OnDeserialized(StreamingContext streamingContext)
|
||||||
{
|
{
|
||||||
|
|
|
@ -91,28 +91,24 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
var steps = 5;
|
var steps = 5;
|
||||||
var currentStep = 1;
|
var currentStep = 1;
|
||||||
while (currentStep <= steps)
|
while (currentStep <= steps)
|
||||||
{
|
{
|
||||||
using (var shadowCapPen = new Pen(Color.FromArgb(alpha, 100, 100, 100), lineThickness))
|
using var shadowCapPen = new Pen(Color.FromArgb(alpha, 100, 100, 100), lineThickness);
|
||||||
{
|
graphics.DrawLine(shadowCapPen,
|
||||||
graphics.DrawLine(shadowCapPen,
|
Left + currentStep,
|
||||||
Left + currentStep,
|
Top + currentStep,
|
||||||
Top + currentStep,
|
Left + currentStep + Width,
|
||||||
Left + currentStep + Width,
|
Top + currentStep + Height);
|
||||||
Top + currentStep + Height);
|
|
||||||
|
|
||||||
currentStep++;
|
currentStep++;
|
||||||
#pragma warning disable IDE0054 // Use compound assignment
|
#pragma warning disable IDE0054 // Use compound assignment
|
||||||
alpha = alpha - basealpha / steps;
|
alpha = alpha - basealpha / steps;
|
||||||
#pragma warning restore IDE0054 // Use compound assignment
|
#pragma warning restore IDE0054 // Use compound assignment
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var pen = new Pen(lineColor, lineThickness))
|
using var pen = new Pen(lineColor, lineThickness);
|
||||||
{
|
graphics.DrawLine(pen, Left, Top, Left + Width, Top + Height);
|
||||||
graphics.DrawLine(pen, Left, Top, Left + Width, Top + Height);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
@ -120,17 +116,12 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
{
|
{
|
||||||
var lineThickness = GetFieldValueAsInt(FieldTypes.LINE_THICKNESS) + 5;
|
var lineThickness = GetFieldValueAsInt(FieldTypes.LINE_THICKNESS) + 5;
|
||||||
if (lineThickness > 0)
|
if (lineThickness > 0)
|
||||||
{
|
{
|
||||||
using (var pen = new Pen(Color.White))
|
using var pen = new Pen(Color.White) {Width = lineThickness};
|
||||||
{
|
using var path = new GraphicsPath();
|
||||||
pen.Width = lineThickness;
|
path.AddLine(Left, Top, Left + Width, Top + Height);
|
||||||
using (var path = new GraphicsPath())
|
return path.IsOutlineVisible(x, y, pen);
|
||||||
{
|
}
|
||||||
path.AddLine(Left, Top, Left + Width, Top + Height);
|
|
||||||
return path.IsOutlineVisible(x, y, pen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,34 +94,33 @@ namespace Greenshot.Addon.LegacyEditor.Drawing {
|
||||||
int alpha = basealpha;
|
int alpha = basealpha;
|
||||||
int steps = 5;
|
int steps = 5;
|
||||||
int currentStep = lineVisible ? 1 : 0;
|
int currentStep = lineVisible ? 1 : 0;
|
||||||
while (currentStep <= steps) {
|
while (currentStep <= steps)
|
||||||
using (var shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100))) {
|
{
|
||||||
shadowPen.Width = lineVisible ? lineThickness : 1;
|
using var shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100)) {Width = lineVisible ? lineThickness : 1};
|
||||||
var shadowRect = new NativeRect(
|
var shadowRect = new NativeRect(
|
||||||
rect.Left + currentStep,
|
rect.Left + currentStep,
|
||||||
rect.Top + currentStep,
|
rect.Top + currentStep,
|
||||||
rect.Width,
|
rect.Width,
|
||||||
rect.Height).Normalize();
|
rect.Height).Normalize();
|
||||||
graphics.DrawRectangle(shadowPen, shadowRect);
|
graphics.DrawRectangle(shadowPen, shadowRect);
|
||||||
currentStep++;
|
currentStep++;
|
||||||
alpha = alpha - basealpha / steps;
|
alpha = alpha - basealpha / steps;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (Colors.IsVisible(fillColor)) {
|
if (Colors.IsVisible(fillColor))
|
||||||
using (Brush brush = new SolidBrush(fillColor)) {
|
{
|
||||||
graphics.FillRectangle(brush, rect);
|
using Brush brush = new SolidBrush(fillColor);
|
||||||
}
|
graphics.FillRectangle(brush, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
graphics.SmoothingMode = SmoothingMode.HighSpeed;
|
graphics.SmoothingMode = SmoothingMode.HighSpeed;
|
||||||
if (lineVisible) {
|
if (lineVisible)
|
||||||
using (var pen = new Pen(lineColor, lineThickness)) {
|
{
|
||||||
graphics.DrawRectangle(pen, rect);
|
using var pen = new Pen(lineColor, lineThickness);
|
||||||
}
|
graphics.DrawRectangle(pen, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public override bool ClickableAt(int x, int y) {
|
public override bool ClickableAt(int x, int y) {
|
||||||
|
@ -143,14 +142,13 @@ namespace Greenshot.Addon.LegacyEditor.Drawing {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the rest of the lines
|
// check the rest of the lines
|
||||||
if (lineThickness > 0) {
|
if (lineThickness > 0)
|
||||||
using (var pen = new Pen(Color.White, lineThickness)) {
|
{
|
||||||
using (var path = new GraphicsPath()) {
|
using var pen = new Pen(Color.White, lineThickness);
|
||||||
path.AddRectangle(rect);
|
using var path = new GraphicsPath();
|
||||||
return path.IsOutlineVisible(x, y, pen);
|
path.AddRectangle(rect);
|
||||||
}
|
return path.IsOutlineVisible(x, y, pen);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,18 +55,14 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
var lineThickness = GetFieldValueAsInt(FieldTypes.LINE_THICKNESS);
|
var lineThickness = GetFieldValueAsInt(FieldTypes.LINE_THICKNESS);
|
||||||
var lineColor = GetFieldValueAsColor(FieldTypes.LINE_COLOR);
|
var lineColor = GetFieldValueAsColor(FieldTypes.LINE_COLOR);
|
||||||
var shadow = GetFieldValueAsBool(FieldTypes.SHADOW);
|
var shadow = GetFieldValueAsBool(FieldTypes.SHADOW);
|
||||||
using (var pen = new Pen(lineColor, lineThickness))
|
using var pen = new Pen(lineColor, lineThickness);
|
||||||
{
|
var inflateValue = lineThickness + 2 + (shadow ? 6 : 0);
|
||||||
var inflateValue = lineThickness + 2 + (shadow ? 6 : 0);
|
using var tailPath = CreateTail();
|
||||||
using (var tailPath = CreateTail())
|
NativeRectFloat tailBounds = tailPath.GetBounds(new Matrix(), pen);
|
||||||
{
|
var bounds = new NativeRect(Left, Top, Width, Height).Normalize();
|
||||||
NativeRectFloat tailBounds = tailPath.GetBounds(new Matrix(), pen);
|
|
||||||
var bounds = new NativeRect(Left, Top, Width, Height).Normalize();
|
|
||||||
|
|
||||||
return tailBounds.Round().Union(bounds).Inflate(inflateValue, inflateValue);
|
return tailBounds.Round().Union(bounds).Inflate(inflateValue, inflateValue);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return NativeRect.Empty;
|
return NativeRect.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,37 +233,33 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
var alpha = basealpha;
|
var alpha = basealpha;
|
||||||
const int steps = 5;
|
const int steps = 5;
|
||||||
var currentStep = lineVisible ? 1 : 0;
|
var currentStep = lineVisible ? 1 : 0;
|
||||||
using (var shadowMatrix = new Matrix())
|
using var shadowMatrix = new Matrix();
|
||||||
using (var bubbleClone = (GraphicsPath) bubble.Clone())
|
using var bubbleClone = (GraphicsPath) bubble.Clone();
|
||||||
using (var tailClone = (GraphicsPath) tail.Clone())
|
using var tailClone = (GraphicsPath) tail.Clone();
|
||||||
{
|
shadowMatrix.Translate(1, 1);
|
||||||
shadowMatrix.Translate(1, 1);
|
while (currentStep <= steps)
|
||||||
while (currentStep <= steps)
|
{
|
||||||
{
|
using (var shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100)))
|
||||||
using (var shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100)))
|
{
|
||||||
{
|
shadowPen.Width = lineVisible ? lineThickness : 1;
|
||||||
shadowPen.Width = lineVisible ? lineThickness : 1;
|
tailClone.Transform(shadowMatrix);
|
||||||
tailClone.Transform(shadowMatrix);
|
graphics.DrawPath(shadowPen, tailClone);
|
||||||
graphics.DrawPath(shadowPen, tailClone);
|
bubbleClone.Transform(shadowMatrix);
|
||||||
bubbleClone.Transform(shadowMatrix);
|
graphics.DrawPath(shadowPen, bubbleClone);
|
||||||
graphics.DrawPath(shadowPen, bubbleClone);
|
}
|
||||||
}
|
currentStep++;
|
||||||
currentStep++;
|
alpha = alpha - basealpha / steps;
|
||||||
alpha = alpha - basealpha / steps;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var state = graphics.Save();
|
var state = graphics.Save();
|
||||||
// draw the tail border where the bubble is not visible
|
// draw the tail border where the bubble is not visible
|
||||||
using (var clipRegion = new Region(bubble))
|
using (var clipRegion = new Region(bubble))
|
||||||
{
|
{
|
||||||
graphics.SetClip(clipRegion, CombineMode.Exclude);
|
graphics.SetClip(clipRegion, CombineMode.Exclude);
|
||||||
using (var pen = new Pen(lineColor, lineThickness))
|
using var pen = new Pen(lineColor, lineThickness);
|
||||||
{
|
graphics.DrawPath(pen, tail);
|
||||||
graphics.DrawPath(pen, tail);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
graphics.Restore(state);
|
graphics.Restore(state);
|
||||||
|
|
||||||
if (Colors.IsVisible(fillColor))
|
if (Colors.IsVisible(fillColor))
|
||||||
|
@ -289,12 +281,10 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
using (var clipRegion = new Region(tail))
|
using (var clipRegion = new Region(tail))
|
||||||
{
|
{
|
||||||
graphics.SetClip(clipRegion, CombineMode.Exclude);
|
graphics.SetClip(clipRegion, CombineMode.Exclude);
|
||||||
using (var pen = new Pen(lineColor, lineThickness))
|
using var pen = new Pen(lineColor, lineThickness);
|
||||||
{
|
//pen.EndCap = pen.StartCap = LineCap.Round;
|
||||||
//pen.EndCap = pen.StartCap = LineCap.Round;
|
graphics.DrawPath(pen, bubble);
|
||||||
graphics.DrawPath(pen, bubble);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
graphics.Restore(state);
|
graphics.Restore(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,26 +318,23 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
{
|
{
|
||||||
var lineThickness = GetFieldValueAsInt(FieldTypes.LINE_THICKNESS);
|
var lineThickness = GetFieldValueAsInt(FieldTypes.LINE_THICKNESS);
|
||||||
var lineColor = GetFieldValueAsColor(FieldTypes.LINE_COLOR);
|
var lineColor = GetFieldValueAsColor(FieldTypes.LINE_COLOR);
|
||||||
using (var pen = new Pen(lineColor, lineThickness))
|
using var pen = new Pen(lineColor, lineThickness);
|
||||||
{
|
using (var bubblePath = CreateBubble(lineThickness))
|
||||||
using (var bubblePath = CreateBubble(lineThickness))
|
{
|
||||||
{
|
bubblePath.Widen(pen);
|
||||||
bubblePath.Widen(pen);
|
if (bubblePath.IsVisible(clickedPoint))
|
||||||
if (bubblePath.IsVisible(clickedPoint))
|
{
|
||||||
{
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
using (var tailPath = CreateTail())
|
using var tailPath = CreateTail();
|
||||||
{
|
tailPath.Widen(pen);
|
||||||
tailPath.Widen(pen);
|
if (tailPath.IsVisible(clickedPoint))
|
||||||
if (tailPath.IsVisible(clickedPoint))
|
{
|
||||||
{
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,14 +195,11 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
{
|
{
|
||||||
EllipseContainer.DrawEllipse(rect, graphics, rm, 0, Color.Transparent, fillColor, false);
|
EllipseContainer.DrawEllipse(rect, graphics, rm, 0, Color.Transparent, fillColor, false);
|
||||||
}
|
}
|
||||||
using (var fam = new FontFamily(FontFamily.GenericSansSerif.Name))
|
|
||||||
{
|
using var fam = new FontFamily(FontFamily.GenericSansSerif.Name);
|
||||||
using (var font = new Font(fam, _fontSize, FontStyle.Bold, GraphicsUnit.Pixel))
|
using var font = new Font(fam, _fontSize, FontStyle.Bold, GraphicsUnit.Pixel);
|
||||||
{
|
TextContainer.DrawText(graphics, rect, 0, lineColor, false, _stringFormat, text, font);
|
||||||
TextContainer.DrawText(graphics, rect, 0, lineColor, false, _stringFormat, text, font);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool ClickableAt(int x, int y)
|
public override bool ClickableAt(int x, int y)
|
||||||
{
|
{
|
||||||
|
|
|
@ -257,6 +257,7 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="coreConfiguration">ICoreConfiguration</param>
|
/// <param name="coreConfiguration">ICoreConfiguration</param>
|
||||||
/// <param name="editorConfiguration">IEditorConfiguration</param>
|
/// <param name="editorConfiguration">IEditorConfiguration</param>
|
||||||
|
/// <param name="editorLanguage">IEditorLanguage</param>
|
||||||
/// <param name="newBitmap">IBitmapWithNativeSupport</param>
|
/// <param name="newBitmap">IBitmapWithNativeSupport</param>
|
||||||
public Surface(ICoreConfiguration coreConfiguration, IEditorConfiguration editorConfiguration, IEditorLanguage editorLanguage, IBitmapWithNativeSupport newBitmap) : this(coreConfiguration, editorConfiguration, editorLanguage)
|
public Surface(ICoreConfiguration coreConfiguration, IEditorConfiguration editorConfiguration, IEditorLanguage editorLanguage, IBitmapWithNativeSupport newBitmap) : this(coreConfiguration, editorConfiguration, editorLanguage)
|
||||||
{
|
{
|
||||||
|
@ -563,7 +564,7 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
/// <param name="effect"></param>
|
/// <param name="effect"></param>
|
||||||
public void ApplyBitmapEffect(IEffect effect)
|
public void ApplyBitmapEffect(IEffect effect)
|
||||||
{
|
{
|
||||||
var backgroundForm = new BackgroundForm("Effect", "Please wait");
|
using var backgroundForm = new BackgroundForm("Effect", "Please wait");
|
||||||
backgroundForm.Show();
|
backgroundForm.Show();
|
||||||
Application.DoEvents();
|
Application.DoEvents();
|
||||||
try
|
try
|
||||||
|
@ -1079,7 +1080,8 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
// TODO: Check if we need to dispose _cursorContainer
|
||||||
|
if (disposing)
|
||||||
{
|
{
|
||||||
Count--;
|
Count--;
|
||||||
Log.Debug().WriteLine("Disposing surface!");
|
Log.Debug().WriteLine("Disposing surface!");
|
||||||
|
@ -2035,14 +2037,12 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
{
|
{
|
||||||
var uri = new Uri(possibleUrl);
|
var uri = new Uri(possibleUrl);
|
||||||
|
|
||||||
using (var image = uri.GetAsAsync<Bitmap>().Result)
|
using var image = uri.GetAsAsync<Bitmap>().Result;
|
||||||
{
|
if (image != null)
|
||||||
if (image != null)
|
{
|
||||||
{
|
AddImageContainer(BitmapWrapper.FromBitmap(image), mouse.X, mouse.Y);
|
||||||
AddImageContainer(BitmapWrapper.FromBitmap(image), mouse.X, mouse.Y);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -2054,15 +2054,13 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
{
|
{
|
||||||
var uri = new Uri(possibleUrl);
|
var uri = new Uri(possibleUrl);
|
||||||
|
|
||||||
using (var image = uri.GetAsAsync<Bitmap>().Result)
|
using var image = uri.GetAsAsync<Bitmap>().Result;
|
||||||
{
|
if (image != null)
|
||||||
if (image != null)
|
{
|
||||||
{
|
AddImageContainer(BitmapWrapper.FromBitmap(image), mouse.X, mouse.Y);
|
||||||
AddImageContainer(BitmapWrapper.FromBitmap(image), mouse.X, mouse.Y);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var image in ClipboardHelper.GetBitmaps(e.Data))
|
foreach (var image in ClipboardHelper.GetBitmaps(e.Data))
|
||||||
|
|
|
@ -262,8 +262,8 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
};
|
};
|
||||||
|
|
||||||
_textBox.DataBindings.Add("Text", this, "Text", false, DataSourceUpdateMode.OnPropertyChanged);
|
_textBox.DataBindings.Add("Text", this, "Text", false, DataSourceUpdateMode.OnPropertyChanged);
|
||||||
_textBox.LostFocus += textBox_LostFocus;
|
_textBox.LostFocus += TextBox_LostFocus;
|
||||||
_textBox.KeyDown += textBox_KeyDown;
|
_textBox.KeyDown += TextBox_KeyDown;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowTextBox()
|
private void ShowTextBox()
|
||||||
|
@ -306,7 +306,10 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
_parent.Focus();
|
_parent.Focus();
|
||||||
_textBox?.Hide();
|
_textBox?.Hide();
|
||||||
_parent.KeysLocked = false;
|
_parent.KeysLocked = false;
|
||||||
_parent.Controls.Remove(_textBox);
|
if (_textBox != null)
|
||||||
|
{
|
||||||
|
_parent.Controls.Remove(_textBox);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -336,43 +339,41 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
var fontStyle = FontStyle.Regular;
|
var fontStyle = FontStyle.Regular;
|
||||||
|
|
||||||
bool hasStyle = false;
|
bool hasStyle = false;
|
||||||
using (var fontFamily = new FontFamily(fontFamilyName))
|
using var fontFamily = new FontFamily(fontFamilyName);
|
||||||
|
bool boldAvailable = fontFamily.IsStyleAvailable(FontStyle.Bold);
|
||||||
|
if (fontBold && boldAvailable)
|
||||||
{
|
{
|
||||||
bool boldAvailable = fontFamily.IsStyleAvailable(FontStyle.Bold);
|
fontStyle |= FontStyle.Bold;
|
||||||
if (fontBold && boldAvailable)
|
hasStyle = true;
|
||||||
{
|
|
||||||
fontStyle |= FontStyle.Bold;
|
|
||||||
hasStyle = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool italicAvailable = fontFamily.IsStyleAvailable(FontStyle.Italic);
|
|
||||||
if (fontItalic && italicAvailable)
|
|
||||||
{
|
|
||||||
fontStyle |= FontStyle.Italic;
|
|
||||||
hasStyle = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasStyle)
|
|
||||||
{
|
|
||||||
bool regularAvailable = fontFamily.IsStyleAvailable(FontStyle.Regular);
|
|
||||||
if (regularAvailable)
|
|
||||||
{
|
|
||||||
fontStyle = FontStyle.Regular;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (boldAvailable)
|
|
||||||
{
|
|
||||||
fontStyle = FontStyle.Bold;
|
|
||||||
}
|
|
||||||
else if (italicAvailable)
|
|
||||||
{
|
|
||||||
fontStyle = FontStyle.Italic;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Font(fontFamily, fontSize, fontStyle, GraphicsUnit.Pixel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool italicAvailable = fontFamily.IsStyleAvailable(FontStyle.Italic);
|
||||||
|
if (fontItalic && italicAvailable)
|
||||||
|
{
|
||||||
|
fontStyle |= FontStyle.Italic;
|
||||||
|
hasStyle = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasStyle)
|
||||||
|
{
|
||||||
|
bool regularAvailable = fontFamily.IsStyleAvailable(FontStyle.Regular);
|
||||||
|
if (regularAvailable)
|
||||||
|
{
|
||||||
|
fontStyle = FontStyle.Regular;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (boldAvailable)
|
||||||
|
{
|
||||||
|
fontStyle = FontStyle.Bold;
|
||||||
|
}
|
||||||
|
else if (italicAvailable)
|
||||||
|
{
|
||||||
|
fontStyle = FontStyle.Italic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Font(fontFamily, fontSize, fontStyle, GraphicsUnit.Pixel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -487,7 +488,7 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
_textBox.ForeColor = lineColor;
|
_textBox.ForeColor = lineColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void textBox_KeyDown(object sender, KeyEventArgs e)
|
private void TextBox_KeyDown(object sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
// ESC and Enter/Return (w/o Shift) hide text editor
|
// ESC and Enter/Return (w/o Shift) hide text editor
|
||||||
if (e.KeyCode == Keys.Escape || ((e.KeyCode == Keys.Return || e.KeyCode == Keys.Enter) && e.Modifiers == Keys.None))
|
if (e.KeyCode == Keys.Escape || ((e.KeyCode == Keys.Return || e.KeyCode == Keys.Enter) && e.Modifiers == Keys.None))
|
||||||
|
@ -518,7 +519,7 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void textBox_LostFocus(object sender, EventArgs e)
|
private void TextBox_LostFocus(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
// next change will be made undoable
|
// next change will be made undoable
|
||||||
makeUndoable = true;
|
makeUndoable = true;
|
||||||
|
@ -593,12 +594,11 @@ namespace Greenshot.Addon.LegacyEditor.Drawing
|
||||||
{
|
{
|
||||||
shadowRect = shadowRect.Inflate(-textOffset, -textOffset);
|
shadowRect = shadowRect.Inflate(-textOffset, -textOffset);
|
||||||
}
|
}
|
||||||
using (Brush fontBrush = new SolidBrush(Color.FromArgb(alpha, 100, 100, 100)))
|
|
||||||
{
|
using Brush fontBrush = new SolidBrush(Color.FromArgb(alpha, 100, 100, 100));
|
||||||
graphics.DrawString(text, font, fontBrush, (Rectangle)shadowRect, stringFormat);
|
graphics.DrawString(text, font, fontBrush, (Rectangle)shadowRect, stringFormat);
|
||||||
currentStep++;
|
currentStep++;
|
||||||
alpha = alpha - basealpha / steps;
|
alpha = alpha - basealpha / steps;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,13 +66,13 @@ namespace Greenshot.Addon.LegacyEditor
|
||||||
{
|
{
|
||||||
switch (fieldType.ValueType)
|
switch (fieldType.ValueType)
|
||||||
{
|
{
|
||||||
case var intType when fieldType.ValueType == typeof(int):
|
case var _ when fieldType.ValueType == typeof(int):
|
||||||
fieldValue = Convert.ToInt32(preferredValue);
|
fieldValue = Convert.ToInt32(preferredValue);
|
||||||
break;
|
break;
|
||||||
case var boolType when fieldType.ValueType == typeof(bool):
|
case var _ when fieldType.ValueType == typeof(bool):
|
||||||
fieldValue = Convert.ToBoolean(preferredValue);
|
fieldValue = Convert.ToBoolean(preferredValue);
|
||||||
break;
|
break;
|
||||||
case var colorType when fieldType.ValueType == typeof(Color):
|
case var _ when fieldType.ValueType == typeof(Color):
|
||||||
var color = Color.FromName(preferredStringValue);
|
var color = Color.FromName(preferredStringValue);
|
||||||
fieldValue = color;
|
fieldValue = color;
|
||||||
if (Color.Empty == color)
|
if (Color.Empty == color)
|
||||||
|
@ -80,22 +80,22 @@ namespace Greenshot.Addon.LegacyEditor
|
||||||
fieldValue = Color.FromArgb(Convert.ToInt32(preferredValue));
|
fieldValue = Color.FromArgb(Convert.ToInt32(preferredValue));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case var alignType when fieldType.ValueType == typeof(StringAlignment):
|
case var _ when fieldType.ValueType == typeof(StringAlignment):
|
||||||
fieldValue = Enum.Parse(typeof(StringAlignment), preferredStringValue, true);
|
fieldValue = Enum.Parse(typeof(StringAlignment), preferredStringValue, true);
|
||||||
break;
|
break;
|
||||||
case var fieldFlagType when fieldType.ValueType == typeof(FieldFlag):
|
case var _ when fieldType.ValueType == typeof(FieldFlag):
|
||||||
fieldValue = Enum.Parse(typeof(FieldFlag), preferredStringValue, true);
|
fieldValue = Enum.Parse(typeof(FieldFlag), preferredStringValue, true);
|
||||||
break;
|
break;
|
||||||
case var preparedFilterType when fieldType.ValueType == typeof(PreparedFilter):
|
case var _ when fieldType.ValueType == typeof(PreparedFilter):
|
||||||
fieldValue = Enum.Parse(typeof(PreparedFilter), preferredStringValue, true);
|
fieldValue = Enum.Parse(typeof(PreparedFilter), preferredStringValue, true);
|
||||||
break;
|
break;
|
||||||
case var arrowHeadCombinationType when fieldType.ValueType == typeof(ArrowContainer.ArrowHeadCombination):
|
case var _ when fieldType.ValueType == typeof(ArrowContainer.ArrowHeadCombination):
|
||||||
fieldValue = Enum.Parse(typeof(ArrowContainer.ArrowHeadCombination), preferredStringValue, true);
|
fieldValue = Enum.Parse(typeof(ArrowContainer.ArrowHeadCombination), preferredStringValue, true);
|
||||||
break;
|
break;
|
||||||
case var floatType when fieldType.ValueType == typeof(float):
|
case var _ when fieldType.ValueType == typeof(float):
|
||||||
fieldValue = Convert.ToSingle(preferredValue, CultureInfo.InvariantCulture);
|
fieldValue = Convert.ToSingle(preferredValue, CultureInfo.InvariantCulture);
|
||||||
break;
|
break;
|
||||||
case var doubleType when fieldType.ValueType == typeof(double):
|
case var _ when fieldType.ValueType == typeof(double):
|
||||||
fieldValue = Convert.ToDouble(preferredValue, CultureInfo.InvariantCulture);
|
fieldValue = Convert.ToDouble(preferredValue, CultureInfo.InvariantCulture);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -41,8 +41,9 @@ namespace Greenshot.Addon.LegacyEditor.Forms {
|
||||||
components.Dispose();
|
components.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Make sure that clipboard changes are not longer processed.
|
_destinationScaleHandler.Dispose();
|
||||||
_clipboardSubscription?.Dispose();
|
// Make sure that clipboard changes are not longer processed.
|
||||||
|
_clipboardSubscription?.Dispose();
|
||||||
// Remove all other stuff
|
// Remove all other stuff
|
||||||
_disposables.Dispose();
|
_disposables.Dispose();
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
|
|
|
@ -350,24 +350,22 @@ namespace Greenshot.Addon.LegacyEditor.Forms
|
||||||
/// <param name="e"></param>
|
/// <param name="e"></param>
|
||||||
private void PropertiesToolStrip_Paint(object sender, PaintEventArgs e)
|
private void PropertiesToolStrip_Paint(object sender, PaintEventArgs e)
|
||||||
{
|
{
|
||||||
using (var cbBorderPen = new Pen(SystemColors.ActiveBorder))
|
using var cbBorderPen = new Pen(SystemColors.ActiveBorder);
|
||||||
|
// Loop over all items in the propertiesToolStrip
|
||||||
|
foreach (ToolStripItem item in propertiesToolStrip.Items)
|
||||||
{
|
{
|
||||||
// Loop over all items in the propertiesToolStrip
|
// Only ToolStripComboBox that are visible
|
||||||
foreach (ToolStripItem item in propertiesToolStrip.Items)
|
if (!(item is ToolStripComboBox cb) || !cb.Visible)
|
||||||
{
|
{
|
||||||
// Only ToolStripComboBox that are visible
|
continue;
|
||||||
if (!(item is ToolStripComboBox cb) || !cb.Visible)
|
}
|
||||||
{
|
// Calculate the rectangle
|
||||||
continue;
|
if (cb.ComboBox != null)
|
||||||
}
|
{
|
||||||
// Calculate the rectangle
|
var r = new Rectangle(cb.ComboBox.Location.X - 1, cb.ComboBox.Location.Y - 1, cb.ComboBox.Size.Width + 1, cb.ComboBox.Size.Height + 1);
|
||||||
if (cb.ComboBox != null)
|
|
||||||
{
|
|
||||||
var r = new Rectangle(cb.ComboBox.Location.X - 1, cb.ComboBox.Location.Y - 1, cb.ComboBox.Size.Width + 1, cb.ComboBox.Size.Height + 1);
|
|
||||||
|
|
||||||
// Draw the rectangle
|
// Draw the rectangle
|
||||||
e.Graphics.DrawRectangle(cbBorderPen, r);
|
e.Graphics.DrawRectangle(cbBorderPen, r);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -901,15 +899,14 @@ namespace Greenshot.Addon.LegacyEditor.Forms
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
using (Stream streamWrite = File.OpenWrite(saveFileDialog.FileName))
|
|
||||||
{
|
using Stream streamWrite = File.OpenWrite(saveFileDialog.FileName);
|
||||||
_surface.SaveElementsToStream(streamWrite);
|
_surface.SaveElementsToStream(streamWrite);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadElementsToolStripMenuItemClick(object sender, EventArgs e)
|
private void LoadElementsToolStripMenuItemClick(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
var openFileDialog = new OpenFileDialog
|
using var openFileDialog = new OpenFileDialog
|
||||||
{
|
{
|
||||||
Filter = "Greenshot templates (*.gst)|*.gst"
|
Filter = "Greenshot templates (*.gst)|*.gst"
|
||||||
};
|
};
|
||||||
|
@ -1105,14 +1102,12 @@ namespace Greenshot.Addon.LegacyEditor.Forms
|
||||||
private void BtnResizeClick(object sender, EventArgs e)
|
private void BtnResizeClick(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
var resizeEffect = new ResizeEffect(_surface.Screenshot.Width, _surface.Screenshot.Height, true);
|
var resizeEffect = new ResizeEffect(_surface.Screenshot.Width, _surface.Screenshot.Height, true);
|
||||||
using (var resizeSettingsForm = _resizeSettingsFormFactory(resizeEffect))
|
using var resizeSettingsForm = _resizeSettingsFormFactory(resizeEffect);
|
||||||
|
var result = resizeSettingsForm.Value.ShowDialog(this);
|
||||||
|
if (result == DialogResult.OK)
|
||||||
{
|
{
|
||||||
var result = resizeSettingsForm.Value.ShowDialog(this);
|
_surface.ApplyBitmapEffect(resizeEffect);
|
||||||
if (result == DialogResult.OK)
|
UpdateUndoRedoSurfaceDependencies();
|
||||||
{
|
|
||||||
_surface.ApplyBitmapEffect(resizeEffect);
|
|
||||||
UpdateUndoRedoSurfaceDependencies();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
using System.ComponentModel;
|
|
||||||
using Dapplo.Config.Language;
|
using Dapplo.Config.Language;
|
||||||
|
|
||||||
namespace Greenshot.Addon.Lutim.Configuration
|
namespace Greenshot.Addon.Lutim.Configuration
|
||||||
|
|
|
@ -48,10 +48,8 @@ namespace Greenshot.Addon.Lutim.Entities
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
using (var memoryStream = new MemoryStream(Convert.FromBase64String(ThumbBase64)))
|
using var memoryStream = new MemoryStream(Convert.FromBase64String(ThumbBase64));
|
||||||
{
|
return Image.FromStream(memoryStream);
|
||||||
return Image.FromStream(memoryStream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,6 @@ using Dapplo.HttpExtensions;
|
||||||
using Dapplo.Log;
|
using Dapplo.Log;
|
||||||
using Greenshot.Addon.Lutim.Configuration;
|
using Greenshot.Addon.Lutim.Configuration;
|
||||||
using Greenshot.Addon.Lutim.Entities;
|
using Greenshot.Addon.Lutim.Entities;
|
||||||
using Greenshot.Addons.Core;
|
|
||||||
using Greenshot.Addons.Interfaces;
|
using Greenshot.Addons.Interfaces;
|
||||||
|
|
||||||
namespace Greenshot.Addon.Lutim
|
namespace Greenshot.Addon.Lutim
|
||||||
|
@ -41,12 +40,10 @@ namespace Greenshot.Addon.Lutim
|
||||||
{
|
{
|
||||||
private static readonly LogSource Log = new LogSource();
|
private static readonly LogSource Log = new LogSource();
|
||||||
private readonly ILutimConfiguration _lutimConfiguration;
|
private readonly ILutimConfiguration _lutimConfiguration;
|
||||||
private readonly ICoreConfiguration _coreConfiguration;
|
|
||||||
|
|
||||||
public LutimApi(ILutimConfiguration lutimConfiguration, ICoreConfiguration coreConfiguration)
|
public LutimApi(ILutimConfiguration lutimConfiguration)
|
||||||
{
|
{
|
||||||
_lutimConfiguration = lutimConfiguration;
|
_lutimConfiguration = lutimConfiguration;
|
||||||
_coreConfiguration = coreConfiguration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -87,13 +84,13 @@ namespace Greenshot.Addon.Lutim
|
||||||
}
|
}
|
||||||
catch (ArgumentException)
|
catch (ArgumentException)
|
||||||
{
|
{
|
||||||
Log.Info().WriteLine("Bad format of lutim history item for short {0}", key);
|
Log.Info().WriteLine("Bad format of Lutim history item for short {0}", key);
|
||||||
_lutimConfiguration.LutimUploadHistory.Remove(key);
|
_lutimConfiguration.LutimUploadHistory.Remove(key);
|
||||||
_lutimConfiguration.RuntimeLutimHistory.Remove(key);
|
_lutimConfiguration.RuntimeLutimHistory.Remove(key);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Log.Error().WriteLine(e, "Problem loading lutim history for short " + key);
|
Log.Error().WriteLine(e, "Problem loading Lutim history for short " + key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,12 +84,11 @@ namespace Greenshot.Addon.Lutim {
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override IBitmapWithNativeSupport DisplayIcon {
|
public override IBitmapWithNativeSupport DisplayIcon {
|
||||||
get {
|
get
|
||||||
|
{
|
||||||
// TODO: Optimize this by caching
|
// TODO: Optimize this by caching
|
||||||
using (var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "Lutim.png"))
|
using var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "Lutim.png");
|
||||||
{
|
return BitmapHelper.FromStream(bitmapStream);
|
||||||
return BitmapHelper.FromStream(bitmapStream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,11 +154,9 @@ namespace Greenshot.Addon.Lutim {
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var clipboardAccessToken = ClipboardNative.Access())
|
using var clipboardAccessToken = ClipboardNative.Access();
|
||||||
{
|
clipboardAccessToken.ClearContents();
|
||||||
clipboardAccessToken.ClearContents();
|
clipboardAccessToken.SetAsUrl(uploadUrl);
|
||||||
clipboardAccessToken.SetAsUrl(uploadUrl);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
@ -181,11 +181,9 @@ namespace Greenshot.Addon.Lutim.ViewModels
|
||||||
public void CopyToClipboard()
|
public void CopyToClipboard()
|
||||||
{
|
{
|
||||||
// TODO: Build url
|
// TODO: Build url
|
||||||
using (var clipboardAccessToken = ClipboardNative.Access())
|
using var clipboardAccessToken = ClipboardNative.Access();
|
||||||
{
|
clipboardAccessToken.ClearContents();
|
||||||
clipboardAccessToken.ClearContents();
|
clipboardAccessToken.SetAsUrl(SelectedLutim.LutimInfo.Short);
|
||||||
clipboardAccessToken.SetAsUrl(SelectedLutim.LutimInfo.Short);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -49,17 +49,18 @@ namespace Greenshot.Addon.Office.Destinations
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor used for dependency wiring
|
/// Constructor used for dependency wiring
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="oneNoteExporter">OneNoteExporter</param>
|
||||||
/// <param name="coreConfiguration">ICoreConfiguration</param>
|
/// <param name="coreConfiguration">ICoreConfiguration</param>
|
||||||
/// <param name="greenshotLanguage">IGreenshotLanguage</param>
|
/// <param name="greenshotLanguage">IGreenshotLanguage</param>
|
||||||
/// <param name="exportNotification">ExportNotification</param>
|
/// <param name="exportNotification">ExportNotification</param>
|
||||||
public OneNoteDestination(
|
public OneNoteDestination(
|
||||||
OneNoteExporter oneNoteExporter,
|
OneNoteExporter oneNoteExporter,
|
||||||
ICoreConfiguration coreConfiguration,
|
ICoreConfiguration coreConfiguration,
|
||||||
IGreenshotLanguage greenshotLanguage,
|
IGreenshotLanguage greenshotLanguage,
|
||||||
ExportNotification exportNotification
|
ExportNotification exportNotification
|
||||||
) : base(coreConfiguration, greenshotLanguage)
|
) : base(coreConfiguration, greenshotLanguage)
|
||||||
{
|
{
|
||||||
this._oneNoteExporter = oneNoteExporter;
|
_oneNoteExporter = oneNoteExporter;
|
||||||
_exportNotification = exportNotification;
|
_exportNotification = exportNotification;
|
||||||
_exePath = PluginUtils.GetExePath("ONENOTE.EXE");
|
_exePath = PluginUtils.GetExePath("ONENOTE.EXE");
|
||||||
if (_exePath != null && !File.Exists(_exePath))
|
if (_exePath != null && !File.Exists(_exePath))
|
||||||
|
@ -71,6 +72,7 @@ namespace Greenshot.Addon.Office.Destinations
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor used for dependency wiring, and being able to specify a page
|
/// Constructor used for dependency wiring, and being able to specify a page
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="oneNoteExporter">OneNoteExporter</param>
|
||||||
/// <param name="page">OneNotePage</param>
|
/// <param name="page">OneNotePage</param>
|
||||||
/// <param name="coreConfiguration">ICoreConfiguration</param>
|
/// <param name="coreConfiguration">ICoreConfiguration</param>
|
||||||
/// <param name="greenshotLanguage">IGreenshotLanguage</param>
|
/// <param name="greenshotLanguage">IGreenshotLanguage</param>
|
||||||
|
|
|
@ -49,10 +49,8 @@ namespace Greenshot.Addon.Office
|
||||||
private bool HasApplication(string applicationName)
|
private bool HasApplication(string applicationName)
|
||||||
{
|
{
|
||||||
string registryPath = $@"{applicationName}\CLSID";
|
string registryPath = $@"{applicationName}\CLSID";
|
||||||
using (var registryKey = Registry.ClassesRoot.OpenSubKey(registryPath, false))
|
using var registryKey = Registry.ClassesRoot.OpenSubKey(registryPath, false);
|
||||||
{
|
return registryKey != null && Guid.TryParse(registryKey.GetValue(null) as string, out _);
|
||||||
return registryKey != null && Guid.TryParse(registryKey.GetValue(null) as string, out _);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -82,24 +82,19 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
/// <returns>IEnumerable with names of the workbooks</returns>
|
/// <returns>IEnumerable with names of the workbooks</returns>
|
||||||
public static IEnumerable<string> GetWorkbooks()
|
public static IEnumerable<string> GetWorkbooks()
|
||||||
{
|
{
|
||||||
using (var excelApplication = GetExcelApplication())
|
using var excelApplication = GetExcelApplication();
|
||||||
|
if ((excelApplication == null) || (excelApplication.ComObject == null))
|
||||||
{
|
{
|
||||||
if ((excelApplication == null) || (excelApplication.ComObject == null))
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var workbooks = DisposableCom.Create(excelApplication.ComObject.Workbooks);
|
||||||
|
for (int i = 1; i <= workbooks.ComObject.Count; i++)
|
||||||
|
{
|
||||||
|
using var workbook = DisposableCom.Create(workbooks.ComObject[i]);
|
||||||
|
if (workbook != null)
|
||||||
{
|
{
|
||||||
yield break;
|
yield return workbook.ComObject.Name;
|
||||||
}
|
|
||||||
using (var workbooks = DisposableCom.Create(excelApplication.ComObject.Workbooks))
|
|
||||||
{
|
|
||||||
for (int i = 1; i <= workbooks.ComObject.Count; i++)
|
|
||||||
{
|
|
||||||
using (var workbook = DisposableCom.Create(workbooks.ComObject[i]))
|
|
||||||
{
|
|
||||||
if (workbook != null)
|
|
||||||
{
|
|
||||||
yield return workbook.ComObject.Name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,24 +124,19 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
/// <param name="imageSize"></param>
|
/// <param name="imageSize"></param>
|
||||||
public static void InsertIntoExistingWorkbook(string workbookName, string tmpFile, Size imageSize)
|
public static void InsertIntoExistingWorkbook(string workbookName, string tmpFile, Size imageSize)
|
||||||
{
|
{
|
||||||
using (var excelApplication = GetExcelApplication())
|
using var excelApplication = GetExcelApplication();
|
||||||
|
if ((excelApplication == null) || (excelApplication.ComObject == null))
|
||||||
{
|
{
|
||||||
if ((excelApplication == null) || (excelApplication.ComObject == null))
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var workbooks = DisposableCom.Create(excelApplication.ComObject.Workbooks);
|
||||||
|
for (int i = 1; i <= workbooks.ComObject.Count; i++)
|
||||||
|
{
|
||||||
|
using var workbook = DisposableCom.Create((_Workbook)workbooks.ComObject[i]);
|
||||||
|
if ((workbook != null) && workbook.ComObject.Name.StartsWith(workbookName))
|
||||||
{
|
{
|
||||||
return;
|
InsertIntoExistingWorkbook(workbook, tmpFile, imageSize);
|
||||||
}
|
|
||||||
using (var workbooks = DisposableCom.Create(excelApplication.ComObject.Workbooks))
|
|
||||||
{
|
|
||||||
for (int i = 1; i <= workbooks.ComObject.Count; i++)
|
|
||||||
{
|
|
||||||
using (var workbook = DisposableCom.Create((_Workbook)workbooks.ComObject[i]))
|
|
||||||
{
|
|
||||||
if ((workbook != null) && workbook.ComObject.Name.StartsWith(workbookName))
|
|
||||||
{
|
|
||||||
InsertIntoExistingWorkbook(workbook, tmpFile, imageSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,40 +149,33 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
/// <param name="imageSize"></param>
|
/// <param name="imageSize"></param>
|
||||||
private static void InsertIntoExistingWorkbook(IDisposableCom<_Workbook> workbook, string tmpFile, Size imageSize)
|
private static void InsertIntoExistingWorkbook(IDisposableCom<_Workbook> workbook, string tmpFile, Size imageSize)
|
||||||
{
|
{
|
||||||
using (var workSheet = DisposableCom.Create(workbook.ComObject.ActiveSheet as Worksheet))
|
using var workSheet = DisposableCom.Create(workbook.ComObject.ActiveSheet as Worksheet);
|
||||||
|
if (workSheet == null)
|
||||||
{
|
{
|
||||||
if (workSheet == null)
|
return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
using (var shapes = DisposableCom.Create(workSheet.ComObject.Shapes))
|
|
||||||
{
|
|
||||||
if (shapes == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var shape = DisposableCom.Create(shapes.ComObject.AddPicture(tmpFile, MsoTriState.msoFalse, MsoTriState.msoTrue, 0, 0, imageSize.Width, imageSize.Height)))
|
|
||||||
{
|
|
||||||
if (shape == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
shape.ComObject.Top = 40;
|
|
||||||
shape.ComObject.Left = 40;
|
|
||||||
shape.ComObject.LockAspectRatio = MsoTriState.msoTrue;
|
|
||||||
shape.ComObject.ScaleHeight(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromTopLeft);
|
|
||||||
shape.ComObject.ScaleWidth(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromTopLeft);
|
|
||||||
workbook.ComObject.Activate();
|
|
||||||
using (var application = DisposableCom.Create(workbook.ComObject.Application))
|
|
||||||
{
|
|
||||||
var excelWindow = InteropWindowFactory.CreateFor((IntPtr) application.ComObject.Hwnd);
|
|
||||||
excelWindow.ToForegroundAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using var shapes = DisposableCom.Create(workSheet.ComObject.Shapes);
|
||||||
|
if (shapes == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var shape = DisposableCom.Create(shapes.ComObject.AddPicture(tmpFile, MsoTriState.msoFalse, MsoTriState.msoTrue, 0, 0, imageSize.Width, imageSize.Height));
|
||||||
|
if (shape == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
shape.ComObject.Top = 40;
|
||||||
|
shape.ComObject.Left = 40;
|
||||||
|
shape.ComObject.LockAspectRatio = MsoTriState.msoTrue;
|
||||||
|
shape.ComObject.ScaleHeight(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromTopLeft);
|
||||||
|
shape.ComObject.ScaleWidth(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromTopLeft);
|
||||||
|
workbook.ComObject.Activate();
|
||||||
|
using var application = DisposableCom.Create(workbook.ComObject.Application);
|
||||||
|
var excelWindow = InteropWindowFactory.CreateFor((IntPtr) application.ComObject.Hwnd);
|
||||||
|
excelWindow.ToForegroundAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -202,22 +185,16 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
/// <param name="imageSize"></param>
|
/// <param name="imageSize"></param>
|
||||||
public static void InsertIntoNewWorkbook(string tmpFile, Size imageSize)
|
public static void InsertIntoNewWorkbook(string tmpFile, Size imageSize)
|
||||||
{
|
{
|
||||||
using (var excelApplication = GetOrCreateExcelApplication())
|
using var excelApplication = GetOrCreateExcelApplication();
|
||||||
|
if (excelApplication == null)
|
||||||
{
|
{
|
||||||
if (excelApplication == null)
|
return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
excelApplication.ComObject.Visible = true;
|
|
||||||
using (var workbooks = DisposableCom.Create(excelApplication.ComObject.Workbooks))
|
|
||||||
{
|
|
||||||
using (var workbook = DisposableCom.Create((_Workbook)workbooks.ComObject.Add()))
|
|
||||||
{
|
|
||||||
InsertIntoExistingWorkbook(workbook, tmpFile, imageSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
excelApplication.ComObject.Visible = true;
|
||||||
|
using var workbooks = DisposableCom.Create(excelApplication.ComObject.Workbooks);
|
||||||
|
using var workbook = DisposableCom.Create((_Workbook)workbooks.ComObject.Add());
|
||||||
|
InsertIntoExistingWorkbook(workbook, tmpFile, imageSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,22 +57,20 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
/// <returns>bool true if export worked</returns>
|
/// <returns>bool true if export worked</returns>
|
||||||
public bool ExportToNewPage(ISurface surfaceToUpload)
|
public bool ExportToNewPage(ISurface surfaceToUpload)
|
||||||
{
|
{
|
||||||
using (var oneNoteApplication = GetOrCreateOneNoteApplication())
|
using var oneNoteApplication = GetOrCreateOneNoteApplication();
|
||||||
|
var newPage = new OneNotePage();
|
||||||
|
string unfiledNotesSectionId = GetSectionId(oneNoteApplication, SpecialLocation.slUnfiledNotesSection);
|
||||||
|
if (unfiledNotesSectionId == null)
|
||||||
{
|
{
|
||||||
var newPage = new OneNotePage();
|
return false;
|
||||||
string unfiledNotesSectionId = GetSectionId(oneNoteApplication, SpecialLocation.slUnfiledNotesSection);
|
|
||||||
if (unfiledNotesSectionId == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
string pageId;
|
|
||||||
oneNoteApplication.ComObject.CreateNewPage(unfiledNotesSectionId, out pageId, NewPageStyle.npsDefault);
|
|
||||||
newPage.Id = pageId;
|
|
||||||
// Set the new name, this is automatically done in the export to page
|
|
||||||
newPage.Name = surfaceToUpload.CaptureDetails.Title;
|
|
||||||
return ExportToPage(oneNoteApplication, surfaceToUpload, newPage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string pageId;
|
||||||
|
oneNoteApplication.ComObject.CreateNewPage(unfiledNotesSectionId, out pageId, NewPageStyle.npsDefault);
|
||||||
|
newPage.Id = pageId;
|
||||||
|
// Set the new name, this is automatically done in the export to page
|
||||||
|
newPage.Name = surfaceToUpload.CaptureDetails.Title;
|
||||||
|
return ExportToPage(oneNoteApplication, surfaceToUpload, newPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -83,10 +81,8 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
/// <returns>bool true if everything worked</returns>
|
/// <returns>bool true if everything worked</returns>
|
||||||
public bool ExportToPage(ISurface surfaceToUpload, OneNotePage page)
|
public bool ExportToPage(ISurface surfaceToUpload, OneNotePage page)
|
||||||
{
|
{
|
||||||
using (var oneNoteApplication = GetOrCreateOneNoteApplication())
|
using var oneNoteApplication = GetOrCreateOneNoteApplication();
|
||||||
{
|
return ExportToPage(oneNoteApplication, surfaceToUpload, page);
|
||||||
return ExportToPage(oneNoteApplication, surfaceToUpload, page);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -103,25 +99,23 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var pngStream = new MemoryStream())
|
using var pngStream = new MemoryStream();
|
||||||
|
var pngOutputSettings = new SurfaceOutputSettings(_coreConfiguration, OutputFormats.png, 100, false);
|
||||||
|
ImageOutput.SaveToStream(surfaceToUpload, pngStream, pngOutputSettings);
|
||||||
|
var base64String = Convert.ToBase64String(pngStream.GetBuffer());
|
||||||
|
var imageXmlStr = string.Format(XmlImageContent, base64String, surfaceToUpload.Screenshot.Width, surfaceToUpload.Screenshot.Height);
|
||||||
|
var pageChangesXml = string.Format(XmlOutline, imageXmlStr, page.Id, OnenoteNamespace2010, page.Name);
|
||||||
|
Log.Info().WriteLine("Sending XML: {0}", pageChangesXml);
|
||||||
|
oneNoteApplication.ComObject.UpdatePageContent(pageChangesXml, DateTime.MinValue, XMLSchema.xs2010, false);
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var pngOutputSettings = new SurfaceOutputSettings(_coreConfiguration, OutputFormats.png, 100, false);
|
oneNoteApplication.ComObject.NavigateTo(page.Id, null, false);
|
||||||
ImageOutput.SaveToStream(surfaceToUpload, pngStream, pngOutputSettings);
|
|
||||||
var base64String = Convert.ToBase64String(pngStream.GetBuffer());
|
|
||||||
var imageXmlStr = string.Format(XmlImageContent, base64String, surfaceToUpload.Screenshot.Width, surfaceToUpload.Screenshot.Height);
|
|
||||||
var pageChangesXml = string.Format(XmlOutline, imageXmlStr, page.Id, OnenoteNamespace2010, page.Name);
|
|
||||||
Log.Info().WriteLine("Sending XML: {0}", pageChangesXml);
|
|
||||||
oneNoteApplication.ComObject.UpdatePageContent(pageChangesXml, DateTime.MinValue, XMLSchema.xs2010, false);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
oneNoteApplication.ComObject.NavigateTo(page.Id, null, false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Warn().WriteLine(ex, "Unable to navigate to the target page");
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Warn().WriteLine(ex, "Unable to navigate to the target page");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -166,80 +160,78 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
var pages = new List<OneNotePage>();
|
var pages = new List<OneNotePage>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var oneNoteApplication = GetOrCreateOneNoteApplication())
|
using var oneNoteApplication = GetOrCreateOneNoteApplication();
|
||||||
|
if (oneNoteApplication != null)
|
||||||
{
|
{
|
||||||
if (oneNoteApplication != null)
|
// ReSharper disable once RedundantAssignment
|
||||||
|
string notebookXml = "";
|
||||||
|
oneNoteApplication.ComObject.GetHierarchy("", HierarchyScope.hsPages, out notebookXml, XMLSchema.xs2010);
|
||||||
|
if (!string.IsNullOrEmpty(notebookXml))
|
||||||
{
|
{
|
||||||
// ReSharper disable once RedundantAssignment
|
Log.Debug().WriteLine(notebookXml);
|
||||||
string notebookXml = "";
|
StringReader reader = null;
|
||||||
oneNoteApplication.ComObject.GetHierarchy("", HierarchyScope.hsPages, out notebookXml, XMLSchema.xs2010);
|
try
|
||||||
if (!string.IsNullOrEmpty(notebookXml))
|
|
||||||
{
|
{
|
||||||
Log.Debug().WriteLine(notebookXml);
|
reader = new StringReader(notebookXml);
|
||||||
StringReader reader = null;
|
using var xmlReader = new XmlTextReader(reader);
|
||||||
try
|
reader = null;
|
||||||
|
OneNoteSection currentSection = null;
|
||||||
|
OneNoteNotebook currentNotebook = null;
|
||||||
|
while (xmlReader.Read())
|
||||||
{
|
{
|
||||||
reader = new StringReader(notebookXml);
|
if ("one:Notebook".Equals(xmlReader.Name))
|
||||||
using (var xmlReader = new XmlTextReader(reader))
|
|
||||||
{
|
{
|
||||||
reader = null;
|
string id = xmlReader.GetAttribute("ID");
|
||||||
OneNoteSection currentSection = null;
|
if ((id != null) && ((currentNotebook == null) || !id.Equals(currentNotebook.Id)))
|
||||||
OneNoteNotebook currentNotebook = null;
|
|
||||||
while (xmlReader.Read())
|
|
||||||
{
|
{
|
||||||
if ("one:Notebook".Equals(xmlReader.Name))
|
currentNotebook = new OneNoteNotebook
|
||||||
{
|
{
|
||||||
string id = xmlReader.GetAttribute("ID");
|
Id = xmlReader.GetAttribute("ID"),
|
||||||
if ((id != null) && ((currentNotebook == null) || !id.Equals(currentNotebook.Id)))
|
Name = xmlReader.GetAttribute("name")
|
||||||
{
|
};
|
||||||
currentNotebook = new OneNoteNotebook();
|
|
||||||
currentNotebook.Id = xmlReader.GetAttribute("ID");
|
|
||||||
currentNotebook.Name = xmlReader.GetAttribute("name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ("one:Section".Equals(xmlReader.Name))
|
|
||||||
{
|
|
||||||
string id = xmlReader.GetAttribute("ID");
|
|
||||||
if ((id != null) && ((currentSection == null) || !id.Equals(currentSection.Id)))
|
|
||||||
{
|
|
||||||
currentSection = new OneNoteSection
|
|
||||||
{
|
|
||||||
Id = xmlReader.GetAttribute("ID"),
|
|
||||||
Name = xmlReader.GetAttribute("name"),
|
|
||||||
Parent = currentNotebook
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ("one:Page".Equals(xmlReader.Name))
|
|
||||||
{
|
|
||||||
// Skip deleted items
|
|
||||||
if ("true".Equals(xmlReader.GetAttribute("isInRecycleBin")))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var page = new OneNotePage
|
|
||||||
{
|
|
||||||
Parent = currentSection,
|
|
||||||
Name = xmlReader.GetAttribute("name"),
|
|
||||||
Id = xmlReader.GetAttribute("ID")
|
|
||||||
};
|
|
||||||
if ((page.Id == null) || (page.Name == null))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
page.IsCurrentlyViewed = "true".Equals(xmlReader.GetAttribute("isCurrentlyViewed"));
|
|
||||||
pages.Add(page);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if ("one:Section".Equals(xmlReader.Name))
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (reader != null)
|
|
||||||
{
|
{
|
||||||
reader.Dispose();
|
string id = xmlReader.GetAttribute("ID");
|
||||||
|
if (id != null && (currentSection == null || !id.Equals(currentSection.Id)))
|
||||||
|
{
|
||||||
|
currentSection = new OneNoteSection
|
||||||
|
{
|
||||||
|
Id = xmlReader.GetAttribute("ID"),
|
||||||
|
Name = xmlReader.GetAttribute("name"),
|
||||||
|
Parent = currentNotebook
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if ("one:Page".Equals(xmlReader.Name))
|
||||||
|
{
|
||||||
|
// Skip deleted items
|
||||||
|
if ("true".Equals(xmlReader.GetAttribute("isInRecycleBin")))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var page = new OneNotePage
|
||||||
|
{
|
||||||
|
Parent = currentSection,
|
||||||
|
Name = xmlReader.GetAttribute("name"),
|
||||||
|
Id = xmlReader.GetAttribute("ID")
|
||||||
|
};
|
||||||
|
if ((page.Id == null) || (page.Name == null))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
page.IsCurrentlyViewed = "true".Equals(xmlReader.GetAttribute("isCurrentlyViewed"));
|
||||||
|
pages.Add(page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (reader != null)
|
||||||
|
{
|
||||||
|
reader.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,20 +286,18 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
reader = new StringReader(notebookXml);
|
reader = new StringReader(notebookXml);
|
||||||
using (var xmlReader = new XmlTextReader(reader))
|
using var xmlReader = new XmlTextReader(reader);
|
||||||
|
while (xmlReader.Read())
|
||||||
{
|
{
|
||||||
while (xmlReader.Read())
|
if (!"one:Section".Equals(xmlReader.Name))
|
||||||
{
|
{
|
||||||
if (!"one:Section".Equals(xmlReader.Name))
|
continue;
|
||||||
{
|
}
|
||||||
continue;
|
string id = xmlReader.GetAttribute("ID");
|
||||||
}
|
string path = xmlReader.GetAttribute("path");
|
||||||
string id = xmlReader.GetAttribute("ID");
|
if (unfiledNotesPath.Equals(path))
|
||||||
string path = xmlReader.GetAttribute("path");
|
{
|
||||||
if (unfiledNotesPath.Equals(path))
|
return id;
|
||||||
{
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,100 +86,94 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
if (_outlookVersion.Major >= (int)OfficeVersions.Office2013)
|
if (_outlookVersion.Major >= (int)OfficeVersions.Office2013)
|
||||||
{
|
{
|
||||||
// Check inline "panel" for Outlook 2013
|
// Check inline "panel" for Outlook 2013
|
||||||
using (var activeExplorer = DisposableCom.Create((_Explorer)outlookApplication.ComObject.ActiveExplorer()))
|
using var activeExplorer = DisposableCom.Create((_Explorer)outlookApplication.ComObject.ActiveExplorer());
|
||||||
|
// Only if we have one and if the capture is the one we selected
|
||||||
|
if ((activeExplorer != null) && activeExplorer.ComObject.Caption.StartsWith(inspectorCaption))
|
||||||
{
|
{
|
||||||
// Only if we have one and if the capture is the one we selected
|
var untypedInlineResponse = activeExplorer.ComObject.ActiveInlineResponse;
|
||||||
if ((activeExplorer != null) && activeExplorer.ComObject.Caption.StartsWith(inspectorCaption))
|
using (DisposableCom.Create(untypedInlineResponse))
|
||||||
{
|
{
|
||||||
var untypedInlineResponse = activeExplorer.ComObject.ActiveInlineResponse;
|
switch (untypedInlineResponse)
|
||||||
using (DisposableCom.Create(untypedInlineResponse))
|
|
||||||
{
|
{
|
||||||
switch (untypedInlineResponse)
|
case MailItem mailItem:
|
||||||
{
|
if (!mailItem.Sent)
|
||||||
case MailItem mailItem:
|
{
|
||||||
if (!mailItem.Sent)
|
return ExportToInspector(null, activeExplorer, mailItem.Class, mailItem, tmpFile, attachmentName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AppointmentItem appointmentItem:
|
||||||
|
if ((_outlookVersion.Major >= (int)OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(appointmentItem.Organizer) && appointmentItem.Organizer.Equals(_currentUser))
|
||||||
{
|
{
|
||||||
return ExportToInspector(null, activeExplorer, mailItem.Class, mailItem, tmpFile, attachmentName);
|
return ExportToInspector(null, activeExplorer, appointmentItem.Class, null, tmpFile, attachmentName);
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case AppointmentItem appointmentItem:
|
break;
|
||||||
if ((_outlookVersion.Major >= (int)OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(appointmentItem.Organizer) && appointmentItem.Organizer.Equals(_currentUser))
|
|
||||||
{
|
|
||||||
return ExportToInspector(null, activeExplorer, appointmentItem.Class, null, tmpFile, attachmentName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var inspectors = DisposableCom.Create(outlookApplication.ComObject.Inspectors))
|
using var inspectors = DisposableCom.Create(outlookApplication.ComObject.Inspectors);
|
||||||
|
if ((inspectors == null) || (inspectors.ComObject.Count == 0))
|
||||||
{
|
{
|
||||||
if ((inspectors == null) || (inspectors.ComObject.Count == 0))
|
return false;
|
||||||
|
}
|
||||||
|
Log.Debug().WriteLine("Got {0} inspectors to check", inspectors.ComObject.Count);
|
||||||
|
for (int i = 1; i <= inspectors.ComObject.Count; i++)
|
||||||
|
{
|
||||||
|
using var inspector = DisposableCom.Create((_Inspector)inspectors.ComObject[i]);
|
||||||
|
string currentCaption = inspector.ComObject.Caption;
|
||||||
|
if (!currentCaption.StartsWith(inspectorCaption))
|
||||||
{
|
{
|
||||||
return false;
|
continue;
|
||||||
}
|
}
|
||||||
Log.Debug().WriteLine("Got {0} inspectors to check", inspectors.ComObject.Count);
|
|
||||||
for (int i = 1; i <= inspectors.ComObject.Count; i++)
|
|
||||||
{
|
|
||||||
using (var inspector = DisposableCom.Create((_Inspector)inspectors.ComObject[i]))
|
|
||||||
{
|
|
||||||
string currentCaption = inspector.ComObject.Caption;
|
|
||||||
if (!currentCaption.StartsWith(inspectorCaption))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var currentItemUntyped = inspector.ComObject.CurrentItem;
|
var currentItemUntyped = inspector.ComObject.CurrentItem;
|
||||||
using (DisposableCom.Create(currentItemUntyped))
|
using (DisposableCom.Create(currentItemUntyped))
|
||||||
{
|
{
|
||||||
switch (currentItemUntyped)
|
switch (currentItemUntyped)
|
||||||
|
{
|
||||||
|
case MailItem mailItem:
|
||||||
|
if (mailItem.Sent)
|
||||||
{
|
{
|
||||||
case MailItem mailItem:
|
continue;
|
||||||
if (mailItem.Sent)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return ExportToInspector(inspector, null, mailItem.Class, mailItem, tmpFile, attachmentName);
|
|
||||||
}
|
|
||||||
catch (Exception exExport)
|
|
||||||
{
|
|
||||||
Log.Error().WriteLine(exExport, "Export to {0} failed.", currentCaption);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AppointmentItem appointmentItem:
|
|
||||||
if ((_outlookVersion.Major >= (int)OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(appointmentItem.Organizer) && !appointmentItem.Organizer.Equals(_currentUser))
|
|
||||||
{
|
|
||||||
Log.Debug().WriteLine("Not exporting, as organizer is set to {0} and currentuser {1} is not him.", appointmentItem.Organizer, _currentUser);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// skip, can't export to olAppointment
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return ExportToInspector(inspector, null, appointmentItem.Class, null, tmpFile, attachmentName);
|
|
||||||
}
|
|
||||||
catch (Exception exExport)
|
|
||||||
{
|
|
||||||
Log.Error().WriteLine(exExport, "Export to {0} failed.", currentCaption);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
try
|
||||||
|
{
|
||||||
|
return ExportToInspector(inspector, null, mailItem.Class, mailItem, tmpFile, attachmentName);
|
||||||
|
}
|
||||||
|
catch (Exception exExport)
|
||||||
|
{
|
||||||
|
Log.Error().WriteLine(exExport, "Export to {0} failed.", currentCaption);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AppointmentItem appointmentItem:
|
||||||
|
if ((_outlookVersion.Major >= (int)OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(appointmentItem.Organizer) && !appointmentItem.Organizer.Equals(_currentUser))
|
||||||
|
{
|
||||||
|
Log.Debug().WriteLine("Not exporting, as organizer is set to {0} and currentuser {1} is not him.", appointmentItem.Organizer, _currentUser);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// skip, can't export to olAppointment
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return ExportToInspector(inspector, null, appointmentItem.Class, null, tmpFile, attachmentName);
|
||||||
|
}
|
||||||
|
catch (Exception exExport)
|
||||||
|
{
|
||||||
|
Log.Error().WriteLine(exExport, "Export to {0} failed.", currentCaption);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,21 +233,19 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
{
|
{
|
||||||
using (wordDocument)
|
using (wordDocument)
|
||||||
{
|
{
|
||||||
using (var application = DisposableCom.Create(wordDocument.ComObject.Application))
|
using var application = DisposableCom.Create(wordDocument.ComObject.Application);
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
if (_wordExporter.InsertIntoExistingDocument(application, wordDocument, tmpFile, null, null))
|
||||||
{
|
{
|
||||||
if (_wordExporter.InsertIntoExistingDocument(application, wordDocument, tmpFile, null, null))
|
Log.Info().WriteLine("Inserted into Wordmail");
|
||||||
{
|
return true;
|
||||||
Log.Info().WriteLine("Inserted into Wordmail");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception exportException)
|
|
||||||
{
|
|
||||||
Log.Error().WriteLine(exportException, "Error exporting to the word editor, trying to do it via another method");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception exportException)
|
||||||
|
{
|
||||||
|
Log.Error().WriteLine(exportException, "Error exporting to the word editor, trying to do it via another method");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isAppointment)
|
else if (isAppointment)
|
||||||
|
@ -296,8 +288,7 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
// The following might cause a security popup... can't ignore it.
|
// The following might cause a security popup... can't ignore it.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var document2 = inspector.ComObject.HTMLEditor as IHTMLDocument2;
|
if (inspector.ComObject.HTMLEditor is IHTMLDocument2 document2)
|
||||||
if (document2 != null)
|
|
||||||
{
|
{
|
||||||
var selection = document2.selection;
|
var selection = document2.selection;
|
||||||
if (selection != null)
|
if (selection != null)
|
||||||
|
@ -332,24 +323,20 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the attachment (if inlined the attachment isn't visible as attachment!)
|
// Create the attachment (if inlined the attachment isn't visible as attachment!)
|
||||||
using (var attachments = DisposableCom.Create(mailItem.Attachments))
|
using var attachments = DisposableCom.Create(mailItem.Attachments);
|
||||||
|
using var attachment = DisposableCom.Create(attachments.ComObject.Add(tmpFile, OlAttachmentType.olByValue, inlinePossible ? 0 : 1, attachmentName));
|
||||||
|
if (_outlookVersion.Major >= (int)OfficeVersions.Office2007)
|
||||||
{
|
{
|
||||||
using (var attachment = DisposableCom.Create(attachments.ComObject.Add(tmpFile, OlAttachmentType.olByValue, inlinePossible ? 0 : 1, attachmentName)))
|
// Add the content id to the attachment, this only works for Outlook >= 2007
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (_outlookVersion.Major >= (int)OfficeVersions.Office2007)
|
var propertyAccessor = attachment.ComObject.PropertyAccessor;
|
||||||
{
|
propertyAccessor.SetProperty(AttachmentContentId, contentId);
|
||||||
// Add the content id to the attachment, this only works for Outlook >= 2007
|
}
|
||||||
try
|
// ReSharper disable once EmptyGeneralCatchClause
|
||||||
{
|
catch
|
||||||
var propertyAccessor = attachment.ComObject.PropertyAccessor;
|
{
|
||||||
propertyAccessor.SetProperty(AttachmentContentId, contentId);
|
// Ignore
|
||||||
}
|
|
||||||
// ReSharper disable once EmptyGeneralCatchClause
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -401,135 +388,127 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
/// <param name="url"></param>
|
/// <param name="url"></param>
|
||||||
private void ExportToNewEmail(IDisposableCom<Application> outlookApplication, EmailFormat format, string tmpFile, string subject, string attachmentName, string to, string cc, string bcc, string url)
|
private void ExportToNewEmail(IDisposableCom<Application> outlookApplication, EmailFormat format, string tmpFile, string subject, string attachmentName, string to, string cc, string bcc, string url)
|
||||||
{
|
{
|
||||||
using (var newItem = DisposableCom.Create((MailItem)outlookApplication.ComObject.CreateItem(OlItemType.olMailItem)))
|
using var newItem = DisposableCom.Create((MailItem)outlookApplication.ComObject.CreateItem(OlItemType.olMailItem));
|
||||||
|
if (newItem == null)
|
||||||
{
|
{
|
||||||
if (newItem == null)
|
return;
|
||||||
{
|
}
|
||||||
return;
|
var newMail = newItem.ComObject;
|
||||||
}
|
newMail.Subject = subject;
|
||||||
var newMail = newItem.ComObject;
|
if (!string.IsNullOrEmpty(to))
|
||||||
newMail.Subject = subject;
|
{
|
||||||
if (!string.IsNullOrEmpty(to))
|
newMail.To = to;
|
||||||
{
|
}
|
||||||
newMail.To = to;
|
if (!string.IsNullOrEmpty(cc))
|
||||||
}
|
{
|
||||||
if (!string.IsNullOrEmpty(cc))
|
newMail.CC = cc;
|
||||||
{
|
}
|
||||||
newMail.CC = cc;
|
if (!string.IsNullOrEmpty(bcc))
|
||||||
}
|
{
|
||||||
if (!string.IsNullOrEmpty(bcc))
|
newMail.BCC = bcc;
|
||||||
{
|
}
|
||||||
newMail.BCC = bcc;
|
newMail.BodyFormat = OlBodyFormat.olFormatHTML;
|
||||||
}
|
string bodyString = null;
|
||||||
newMail.BodyFormat = OlBodyFormat.olFormatHTML;
|
// Read the default signature, if nothing found use empty email
|
||||||
string bodyString = null;
|
try
|
||||||
// Read the default signature, if nothing found use empty email
|
{
|
||||||
try
|
bodyString = GetOutlookSignature(format);
|
||||||
{
|
}
|
||||||
bodyString = GetOutlookSignature(format);
|
catch (Exception e)
|
||||||
}
|
{
|
||||||
catch (Exception e)
|
Log.Error().WriteLine("Problem reading signature!", e);
|
||||||
{
|
}
|
||||||
Log.Error().WriteLine("Problem reading signature!", e);
|
switch (format)
|
||||||
}
|
{
|
||||||
switch (format)
|
case EmailFormat.Text:
|
||||||
{
|
// Create the attachment (and dispose the COM object after using)
|
||||||
case EmailFormat.Text:
|
using (var attachments = DisposableCom.Create(newMail.Attachments))
|
||||||
// Create the attachment (and dispose the COM object after using)
|
{
|
||||||
using (var attachments = DisposableCom.Create(newMail.Attachments))
|
using (DisposableCom.Create(attachments.ComObject.Add(tmpFile, OlAttachmentType.olByValue, 1, attachmentName)))
|
||||||
{
|
{
|
||||||
using (DisposableCom.Create(attachments.ComObject.Add(tmpFile, OlAttachmentType.olByValue, 1, attachmentName)))
|
newMail.BodyFormat = OlBodyFormat.olFormatPlain;
|
||||||
|
if (bodyString == null)
|
||||||
{
|
{
|
||||||
newMail.BodyFormat = OlBodyFormat.olFormatPlain;
|
bodyString = "";
|
||||||
if (bodyString == null)
|
}
|
||||||
{
|
newMail.Body = bodyString;
|
||||||
bodyString = "";
|
}
|
||||||
}
|
}
|
||||||
newMail.Body = bodyString;
|
break;
|
||||||
}
|
default:
|
||||||
}
|
string contentId = Path.GetFileName(tmpFile);
|
||||||
break;
|
// Create the attachment (and dispose the COM object after using)
|
||||||
default:
|
using (var attachments = DisposableCom.Create(newMail.Attachments))
|
||||||
string contentId = Path.GetFileName(tmpFile);
|
{
|
||||||
// Create the attachment (and dispose the COM object after using)
|
using var attachment = DisposableCom.Create(attachments.ComObject.Add(tmpFile, OlAttachmentType.olByValue, 0, attachmentName));
|
||||||
using (var attachments = DisposableCom.Create(newMail.Attachments))
|
// add content ID to the attachment
|
||||||
{
|
if (_outlookVersion.Major >= (int)OfficeVersions.Office2007)
|
||||||
using (var attachment = DisposableCom.Create(attachments.ComObject.Add(tmpFile, OlAttachmentType.olByValue, 0, attachmentName)))
|
{
|
||||||
{
|
try
|
||||||
// add content ID to the attachment
|
{
|
||||||
if (_outlookVersion.Major >= (int)OfficeVersions.Office2007)
|
contentId = Guid.NewGuid().ToString();
|
||||||
{
|
using var propertyAccessor = DisposableCom.Create(attachment.ComObject.PropertyAccessor);
|
||||||
try
|
propertyAccessor.ComObject.SetProperty(AttachmentContentId, contentId);
|
||||||
{
|
}
|
||||||
contentId = Guid.NewGuid().ToString();
|
catch
|
||||||
using (var propertyAccessor = DisposableCom.Create(attachment.ComObject.PropertyAccessor))
|
{
|
||||||
{
|
Log.Info().WriteLine("Error working with the PropertyAccessor, using filename as contentid");
|
||||||
propertyAccessor.ComObject.SetProperty(AttachmentContentId, contentId);
|
contentId = Path.GetFileName(tmpFile);
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Log.Info().WriteLine("Error working with the PropertyAccessor, using filename as contentid");
|
|
||||||
contentId = Path.GetFileName(tmpFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
newMail.BodyFormat = OlBodyFormat.olFormatHTML;
|
newMail.BodyFormat = OlBodyFormat.olFormatHTML;
|
||||||
string href = "";
|
string href = "";
|
||||||
string hrefEnd = "";
|
string hrefEnd = "";
|
||||||
if (!string.IsNullOrEmpty(url))
|
if (!string.IsNullOrEmpty(url))
|
||||||
|
{
|
||||||
|
href = string.Format("<A HREF=\"{0}\">", url);
|
||||||
|
hrefEnd = "</A>";
|
||||||
|
}
|
||||||
|
string htmlImgEmbedded = string.Format("<BR/>{0}<IMG border=0 hspace=0 alt=\"{1}\" align=baseline src=\"cid:{2}\">{3}<BR/>", href, attachmentName, contentId, hrefEnd);
|
||||||
|
string fallbackBody = string.Format("<HTML><BODY>{0}</BODY></HTML>", htmlImgEmbedded);
|
||||||
|
if (bodyString == null)
|
||||||
|
{
|
||||||
|
bodyString = fallbackBody;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int bodyIndex = bodyString.IndexOf("<body", StringComparison.CurrentCultureIgnoreCase);
|
||||||
|
if (bodyIndex >= 0)
|
||||||
{
|
{
|
||||||
href = string.Format("<A HREF=\"{0}\">", url);
|
bodyIndex = bodyString.IndexOf(">", bodyIndex, StringComparison.Ordinal) + 1;
|
||||||
hrefEnd = "</A>";
|
|
||||||
}
|
|
||||||
string htmlImgEmbedded = string.Format("<BR/>{0}<IMG border=0 hspace=0 alt=\"{1}\" align=baseline src=\"cid:{2}\">{3}<BR/>", href, attachmentName, contentId, hrefEnd);
|
|
||||||
string fallbackBody = string.Format("<HTML><BODY>{0}</BODY></HTML>", htmlImgEmbedded);
|
|
||||||
if (bodyString == null)
|
|
||||||
{
|
|
||||||
bodyString = fallbackBody;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int bodyIndex = bodyString.IndexOf("<body", StringComparison.CurrentCultureIgnoreCase);
|
|
||||||
if (bodyIndex >= 0)
|
if (bodyIndex >= 0)
|
||||||
{
|
{
|
||||||
bodyIndex = bodyString.IndexOf(">", bodyIndex, StringComparison.Ordinal) + 1;
|
bodyString = bodyString.Insert(bodyIndex, htmlImgEmbedded);
|
||||||
if (bodyIndex >= 0)
|
|
||||||
{
|
|
||||||
bodyString = bodyString.Insert(bodyIndex, htmlImgEmbedded);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bodyString = fallbackBody;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bodyString = fallbackBody;
|
bodyString = fallbackBody;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newMail.HTMLBody = bodyString;
|
else
|
||||||
break;
|
|
||||||
}
|
|
||||||
// So not save, otherwise the email is always stored in Draft folder.. (newMail.Save();)
|
|
||||||
newMail.Display(false);
|
|
||||||
|
|
||||||
using (var inspector = DisposableCom.Create((_Inspector)newMail.GetInspector))
|
|
||||||
{
|
|
||||||
if (inspector != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
inspector.ComObject.Activate();
|
bodyString = fallbackBody;
|
||||||
}
|
|
||||||
// ReSharper disable once EmptyGeneralCatchClause
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Ignore
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
newMail.HTMLBody = bodyString;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// So not save, otherwise the email is always stored in Draft folder.. (newMail.Save();)
|
||||||
|
newMail.Display(false);
|
||||||
|
|
||||||
|
using var inspector = DisposableCom.Create((_Inspector)newMail.GetInspector);
|
||||||
|
if (inspector != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
inspector.ComObject.Activate();
|
||||||
|
}
|
||||||
|
// ReSharper disable once EmptyGeneralCatchClause
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -620,50 +599,41 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
}
|
}
|
||||||
string defaultProfile = (string)profilesKey.GetValue(DefaultProfileValue);
|
string defaultProfile = (string)profilesKey.GetValue(DefaultProfileValue);
|
||||||
Log.Debug().WriteLine("defaultProfile={0}", defaultProfile);
|
Log.Debug().WriteLine("defaultProfile={0}", defaultProfile);
|
||||||
using (var profileKey = profilesKey.OpenSubKey(defaultProfile + @"\" + AccountKey, false))
|
using var profileKey = profilesKey.OpenSubKey(defaultProfile + @"\" + AccountKey, false);
|
||||||
|
if (profileKey != null)
|
||||||
{
|
{
|
||||||
if (profileKey != null)
|
string[] numbers = profileKey.GetSubKeyNames();
|
||||||
|
foreach (string number in numbers)
|
||||||
{
|
{
|
||||||
string[] numbers = profileKey.GetSubKeyNames();
|
Log.Debug().WriteLine("Found subkey {0}", number);
|
||||||
foreach (string number in numbers)
|
using var numberKey = profileKey.OpenSubKey(number, false);
|
||||||
|
if (numberKey != null)
|
||||||
{
|
{
|
||||||
Log.Debug().WriteLine("Found subkey {0}", number);
|
byte[] val = (byte[])numberKey.GetValue(NewSignatureValue);
|
||||||
using (var numberKey = profileKey.OpenSubKey(number, false))
|
if (val == null)
|
||||||
{
|
{
|
||||||
if (numberKey != null)
|
continue;
|
||||||
|
}
|
||||||
|
string signatureName = "";
|
||||||
|
foreach (byte b in val)
|
||||||
|
{
|
||||||
|
if (b != 0)
|
||||||
{
|
{
|
||||||
byte[] val = (byte[])numberKey.GetValue(NewSignatureValue);
|
signatureName += (char)b;
|
||||||
if (val == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
string signatureName = "";
|
|
||||||
foreach (byte b in val)
|
|
||||||
{
|
|
||||||
if (b != 0)
|
|
||||||
{
|
|
||||||
signatureName += (char)b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Log.Debug().WriteLine("Found email signature: {0}", signatureName);
|
|
||||||
string extension;
|
|
||||||
switch (format)
|
|
||||||
{
|
|
||||||
case EmailFormat.Text:
|
|
||||||
extension = ".txt";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
extension = ".htm";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
string signatureFile = Path.Combine(SignaturePath, signatureName + extension);
|
|
||||||
if (File.Exists(signatureFile))
|
|
||||||
{
|
|
||||||
Log.Debug().WriteLine("Found email signature file: {0}", signatureFile);
|
|
||||||
return File.ReadAllText(signatureFile, Encoding.Default);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Log.Debug().WriteLine("Found email signature: {0}", signatureName);
|
||||||
|
var extension = format switch
|
||||||
|
{
|
||||||
|
EmailFormat.Text => ".txt",
|
||||||
|
_ => ".htm"
|
||||||
|
};
|
||||||
|
string signatureFile = Path.Combine(SignaturePath, signatureName + extension);
|
||||||
|
if (File.Exists(signatureFile))
|
||||||
|
{
|
||||||
|
Log.Debug().WriteLine("Found email signature file: {0}", signatureFile);
|
||||||
|
return File.ReadAllText(signatureFile, Encoding.Default);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -694,10 +664,8 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
{
|
{
|
||||||
using (var mapiNamespace = DisposableCom.Create(outlookApplication.ComObject.GetNamespace("MAPI")))
|
using (var mapiNamespace = DisposableCom.Create(outlookApplication.ComObject.GetNamespace("MAPI")))
|
||||||
{
|
{
|
||||||
using (var currentUser = DisposableCom.Create(mapiNamespace.ComObject.CurrentUser))
|
using var currentUser = DisposableCom.Create(mapiNamespace.ComObject.CurrentUser);
|
||||||
{
|
_currentUser = currentUser.ComObject.Name;
|
||||||
_currentUser = currentUser.ComObject.Name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Log.Info().WriteLine("Current user: {0}", _currentUser);
|
Log.Info().WriteLine("Current user: {0}", _currentUser);
|
||||||
}
|
}
|
||||||
|
@ -717,99 +685,91 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
IDictionary<string, OlObjectClass> inspectorCaptions = new SortedDictionary<string, OlObjectClass>();
|
IDictionary<string, OlObjectClass> inspectorCaptions = new SortedDictionary<string, OlObjectClass>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var outlookApplication = GetOutlookApplication())
|
using var outlookApplication = GetOutlookApplication();
|
||||||
|
if (outlookApplication == null)
|
||||||
{
|
{
|
||||||
if (outlookApplication == null)
|
return inspectorCaptions;
|
||||||
{
|
}
|
||||||
return inspectorCaptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The activeexplorer inline response only works with >= 2013, Microsoft Outlook 15.0 Object Library
|
// The activeexplorer inline response only works with >= 2013, Microsoft Outlook 15.0 Object Library
|
||||||
if (_outlookVersion.Major >= (int)OfficeVersions.Office2013)
|
if (_outlookVersion.Major >= (int)OfficeVersions.Office2013)
|
||||||
|
{
|
||||||
|
// Check inline "panel" for Outlook 2013
|
||||||
|
using var activeExplorer = DisposableCom.Create(outlookApplication.ComObject.ActiveExplorer());
|
||||||
|
if (activeExplorer != null)
|
||||||
{
|
{
|
||||||
// Check inline "panel" for Outlook 2013
|
var untypedInlineResponse = activeExplorer.ComObject.ActiveInlineResponse;
|
||||||
using (var activeExplorer = DisposableCom.Create(outlookApplication.ComObject.ActiveExplorer()))
|
if (untypedInlineResponse != null)
|
||||||
{
|
{
|
||||||
if (activeExplorer != null)
|
string caption = activeExplorer.ComObject.Caption;
|
||||||
|
using (DisposableCom.Create(untypedInlineResponse))
|
||||||
{
|
{
|
||||||
var untypedInlineResponse = activeExplorer.ComObject.ActiveInlineResponse;
|
switch (untypedInlineResponse)
|
||||||
if (untypedInlineResponse != null)
|
|
||||||
{
|
{
|
||||||
string caption = activeExplorer.ComObject.Caption;
|
case MailItem mailItem:
|
||||||
using (DisposableCom.Create(untypedInlineResponse))
|
if (!mailItem.Sent)
|
||||||
{
|
|
||||||
switch (untypedInlineResponse)
|
|
||||||
{
|
{
|
||||||
case MailItem mailItem:
|
inspectorCaptions.Add(caption, mailItem.Class);
|
||||||
if (!mailItem.Sent)
|
|
||||||
{
|
|
||||||
inspectorCaptions.Add(caption, mailItem.Class);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AppointmentItem appointmentItem:
|
|
||||||
if ((_outlookVersion.Major >= (int)OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(appointmentItem.Organizer) && appointmentItem.Organizer.Equals(_currentUser))
|
|
||||||
{
|
|
||||||
inspectorCaptions.Add(caption, appointmentItem.Class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
|
case AppointmentItem appointmentItem:
|
||||||
|
if ((_outlookVersion.Major >= (int)OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(appointmentItem.Organizer) && appointmentItem.Organizer.Equals(_currentUser))
|
||||||
|
{
|
||||||
|
inspectorCaptions.Add(caption, appointmentItem.Class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
using (var inspectors = DisposableCom.Create(outlookApplication.ComObject.Inspectors))
|
using var inspectors = DisposableCom.Create(outlookApplication.ComObject.Inspectors);
|
||||||
|
if ((inspectors != null) && (inspectors.ComObject.Count > 0))
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= inspectors.ComObject.Count; i++)
|
||||||
{
|
{
|
||||||
if ((inspectors != null) && (inspectors.ComObject.Count > 0))
|
using var inspector = DisposableCom.Create(inspectors.ComObject[i]);
|
||||||
|
string caption = inspector.ComObject.Caption;
|
||||||
|
// Fix double entries in the directory, TODO: store on something uniq
|
||||||
|
if (inspectorCaptions.ContainsKey(caption))
|
||||||
{
|
{
|
||||||
for (int i = 1; i <= inspectors.ComObject.Count; i++)
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentItemUntyped = inspector.ComObject.CurrentItem;
|
||||||
|
using (DisposableCom.Create(currentItemUntyped))
|
||||||
|
{
|
||||||
|
switch (currentItemUntyped)
|
||||||
{
|
{
|
||||||
using (var inspector = DisposableCom.Create(inspectors.ComObject[i]))
|
case MailItem mailItem:
|
||||||
{
|
if (mailItem.Sent)
|
||||||
string caption = inspector.ComObject.Caption;
|
|
||||||
// Fix double entries in the directory, TODO: store on something uniq
|
|
||||||
if (inspectorCaptions.ContainsKey(caption))
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
inspectorCaptions.Add(caption, mailItem.Class);
|
||||||
var currentItemUntyped = inspector.ComObject.CurrentItem;
|
break;
|
||||||
using (DisposableCom.Create(currentItemUntyped))
|
case AppointmentItem appointmentItem:
|
||||||
|
if ((_outlookVersion.Major >= (int)OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
|
||||||
{
|
{
|
||||||
switch (currentItemUntyped)
|
if (!string.IsNullOrEmpty(appointmentItem.Organizer) && !appointmentItem.Organizer.Equals(_currentUser))
|
||||||
{
|
{
|
||||||
case MailItem mailItem:
|
Log.Debug().WriteLine("Not exporting, as organizer is set to {0} and currentuser {1} is not him.", appointmentItem.Organizer, _currentUser);
|
||||||
if (mailItem.Sent)
|
continue;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
inspectorCaptions.Add(caption, mailItem.Class);
|
|
||||||
break;
|
|
||||||
case AppointmentItem appointmentItem:
|
|
||||||
if ((_outlookVersion.Major >= (int)OfficeVersions.Office2010) && _officeConfiguration.OutlookAllowExportInMeetings)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(appointmentItem.Organizer) && !appointmentItem.Organizer.Equals(_currentUser))
|
|
||||||
{
|
|
||||||
Log.Debug().WriteLine("Not exporting, as organizer is set to {0} and currentuser {1} is not him.", appointmentItem.Organizer, _currentUser);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// skip, can't export to olAppointment
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
inspectorCaptions.Add(caption, appointmentItem.Class);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
// skip, can't export to olAppointment
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
inspectorCaptions.Add(caption, appointmentItem.Class);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,72 +81,64 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
slide = DisposableCom.Create(slides.ComObject.Add(slides.ComObject.Count + 1, _officeConfiguration.PowerpointSlideLayout));
|
slide = DisposableCom.Create(slides.ComObject.Add(slides.ComObject.Count + 1, _officeConfiguration.PowerpointSlideLayout));
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var shapes = DisposableCom.Create(slide.ComObject.Shapes))
|
using var shapes = DisposableCom.Create(slide.ComObject.Shapes);
|
||||||
|
using var shapeForLocation = DisposableCom.Create(shapes.ComObject[2]);
|
||||||
|
// Shapes[2] is the image shape on this layout.
|
||||||
|
shapeForCaption = DisposableCom.Create(shapes.ComObject[1]);
|
||||||
|
if (width > shapeForLocation.ComObject.Width)
|
||||||
{
|
{
|
||||||
using (var shapeForLocation = DisposableCom.Create(shapes.ComObject[2]))
|
width = shapeForLocation.ComObject.Width;
|
||||||
{
|
left = shapeForLocation.ComObject.Left;
|
||||||
// Shapes[2] is the image shape on this layout.
|
hasScaledWidth = true;
|
||||||
shapeForCaption = DisposableCom.Create(shapes.ComObject[1]);
|
|
||||||
if (width > shapeForLocation.ComObject.Width)
|
|
||||||
{
|
|
||||||
width = shapeForLocation.ComObject.Width;
|
|
||||||
left = shapeForLocation.ComObject.Left;
|
|
||||||
hasScaledWidth = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
shapeForLocation.ComObject.Left = left;
|
|
||||||
}
|
|
||||||
shapeForLocation.ComObject.Width = imageSize.Width;
|
|
||||||
|
|
||||||
if (height > shapeForLocation.ComObject.Height)
|
|
||||||
{
|
|
||||||
height = shapeForLocation.ComObject.Height;
|
|
||||||
top = shapeForLocation.ComObject.Top;
|
|
||||||
hasScaledHeight = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
top = shapeForLocation.ComObject.Top + shapeForLocation.ComObject.Height / 2 - imageSize.Height / 2f;
|
|
||||||
}
|
|
||||||
shapeForLocation.ComObject.Height = imageSize.Height;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shapeForLocation.ComObject.Left = left;
|
||||||
|
}
|
||||||
|
shapeForLocation.ComObject.Width = imageSize.Width;
|
||||||
|
|
||||||
|
if (height > shapeForLocation.ComObject.Height)
|
||||||
|
{
|
||||||
|
height = shapeForLocation.ComObject.Height;
|
||||||
|
top = shapeForLocation.ComObject.Top;
|
||||||
|
hasScaledHeight = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
top = shapeForLocation.ComObject.Top + shapeForLocation.ComObject.Height / 2 - imageSize.Height / 2f;
|
||||||
|
}
|
||||||
|
shapeForLocation.ComObject.Height = imageSize.Height;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Log.Error().WriteLine(e, "Powerpoint shape creating failed");
|
Log.Error().WriteLine(e, "Powerpoint shape creating failed");
|
||||||
using (var slides = DisposableCom.Create(presentation.ComObject.Slides))
|
using var slides = DisposableCom.Create(presentation.ComObject.Slides);
|
||||||
{
|
slide = DisposableCom.Create(slides.ComObject.Add(slides.ComObject.Count + 1, PpSlideLayout.ppLayoutBlank));
|
||||||
slide = DisposableCom.Create(slides.ComObject.Add(slides.ComObject.Count + 1, PpSlideLayout.ppLayoutBlank));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
using (var shapes = DisposableCom.Create(slide.ComObject.Shapes))
|
using (var shapes = DisposableCom.Create(slide.ComObject.Shapes))
|
||||||
{
|
{
|
||||||
using (var shape = DisposableCom.Create(shapes.ComObject.AddPicture(tmpFile, MsoTriState.msoFalse, MsoTriState.msoTrue, 0, 0, width, height)))
|
using var shape = DisposableCom.Create(shapes.ComObject.AddPicture(tmpFile, MsoTriState.msoFalse, MsoTriState.msoTrue, 0, 0, width, height));
|
||||||
|
if (_officeConfiguration.PowerpointLockAspectRatio)
|
||||||
{
|
{
|
||||||
if (_officeConfiguration.PowerpointLockAspectRatio)
|
shape.ComObject.LockAspectRatio = MsoTriState.msoTrue;
|
||||||
{
|
|
||||||
shape.ComObject.LockAspectRatio = MsoTriState.msoTrue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
shape.ComObject.LockAspectRatio = MsoTriState.msoFalse;
|
|
||||||
}
|
|
||||||
shape.ComObject.ScaleHeight(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle);
|
|
||||||
shape.ComObject.ScaleWidth(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle);
|
|
||||||
if (hasScaledWidth)
|
|
||||||
{
|
|
||||||
shape.ComObject.Width = width;
|
|
||||||
}
|
|
||||||
if (hasScaledHeight)
|
|
||||||
{
|
|
||||||
shape.ComObject.Height = height;
|
|
||||||
}
|
|
||||||
shape.ComObject.Left = left;
|
|
||||||
shape.ComObject.Top = top;
|
|
||||||
shape.ComObject.AlternativeText = title;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shape.ComObject.LockAspectRatio = MsoTriState.msoFalse;
|
||||||
|
}
|
||||||
|
shape.ComObject.ScaleHeight(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle);
|
||||||
|
shape.ComObject.ScaleWidth(1, MsoTriState.msoTrue, MsoScaleFrom.msoScaleFromMiddle);
|
||||||
|
if (hasScaledWidth)
|
||||||
|
{
|
||||||
|
shape.ComObject.Width = width;
|
||||||
|
}
|
||||||
|
if (hasScaledHeight)
|
||||||
|
{
|
||||||
|
shape.ComObject.Height = height;
|
||||||
|
}
|
||||||
|
shape.ComObject.Left = left;
|
||||||
|
shape.ComObject.Top = top;
|
||||||
|
shape.ComObject.AlternativeText = title;
|
||||||
}
|
}
|
||||||
if (shapeForCaption != null)
|
if (shapeForCaption != null)
|
||||||
{
|
{
|
||||||
|
@ -155,13 +147,9 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
using (shapeForCaption)
|
using (shapeForCaption)
|
||||||
{
|
{
|
||||||
// Using try/catch to make sure problems with the text range don't give an exception.
|
// Using try/catch to make sure problems with the text range don't give an exception.
|
||||||
using (var textFrame = DisposableCom.Create(shapeForCaption.ComObject.TextFrame))
|
using var textFrame = DisposableCom.Create(shapeForCaption.ComObject.TextFrame);
|
||||||
{
|
using var textRange = DisposableCom.Create(textFrame.ComObject.TextRange);
|
||||||
using (var textRange = DisposableCom.Create(textFrame.ComObject.TextRange))
|
textRange.ComObject.Text = title;
|
||||||
{
|
|
||||||
textRange.ComObject.Text = title;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -172,16 +160,10 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
// Activate/Goto the slide
|
// Activate/Goto the slide
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var application = DisposableCom.Create(presentation.ComObject.Application))
|
using var application = DisposableCom.Create(presentation.ComObject.Application);
|
||||||
{
|
using var activeWindow = DisposableCom.Create(application.ComObject.ActiveWindow);
|
||||||
using (var activeWindow = DisposableCom.Create(application.ComObject.ActiveWindow))
|
using var view = DisposableCom.Create(activeWindow.ComObject.View);
|
||||||
{
|
view.ComObject.GotoSlide(slide.ComObject.SlideNumber);
|
||||||
using (var view = DisposableCom.Create(activeWindow.ComObject.View))
|
|
||||||
{
|
|
||||||
view.ComObject.GotoSlide(slide.ComObject.SlideNumber);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -211,31 +193,28 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
using (var presentations = DisposableCom.Create(powerpointApplication.ComObject.Presentations))
|
|
||||||
|
using var presentations = DisposableCom.Create(powerpointApplication.ComObject.Presentations);
|
||||||
|
Log.Debug().WriteLine("Open Presentations: {0}", presentations.ComObject.Count);
|
||||||
|
for (int i = 1; i <= presentations.ComObject.Count; i++)
|
||||||
{
|
{
|
||||||
Log.Debug().WriteLine("Open Presentations: {0}", presentations.ComObject.Count);
|
using var presentation = DisposableCom.Create(presentations.ComObject[i]);
|
||||||
for (int i = 1; i <= presentations.ComObject.Count; i++)
|
if (presentation == null)
|
||||||
{
|
{
|
||||||
using (var presentation = DisposableCom.Create(presentations.ComObject[i]))
|
continue;
|
||||||
{
|
}
|
||||||
if (presentation == null)
|
if (!presentation.ComObject.Name.StartsWith(presentationName))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!presentation.ComObject.Name.StartsWith(presentationName))
|
try
|
||||||
{
|
{
|
||||||
continue;
|
AddPictureToPresentation(presentation, tmpFile, imageSize, title);
|
||||||
}
|
return true;
|
||||||
try
|
}
|
||||||
{
|
catch (Exception e)
|
||||||
AddPictureToPresentation(presentation, tmpFile, imageSize, title);
|
{
|
||||||
return true;
|
Log.Error().WriteLine(e, "Adding picture to powerpoint failed");
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Log.Error().WriteLine(e, "Adding picture to powerpoint failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,39 +265,33 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public IEnumerable<string> GetPowerpointPresentations()
|
public IEnumerable<string> GetPowerpointPresentations()
|
||||||
{
|
{
|
||||||
using (var powerpointApplication = GetPowerPointApplication())
|
using var powerpointApplication = GetPowerPointApplication();
|
||||||
|
if (powerpointApplication == null)
|
||||||
{
|
{
|
||||||
if (powerpointApplication == null)
|
yield break;
|
||||||
{
|
}
|
||||||
yield break;
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var presentations = DisposableCom.Create(powerpointApplication.ComObject.Presentations))
|
using var presentations = DisposableCom.Create(powerpointApplication.ComObject.Presentations);
|
||||||
|
Log.Debug().WriteLine("Open Presentations: {0}", presentations.ComObject.Count);
|
||||||
|
for (int i = 1; i <= presentations.ComObject.Count; i++)
|
||||||
|
{
|
||||||
|
using var presentation = DisposableCom.Create(presentations.ComObject[i]);
|
||||||
|
if (presentation == null)
|
||||||
{
|
{
|
||||||
Log.Debug().WriteLine("Open Presentations: {0}", presentations.ComObject.Count);
|
continue;
|
||||||
for (int i = 1; i <= presentations.ComObject.Count; i++)
|
}
|
||||||
|
if (presentation.ComObject.ReadOnly == MsoTriState.msoTrue)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (IsAfter2003())
|
||||||
|
{
|
||||||
|
if (presentation.ComObject.Final)
|
||||||
{
|
{
|
||||||
using (var presentation = DisposableCom.Create(presentations.ComObject[i]))
|
continue;
|
||||||
{
|
|
||||||
if (presentation == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (presentation.ComObject.ReadOnly == MsoTriState.msoTrue)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (IsAfter2003())
|
|
||||||
{
|
|
||||||
if (presentation.ComObject.Final)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
yield return presentation.ComObject.Name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
yield return presentation.ComObject.Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,20 +328,16 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
{
|
{
|
||||||
powerpointApplication.ComObject.Activate();
|
powerpointApplication.ComObject.Activate();
|
||||||
powerpointApplication.ComObject.Visible = MsoTriState.msoTrue;
|
powerpointApplication.ComObject.Visible = MsoTriState.msoTrue;
|
||||||
using (var presentations = DisposableCom.Create(powerpointApplication.ComObject.Presentations))
|
using var presentations = DisposableCom.Create(powerpointApplication.ComObject.Presentations);
|
||||||
|
using var presentation = DisposableCom.Create(presentations.ComObject.Add());
|
||||||
|
try
|
||||||
{
|
{
|
||||||
using (var presentation = DisposableCom.Create(presentations.ComObject.Add()))
|
AddPictureToPresentation(presentation, tmpFile, imageSize, title);
|
||||||
{
|
isPictureAdded = true;
|
||||||
try
|
}
|
||||||
{
|
catch (Exception e)
|
||||||
AddPictureToPresentation(presentation, tmpFile, imageSize, title);
|
{
|
||||||
isPictureAdded = true;
|
Log.Error().WriteLine(e, "Powerpoint add picture to presentation failed");
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Log.Error().WriteLine(e, "Powerpoint add picture to presentation failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,18 +55,16 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private IDisposableCom<InlineShape> AddPictureToSelection(IDisposableCom<Selection> selection, string tmpFile)
|
private IDisposableCom<InlineShape> AddPictureToSelection(IDisposableCom<Selection> selection, string tmpFile)
|
||||||
{
|
{
|
||||||
using (var shapes = DisposableCom.Create(selection.ComObject.InlineShapes))
|
using var shapes = DisposableCom.Create(selection.ComObject.InlineShapes);
|
||||||
|
var shape = DisposableCom.Create(shapes.ComObject.AddPicture(tmpFile, false, true, Type.Missing));
|
||||||
|
// Lock aspect ratio
|
||||||
|
if (_officeConfiguration.WordLockAspectRatio)
|
||||||
{
|
{
|
||||||
var shape = DisposableCom.Create(shapes.ComObject.AddPicture(tmpFile, false, true, Type.Missing));
|
shape.ComObject.LockAspectRatio = MsoTriState.msoTrue;
|
||||||
// Lock aspect ratio
|
|
||||||
if (_officeConfiguration.WordLockAspectRatio)
|
|
||||||
{
|
|
||||||
shape.ComObject.LockAspectRatio = MsoTriState.msoTrue;
|
|
||||||
}
|
|
||||||
selection.ComObject.InsertAfter("\r\n");
|
|
||||||
selection.ComObject.MoveDown(WdUnits.wdLine, 1, Type.Missing);
|
|
||||||
return shape;
|
|
||||||
}
|
}
|
||||||
|
selection.ComObject.InsertAfter("\r\n");
|
||||||
|
selection.ComObject.MoveDown(WdUnits.wdLine, 1, Type.Missing);
|
||||||
|
return shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -113,36 +111,30 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public IEnumerable<string> GetWordDocuments()
|
public IEnumerable<string> GetWordDocuments()
|
||||||
{
|
{
|
||||||
using (var wordApplication = GetWordApplication())
|
using var wordApplication = GetWordApplication();
|
||||||
|
if (wordApplication == null)
|
||||||
{
|
{
|
||||||
if (wordApplication == null)
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var documents = DisposableCom.Create(wordApplication.ComObject.Documents);
|
||||||
|
for (int i = 1; i <= documents.ComObject.Count; i++)
|
||||||
|
{
|
||||||
|
using var document = DisposableCom.Create(documents.ComObject[i]);
|
||||||
|
if (document.ComObject.ReadOnly)
|
||||||
{
|
{
|
||||||
yield break;
|
continue;
|
||||||
}
|
}
|
||||||
using (var documents = DisposableCom.Create(wordApplication.ComObject.Documents))
|
if (IsAfter2003())
|
||||||
{
|
{
|
||||||
for (int i = 1; i <= documents.ComObject.Count; i++)
|
if (document.ComObject.Final)
|
||||||
{
|
{
|
||||||
using (var document = DisposableCom.Create(documents.ComObject[i]))
|
continue;
|
||||||
{
|
|
||||||
if (document.ComObject.ReadOnly)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (IsAfter2003())
|
|
||||||
{
|
|
||||||
if (document.ComObject.Final)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
using (var activeWindow = DisposableCom.Create(document.ComObject.ActiveWindow))
|
|
||||||
{
|
|
||||||
yield return activeWindow.ComObject.Caption;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using var activeWindow = DisposableCom.Create(document.ComObject.ActiveWindow);
|
||||||
|
yield return activeWindow.ComObject.Caption;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,20 +169,15 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
using (var documents = DisposableCom.Create(wordApplication.ComObject.Documents))
|
|
||||||
|
using var documents = DisposableCom.Create(wordApplication.ComObject.Documents);
|
||||||
|
for (int i = 1; i <= documents.ComObject.Count; i++)
|
||||||
{
|
{
|
||||||
for (int i = 1; i <= documents.ComObject.Count; i++)
|
using var wordDocument = DisposableCom.Create((_Document)documents.ComObject[i]);
|
||||||
|
using var activeWindow = DisposableCom.Create(wordDocument.ComObject.ActiveWindow);
|
||||||
|
if (activeWindow.ComObject.Caption.StartsWith(wordCaption))
|
||||||
{
|
{
|
||||||
using (var wordDocument = DisposableCom.Create((_Document)documents.ComObject[i]))
|
return InsertIntoExistingDocument(wordApplication, wordDocument, tmpFile, null, null);
|
||||||
{
|
|
||||||
using (var activeWindow = DisposableCom.Create(wordDocument.ComObject.ActiveWindow))
|
|
||||||
{
|
|
||||||
if (activeWindow.ComObject.Caption.StartsWith(wordCaption))
|
|
||||||
{
|
|
||||||
return InsertIntoExistingDocument(wordApplication, wordDocument, tmpFile, null, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,81 +206,72 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
{
|
{
|
||||||
Log.Warn().WriteLine(ex);
|
Log.Warn().WriteLine(ex);
|
||||||
}
|
}
|
||||||
using (var selection = DisposableCom.Create(wordApplication.ComObject.Selection))
|
|
||||||
|
using var selection = DisposableCom.Create(wordApplication.ComObject.Selection);
|
||||||
|
if (selection == null)
|
||||||
{
|
{
|
||||||
if (selection == null)
|
Log.Info().WriteLine("No selection to insert {0} into found.", tmpFile);
|
||||||
{
|
return false;
|
||||||
Log.Info().WriteLine("No selection to insert {0} into found.", tmpFile);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Add Picture
|
|
||||||
using (var shape = AddPictureToSelection(selection, tmpFile))
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(address))
|
|
||||||
{
|
|
||||||
object screentip = Type.Missing;
|
|
||||||
if (!string.IsNullOrEmpty(tooltip))
|
|
||||||
{
|
|
||||||
screentip = tooltip;
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var hyperlinks = DisposableCom.Create(wordDocument.ComObject.Hyperlinks))
|
|
||||||
{
|
|
||||||
hyperlinks.ComObject.Add(shape, screentip, Type.Missing, screentip, Type.Missing, Type.Missing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Log.Warn().WriteLine("Couldn't add hyperlink for image: {0}", e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var activeWindow = DisposableCom.Create(wordDocument.ComObject.ActiveWindow))
|
|
||||||
{
|
|
||||||
activeWindow.ComObject.Activate();
|
|
||||||
using (var activePane = DisposableCom.Create(activeWindow.ComObject.ActivePane))
|
|
||||||
{
|
|
||||||
using (var view = DisposableCom.Create(activePane.ComObject.View))
|
|
||||||
{
|
|
||||||
view.ComObject.Zoom.Percentage = 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
if (e.InnerException != null)
|
|
||||||
{
|
|
||||||
Log.Warn().WriteLine("Couldn't set zoom to 100, error: {0}", e.InnerException.Message);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.Warn().WriteLine("Couldn't set zoom to 100, error: {0}", e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
wordApplication.ComObject.Activate();
|
|
||||||
// ReSharper disable once EmptyGeneralCatchClause
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Warn().WriteLine(ex);
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
wordDocument.ComObject.Activate();
|
|
||||||
// ReSharper disable once EmptyGeneralCatchClause
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Warn().WriteLine(ex);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
// Add Picture
|
||||||
|
using (var shape = AddPictureToSelection(selection, tmpFile))
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(address))
|
||||||
|
{
|
||||||
|
object screentip = Type.Missing;
|
||||||
|
if (!string.IsNullOrEmpty(tooltip))
|
||||||
|
{
|
||||||
|
screentip = tooltip;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var hyperlinks = DisposableCom.Create(wordDocument.ComObject.Hyperlinks);
|
||||||
|
hyperlinks.ComObject.Add(shape, screentip, Type.Missing, screentip, Type.Missing, Type.Missing);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Warn().WriteLine("Couldn't add hyperlink for image: {0}", e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var activeWindow = DisposableCom.Create(wordDocument.ComObject.ActiveWindow);
|
||||||
|
activeWindow.ComObject.Activate();
|
||||||
|
using var activePane = DisposableCom.Create(activeWindow.ComObject.ActivePane);
|
||||||
|
using var view = DisposableCom.Create(activePane.ComObject.View);
|
||||||
|
view.ComObject.Zoom.Percentage = 100;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (e.InnerException != null)
|
||||||
|
{
|
||||||
|
Log.Warn().WriteLine("Couldn't set zoom to 100, error: {0}", e.InnerException.Message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.Warn().WriteLine("Couldn't set zoom to 100, error: {0}", e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wordApplication.ComObject.Activate();
|
||||||
|
// ReSharper disable once EmptyGeneralCatchClause
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Warn().WriteLine(ex);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wordDocument.ComObject.Activate();
|
||||||
|
// ReSharper disable once EmptyGeneralCatchClause
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Warn().WriteLine(ex);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -304,76 +282,64 @@ namespace Greenshot.Addon.Office.OfficeExport
|
||||||
/// <param name="tooltip">string</param>
|
/// <param name="tooltip">string</param>
|
||||||
public void InsertIntoNewDocument(string tmpFile, string address, string tooltip)
|
public void InsertIntoNewDocument(string tmpFile, string address, string tooltip)
|
||||||
{
|
{
|
||||||
using (var wordApplication = GetOrCreateWordApplication())
|
using var wordApplication = GetOrCreateWordApplication();
|
||||||
|
if (wordApplication == null)
|
||||||
{
|
{
|
||||||
if (wordApplication == null)
|
return;
|
||||||
|
}
|
||||||
|
wordApplication.ComObject.Visible = true;
|
||||||
|
wordApplication.ComObject.Activate();
|
||||||
|
// Create new Document
|
||||||
|
object template = string.Empty;
|
||||||
|
object newTemplate = false;
|
||||||
|
object documentType = 0;
|
||||||
|
object documentVisible = true;
|
||||||
|
using var documents = DisposableCom.Create(wordApplication.ComObject.Documents);
|
||||||
|
using var wordDocument = DisposableCom.Create(documents.ComObject.Add(template, newTemplate, documentType, documentVisible));
|
||||||
|
using (var selection = DisposableCom.Create(wordApplication.ComObject.Selection))
|
||||||
|
{
|
||||||
|
// Add Picture
|
||||||
|
using var shape = AddPictureToSelection(selection, tmpFile);
|
||||||
|
if (!string.IsNullOrEmpty(address))
|
||||||
{
|
{
|
||||||
return;
|
object screentip = Type.Missing;
|
||||||
}
|
if (!string.IsNullOrEmpty(tooltip))
|
||||||
wordApplication.ComObject.Visible = true;
|
|
||||||
wordApplication.ComObject.Activate();
|
|
||||||
// Create new Document
|
|
||||||
object template = string.Empty;
|
|
||||||
object newTemplate = false;
|
|
||||||
object documentType = 0;
|
|
||||||
object documentVisible = true;
|
|
||||||
using (var documents = DisposableCom.Create(wordApplication.ComObject.Documents))
|
|
||||||
{
|
|
||||||
using (var wordDocument = DisposableCom.Create(documents.ComObject.Add(template, newTemplate, documentType, documentVisible)))
|
|
||||||
{
|
{
|
||||||
using (var selection = DisposableCom.Create(wordApplication.ComObject.Selection))
|
screentip = tooltip;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var hyperlinks = DisposableCom.Create(wordDocument.ComObject.Hyperlinks);
|
||||||
|
using (DisposableCom.Create(hyperlinks.ComObject.Add(shape, screentip, Type.Missing, screentip, Type.Missing, Type.Missing)))
|
||||||
{
|
{
|
||||||
// Add Picture
|
// Do nothing
|
||||||
using (var shape = AddPictureToSelection(selection, tmpFile))
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(address))
|
|
||||||
{
|
|
||||||
object screentip = Type.Missing;
|
|
||||||
if (!string.IsNullOrEmpty(tooltip))
|
|
||||||
{
|
|
||||||
screentip = tooltip;
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var hyperlinks = DisposableCom.Create(wordDocument.ComObject.Hyperlinks))
|
|
||||||
{
|
|
||||||
using (DisposableCom.Create(hyperlinks.ComObject.Add(shape, screentip, Type.Missing, screentip, Type.Missing, Type.Missing)))
|
|
||||||
{
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Log.Warn().WriteLine("Couldn't add hyperlink for image: {0}", e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
wordDocument.ComObject.Activate();
|
|
||||||
// ReSharper disable once EmptyGeneralCatchClause
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Warn().WriteLine(ex);
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var activeWindow = DisposableCom.Create(wordDocument.ComObject.ActiveWindow))
|
|
||||||
{
|
|
||||||
activeWindow.ComObject.Activate();
|
|
||||||
}
|
|
||||||
// ReSharper disable once EmptyGeneralCatchClause
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Warn().WriteLine(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Warn().WriteLine("Couldn't add hyperlink for image: {0}", e.Message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wordDocument.ComObject.Activate();
|
||||||
|
// ReSharper disable once EmptyGeneralCatchClause
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Warn().WriteLine(ex);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var activeWindow = DisposableCom.Create(wordDocument.ComObject.ActiveWindow);
|
||||||
|
activeWindow.ComObject.Activate();
|
||||||
|
// ReSharper disable once EmptyGeneralCatchClause
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Warn().WriteLine(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -126,10 +126,8 @@ namespace Greenshot.Addon.OneDrive
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
// TODO: Optimize this by caching
|
// TODO: Optimize this by caching
|
||||||
using (var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "onedrive.png"))
|
using var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "onedrive.png");
|
||||||
{
|
return BitmapHelper.FromStream(bitmapStream);
|
||||||
return BitmapHelper.FromStream(bitmapStream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,11 +186,9 @@ namespace Greenshot.Addon.OneDrive
|
||||||
|
|
||||||
if (_oneDriveConfiguration.AfterUploadLinkToClipBoard)
|
if (_oneDriveConfiguration.AfterUploadLinkToClipBoard)
|
||||||
{
|
{
|
||||||
using (var clipboardAccessToken = ClipboardNative.Access())
|
using var clipboardAccessToken = ClipboardNative.Access();
|
||||||
{
|
clipboardAccessToken.ClearContents();
|
||||||
clipboardAccessToken.ClearContents();
|
clipboardAccessToken.SetAsUrl(response.AbsoluteUri);
|
||||||
clipboardAccessToken.SetAsUrl(response.AbsoluteUri);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
|
@ -227,17 +223,13 @@ namespace Greenshot.Addon.OneDrive
|
||||||
localBehaviour.UploadProgress = percent => { Execute.OnUIThread(() => progress.Report((int)(percent * 100))); };
|
localBehaviour.UploadProgress = percent => { Execute.OnUIThread(() => progress.Report((int)(percent * 100))); };
|
||||||
}
|
}
|
||||||
var oauthHttpBehaviour = OAuth2HttpBehaviourFactory.Create(oAuth2Settings, localBehaviour);
|
var oauthHttpBehaviour = OAuth2HttpBehaviourFactory.Create(oAuth2Settings, localBehaviour);
|
||||||
using (var imageStream = new MemoryStream())
|
using var imageStream = new MemoryStream();
|
||||||
{
|
surfaceToUpload.WriteToStream(imageStream, CoreConfiguration, _oneDriveConfiguration);
|
||||||
surfaceToUpload.WriteToStream(imageStream, CoreConfiguration, _oneDriveConfiguration);
|
imageStream.Position = 0;
|
||||||
imageStream.Position = 0;
|
using var content = new StreamContent(imageStream);
|
||||||
using (var content = new StreamContent(imageStream))
|
content.Headers.Add("Content-Type", surfaceToUpload.GenerateMimeType(CoreConfiguration, _oneDriveConfiguration));
|
||||||
{
|
oauthHttpBehaviour.MakeCurrent();
|
||||||
content.Headers.Add("Content-Type", surfaceToUpload.GenerateMimeType(CoreConfiguration, _oneDriveConfiguration));
|
return await uploadUri.PutAsync<OneDriveUploadResponse>(content, token);
|
||||||
oauthHttpBehaviour.MakeCurrent();
|
|
||||||
return await uploadUri.PutAsync<OneDriveUploadResponse>(content, token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<OneDriveGetLinkResponse> CreateSharableLinkAync(OAuth2Settings oAuth2Settings,
|
private async Task<OneDriveGetLinkResponse> CreateSharableLinkAync(OAuth2Settings oAuth2Settings,
|
||||||
|
|
|
@ -185,12 +185,10 @@ namespace Greenshot.Addon.Photobucket
|
||||||
public override IBitmapWithNativeSupport DisplayIcon
|
public override IBitmapWithNativeSupport DisplayIcon
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
// TODO: Optimize this
|
// TODO: Optimize this
|
||||||
using (var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "photobucket-logo.png"))
|
using var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "photobucket-logo.png");
|
||||||
{
|
return BitmapHelper.FromStream(bitmapStream);
|
||||||
return BitmapHelper.FromStream(bitmapStream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,28 +293,26 @@ namespace Greenshot.Addon.Photobucket
|
||||||
{
|
{
|
||||||
surfaceToUpload.WriteToStream(imageStream, CoreConfiguration, _photobucketConfiguration);
|
surfaceToUpload.WriteToStream(imageStream, CoreConfiguration, _photobucketConfiguration);
|
||||||
imageStream.Position = 0;
|
imageStream.Position = 0;
|
||||||
using (var streamContent = new StreamContent(imageStream))
|
using var streamContent = new StreamContent(imageStream);
|
||||||
|
streamContent.Headers.ContentType = new MediaTypeHeaderValue(surfaceToUpload.GenerateMimeType(CoreConfiguration, _photobucketConfiguration));
|
||||||
|
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
|
||||||
{
|
{
|
||||||
streamContent.Headers.ContentType = new MediaTypeHeaderValue(surfaceToUpload.GenerateMimeType(CoreConfiguration, _photobucketConfiguration));
|
Name = "\"uploadfile\"",
|
||||||
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
|
FileName = "\"" + filename + "\""
|
||||||
{
|
};
|
||||||
Name = "\"uploadfile\"",
|
|
||||||
FileName = "\"" + filename + "\""
|
|
||||||
};
|
|
||||||
|
|
||||||
HttpBehaviour.Current.SetConfig(new HttpRequestMessageConfiguration
|
HttpBehaviour.Current.SetConfig(new HttpRequestMessageConfiguration
|
||||||
{
|
{
|
||||||
Properties = signedParameters
|
Properties = signedParameters
|
||||||
});
|
});
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
responseString = await uploadUri.PostAsync<string>(streamContent, token);
|
responseString = await uploadUri.PostAsync<string>(streamContent, token);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log.Error().WriteLine(ex, "Error uploading to Photobucket.");
|
Log.Error().WriteLine(ex, "Error uploading to Photobucket.");
|
||||||
throw;
|
throw;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -145,21 +145,17 @@ namespace Greenshot.Addon.Tfs
|
||||||
|
|
||||||
var filename = surface.GenerateFilename(_coreConfiguration, _tfsConfiguration);
|
var filename = surface.GenerateFilename(_coreConfiguration, _tfsConfiguration);
|
||||||
var attachmentUri = apiUri.AppendSegments("wit", "attachments").ExtendQuery("fileName", filename);
|
var attachmentUri = apiUri.AppendSegments("wit", "attachments").ExtendQuery("fileName", filename);
|
||||||
using (var imageStream = new MemoryStream())
|
using var imageStream = new MemoryStream();
|
||||||
|
surface.WriteToStream(imageStream, _coreConfiguration, _tfsConfiguration);
|
||||||
|
imageStream.Position = 0;
|
||||||
|
using var content = new StreamContent(imageStream);
|
||||||
|
content.SetContentType("application/octet-stream");
|
||||||
|
var createAttachmentresult = await client.PostAsync<HttpResponse<CreateAttachmentResult, string>>(attachmentUri, content).ConfigureAwait(false);
|
||||||
|
if (createAttachmentresult.HasError)
|
||||||
{
|
{
|
||||||
surface.WriteToStream(imageStream, _coreConfiguration, _tfsConfiguration);
|
throw new Exception(createAttachmentresult.ErrorResponse);
|
||||||
imageStream.Position = 0;
|
|
||||||
using (var content = new StreamContent(imageStream))
|
|
||||||
{
|
|
||||||
content.SetContentType("application/octet-stream");
|
|
||||||
var createAttachmentresult = await client.PostAsync<HttpResponse<CreateAttachmentResult, string>>(attachmentUri, content).ConfigureAwait(false);
|
|
||||||
if (createAttachmentresult.HasError)
|
|
||||||
{
|
|
||||||
throw new Exception(createAttachmentresult.ErrorResponse);
|
|
||||||
}
|
|
||||||
return createAttachmentresult.Response;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return createAttachmentresult.Response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -165,10 +165,8 @@ namespace Greenshot.Addon.Tfs
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
// TODO: Optimize this by using a cache
|
// TODO: Optimize this by using a cache
|
||||||
using (var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "vsts.png"))
|
using var bitmapStream = _resourceProvider.ResourceAsStream(GetType().Assembly, "vsts.png");
|
||||||
{
|
return BitmapHelper.FromStream(bitmapStream);
|
||||||
return BitmapHelper.FromStream(bitmapStream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,11 +222,9 @@ namespace Greenshot.Addon.Tfs
|
||||||
|
|
||||||
if (_tfsConfiguration.AfterUploadLinkToClipBoard)
|
if (_tfsConfiguration.AfterUploadLinkToClipBoard)
|
||||||
{
|
{
|
||||||
using (var clipboardAccessToken = ClipboardNative.Access())
|
using var clipboardAccessToken = ClipboardNative.Access();
|
||||||
{
|
clipboardAccessToken.ClearContents();
|
||||||
clipboardAccessToken.ClearContents();
|
clipboardAccessToken.SetAsUrl(response.AbsoluteUri);
|
||||||
clipboardAccessToken.SetAsUrl(response.AbsoluteUri);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
|
|
|
@ -67,19 +67,14 @@ namespace Greenshot.Addons.Animation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected double EasingValue
|
protected double EasingValue
|
||||||
{
|
{
|
||||||
get
|
get =>
|
||||||
{
|
EasingMode switch
|
||||||
switch (EasingMode)
|
{
|
||||||
{
|
EasingModes.EaseOut => Easing.EaseOut(CurrentFrameNr / (double) Frames, EasingType),
|
||||||
case EasingModes.EaseOut:
|
EasingModes.EaseInOut => Easing.EaseInOut(CurrentFrameNr / (double) Frames, EasingType),
|
||||||
return Easing.EaseOut(CurrentFrameNr / (double) Frames, EasingType);
|
_ => Easing.EaseIn(CurrentFrameNr / (double) Frames, EasingType)
|
||||||
case EasingModes.EaseInOut:
|
};
|
||||||
return Easing.EaseInOut(CurrentFrameNr / (double) Frames, EasingType);
|
}
|
||||||
default:
|
|
||||||
return Easing.EaseIn(CurrentFrameNr / (double) Frames, EasingType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Final animation value, this is including the legs
|
/// Final animation value, this is including the legs
|
||||||
|
|
|
@ -47,27 +47,18 @@ namespace Greenshot.Addons.Animation
|
||||||
/// <param name="linearStep">double</param>
|
/// <param name="linearStep">double</param>
|
||||||
/// <param name="type">EasingTypes</param>
|
/// <param name="type">EasingTypes</param>
|
||||||
/// <returns>double</returns>
|
/// <returns>double</returns>
|
||||||
public static double EaseIn(double linearStep, EasingTypes type)
|
public static double EaseIn(double linearStep, EasingTypes type) =>
|
||||||
{
|
type switch
|
||||||
switch (type)
|
{
|
||||||
{
|
EasingTypes.Step => (linearStep < 0.5 ? 0 : 1),
|
||||||
case EasingTypes.Step:
|
EasingTypes.Linear => linearStep,
|
||||||
return linearStep < 0.5 ? 0 : 1;
|
EasingTypes.Sine => EaseSine.EaseIn(linearStep),
|
||||||
case EasingTypes.Linear:
|
EasingTypes.Quadratic => EasePower.EaseIn(linearStep, 2),
|
||||||
return linearStep;
|
EasingTypes.Cubic => EasePower.EaseIn(linearStep, 3),
|
||||||
case EasingTypes.Sine:
|
EasingTypes.Quartic => EasePower.EaseIn(linearStep, 4),
|
||||||
return EaseSine.EaseIn(linearStep);
|
EasingTypes.Quintic => EasePower.EaseIn(linearStep, 5),
|
||||||
case EasingTypes.Quadratic:
|
_ => throw new NotImplementedException()
|
||||||
return EasePower.EaseIn(linearStep, 2);
|
};
|
||||||
case EasingTypes.Cubic:
|
|
||||||
return EasePower.EaseIn(linearStep, 3);
|
|
||||||
case EasingTypes.Quartic:
|
|
||||||
return EasePower.EaseIn(linearStep, 4);
|
|
||||||
case EasingTypes.Quintic:
|
|
||||||
return EasePower.EaseIn(linearStep, 5);
|
|
||||||
}
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Apply ease in-out
|
/// Apply ease in-out
|
||||||
|
@ -87,54 +78,36 @@ namespace Greenshot.Addons.Animation
|
||||||
/// <param name="linearStep">double</param>
|
/// <param name="linearStep">double</param>
|
||||||
/// <param name="type">EasingTypes</param>
|
/// <param name="type">EasingTypes</param>
|
||||||
/// <returns>double</returns>
|
/// <returns>double</returns>
|
||||||
public static double EaseInOut(double linearStep, EasingTypes type)
|
public static double EaseInOut(double linearStep, EasingTypes type) =>
|
||||||
{
|
type switch
|
||||||
switch (type)
|
{
|
||||||
{
|
EasingTypes.Step => (linearStep < 0.5 ? 0 : 1),
|
||||||
case EasingTypes.Step:
|
EasingTypes.Linear => linearStep,
|
||||||
return linearStep < 0.5 ? 0 : 1;
|
EasingTypes.Sine => EaseSine.EaseInOut(linearStep),
|
||||||
case EasingTypes.Linear:
|
EasingTypes.Quadratic => EasePower.EaseInOut(linearStep, 2),
|
||||||
return linearStep;
|
EasingTypes.Cubic => EasePower.EaseInOut(linearStep, 3),
|
||||||
case EasingTypes.Sine:
|
EasingTypes.Quartic => EasePower.EaseInOut(linearStep, 4),
|
||||||
return EaseSine.EaseInOut(linearStep);
|
EasingTypes.Quintic => EasePower.EaseInOut(linearStep, 5),
|
||||||
case EasingTypes.Quadratic:
|
_ => throw new NotImplementedException()
|
||||||
return EasePower.EaseInOut(linearStep, 2);
|
};
|
||||||
case EasingTypes.Cubic:
|
|
||||||
return EasePower.EaseInOut(linearStep, 3);
|
|
||||||
case EasingTypes.Quartic:
|
|
||||||
return EasePower.EaseInOut(linearStep, 4);
|
|
||||||
case EasingTypes.Quintic:
|
|
||||||
return EasePower.EaseInOut(linearStep, 5);
|
|
||||||
}
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Apply easy out
|
/// Apply easy out
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="linearStep">double</param>
|
/// <param name="linearStep">double</param>
|
||||||
/// <param name="type">EasingTypes</param>
|
/// <param name="type">EasingTypes</param>
|
||||||
/// <returns>double</returns>
|
/// <returns>double</returns>
|
||||||
public static double EaseOut(double linearStep, EasingTypes type)
|
public static double EaseOut(double linearStep, EasingTypes type) =>
|
||||||
{
|
type switch
|
||||||
switch (type)
|
{
|
||||||
{
|
EasingTypes.Step => (linearStep < 0.5 ? 0 : 1),
|
||||||
case EasingTypes.Step:
|
EasingTypes.Linear => linearStep,
|
||||||
return linearStep < 0.5 ? 0 : 1;
|
EasingTypes.Sine => EaseSine.EaseOut(linearStep),
|
||||||
case EasingTypes.Linear:
|
EasingTypes.Quadratic => EasePower.EaseOut(linearStep, 2),
|
||||||
return linearStep;
|
EasingTypes.Cubic => EasePower.EaseOut(linearStep, 3),
|
||||||
case EasingTypes.Sine:
|
EasingTypes.Quartic => EasePower.EaseOut(linearStep, 4),
|
||||||
return EaseSine.EaseOut(linearStep);
|
EasingTypes.Quintic => EasePower.EaseOut(linearStep, 5),
|
||||||
case EasingTypes.Quadratic:
|
_ => throw new NotImplementedException()
|
||||||
return EasePower.EaseOut(linearStep, 2);
|
};
|
||||||
case EasingTypes.Cubic:
|
}
|
||||||
return EasePower.EaseOut(linearStep, 3);
|
|
||||||
case EasingTypes.Quartic:
|
|
||||||
return EasePower.EaseOut(linearStep, 4);
|
|
||||||
case EasingTypes.Quintic:
|
|
||||||
return EasePower.EaseOut(linearStep, 5);
|
|
||||||
}
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -81,13 +81,11 @@ namespace Greenshot.Addons.Controls
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_vRefresh == 0)
|
if (_vRefresh == 0)
|
||||||
{
|
{
|
||||||
// get te hDC of the desktop to get the VREFRESH
|
// get te hDC of the desktop to get the VREFRESH
|
||||||
using (var desktopHandle = SafeWindowDcHandle.FromDesktop())
|
using var desktopHandle = SafeWindowDcHandle.FromDesktop();
|
||||||
{
|
_vRefresh = Gdi32Api.GetDeviceCaps(desktopHandle, DeviceCaps.VREFRESH);
|
||||||
_vRefresh = Gdi32Api.GetDeviceCaps(desktopHandle, DeviceCaps.VREFRESH);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
// A vertical refresh rate value of 0 or 1 represents the display hardware's default refresh rate.
|
// A vertical refresh rate value of 0 or 1 represents the display hardware's default refresh rate.
|
||||||
// As there is currently no know way to get the default, we guess it.
|
// As there is currently no know way to get the default, we guess it.
|
||||||
if (_vRefresh <= 1)
|
if (_vRefresh <= 1)
|
||||||
|
|
|
@ -101,20 +101,18 @@ namespace Greenshot.Addons.Controls
|
||||||
/// <param name="screenCoordinates">Point with the coordinates</param>
|
/// <param name="screenCoordinates">Point with the coordinates</param>
|
||||||
/// <returns>Color at the specified screenCoordinates</returns>
|
/// <returns>Color at the specified screenCoordinates</returns>
|
||||||
private static Color GetPixelColor(Point screenCoordinates)
|
private static Color GetPixelColor(Point screenCoordinates)
|
||||||
{
|
{
|
||||||
using (var screenDc = SafeWindowDcHandle.FromDesktop())
|
using var screenDc = SafeWindowDcHandle.FromDesktop();
|
||||||
{
|
try
|
||||||
try
|
{
|
||||||
{
|
var pixel = Gdi32Api.GetPixel(screenDc, screenCoordinates.X, screenCoordinates.Y);
|
||||||
var pixel = Gdi32Api.GetPixel(screenDc, screenCoordinates.X, screenCoordinates.Y);
|
var color = Color.FromArgb(255, (int) (pixel & 0xFF), (int) (pixel & 0xFF00) >> 8, (int) (pixel & 0xFF0000) >> 16);
|
||||||
var color = Color.FromArgb(255, (int) (pixel & 0xFF), (int) (pixel & 0xFF00) >> 8, (int) (pixel & 0xFF0000) >> 16);
|
return color;
|
||||||
return color;
|
}
|
||||||
}
|
catch (Exception)
|
||||||
catch (Exception)
|
{
|
||||||
{
|
return Color.Empty;
|
||||||
return Color.Empty;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -132,6 +132,7 @@ namespace Greenshot.Addons.Core
|
||||||
_safeDibSectionHandle.Dispose();
|
_safeDibSectionHandle.Dispose();
|
||||||
_safeCompatibleDcHandle.Dispose();
|
_safeCompatibleDcHandle.Dispose();
|
||||||
_desktopDcHandle.Dispose();
|
_desktopDcHandle.Dispose();
|
||||||
|
_bitmap.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,26 +122,24 @@ EndSelection:<<<<<<<4
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
User32Api.GetWindowThreadProcessId(hWnd, out var pid);
|
User32Api.GetWindowThreadProcessId(hWnd, out var pid);
|
||||||
using (var me = Process.GetCurrentProcess())
|
using var me = Process.GetCurrentProcess();
|
||||||
using (var ownerProcess = Process.GetProcessById(pid))
|
using var ownerProcess = Process.GetProcessById(pid);
|
||||||
{
|
// Exclude myself
|
||||||
// Exclude myself
|
if (me.Id != ownerProcess.Id)
|
||||||
if (me.Id != ownerProcess.Id)
|
{
|
||||||
{
|
// Get Process Name
|
||||||
// Get Process Name
|
owner = ownerProcess.ProcessName;
|
||||||
owner = ownerProcess.ProcessName;
|
// Try to get the starting Process Filename, this might fail.
|
||||||
// Try to get the starting Process Filename, this might fail.
|
try
|
||||||
try
|
{
|
||||||
{
|
owner = ownerProcess.Modules[0].FileName;
|
||||||
owner = ownerProcess.Modules[0].FileName;
|
}
|
||||||
}
|
catch (Exception)
|
||||||
catch (Exception)
|
{
|
||||||
{
|
// Ignore
|
||||||
// Ignore
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Log.Warn().WriteLine(e, "Non critical error: Couldn't get clipboard process, trying to use the title.");
|
Log.Warn().WriteLine(e, "Non critical error: Couldn't get clipboard process, trying to use the title.");
|
||||||
|
@ -483,18 +481,16 @@ EndSelection:<<<<<<<4
|
||||||
var fileHeader = BitmapFileHeader.Create(infoHeader);
|
var fileHeader = BitmapFileHeader.Create(infoHeader);
|
||||||
var fileHeaderBytes = BinaryStructHelper.ToByteArray(fileHeader);
|
var fileHeaderBytes = BinaryStructHelper.ToByteArray(fileHeader);
|
||||||
|
|
||||||
using (var bitmapStream = new MemoryStream())
|
using var bitmapStream = new MemoryStream();
|
||||||
{
|
bitmapStream.Write(fileHeaderBytes, 0, fileHeaderSize);
|
||||||
bitmapStream.Write(fileHeaderBytes, 0, fileHeaderSize);
|
bitmapStream.Write(dibBuffer, 0, dibBuffer.Length);
|
||||||
bitmapStream.Write(dibBuffer, 0, dibBuffer.Length);
|
bitmapStream.Seek(0, SeekOrigin.Begin);
|
||||||
bitmapStream.Seek(0, SeekOrigin.Begin);
|
var image = BitmapHelper.FromStream(bitmapStream);
|
||||||
var image = BitmapHelper.FromStream(bitmapStream);
|
if (image != null)
|
||||||
if (image != null)
|
{
|
||||||
{
|
return image;
|
||||||
return image;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log.Info().WriteLine("Using special DIBV5 / Format17 format reader");
|
Log.Info().WriteLine("Using special DIBV5 / Format17 format reader");
|
||||||
|
|
|
@ -326,8 +326,9 @@ namespace Greenshot.Addons.Core.Credentials
|
||||||
info.pszCaptionText = Caption;
|
info.pszCaptionText = Caption;
|
||||||
info.pszMessageText = Message;
|
info.pszMessageText = Message;
|
||||||
if (Banner != null)
|
if (Banner != null)
|
||||||
{
|
{
|
||||||
info.hbmBanner = new Bitmap(Banner, ValidBannerWidth, ValidBannerHeight).GetHbitmap();
|
using var bitmap = new Bitmap(Banner, ValidBannerWidth, ValidBannerHeight);
|
||||||
|
info.hbmBanner = bitmap.GetHbitmap();
|
||||||
}
|
}
|
||||||
info.cbSize = Marshal.SizeOf(info);
|
info.cbSize = Marshal.SizeOf(info);
|
||||||
return info;
|
return info;
|
||||||
|
@ -380,36 +381,21 @@ namespace Greenshot.Addons.Core.Credentials
|
||||||
|
|
||||||
/// <summary>Returns a DialogResult from the specified code.</summary>
|
/// <summary>Returns a DialogResult from the specified code.</summary>
|
||||||
/// <param name="code">The credential return code.</param>
|
/// <param name="code">The credential return code.</param>
|
||||||
private DialogResult GetDialogResult(CredUiReturnCodes code)
|
private DialogResult GetDialogResult(CredUiReturnCodes code) =>
|
||||||
{
|
code switch
|
||||||
DialogResult result;
|
{
|
||||||
switch (code)
|
CredUiReturnCodes.NoError => DialogResult.OK,
|
||||||
{
|
CredUiReturnCodes.ErrorCancelled => DialogResult.Cancel,
|
||||||
case CredUiReturnCodes.NoError:
|
CredUiReturnCodes.ErrorNoSuchLogonSession => throw new ApplicationException("No such logon session."),
|
||||||
result = DialogResult.OK;
|
CredUiReturnCodes.ErrorNotFound => throw new ApplicationException("Not found."),
|
||||||
break;
|
CredUiReturnCodes.ErrorInvalidAccountName => throw new ApplicationException("Invalid account name."),
|
||||||
case CredUiReturnCodes.ErrorCancelled:
|
CredUiReturnCodes.ErrorInsufficientBuffer => throw new ApplicationException("Insufficient buffer."),
|
||||||
result = DialogResult.Cancel;
|
CredUiReturnCodes.ErrorInvalidParameter => throw new ApplicationException("Invalid parameter."),
|
||||||
break;
|
CredUiReturnCodes.ErrorInvalidFlags => throw new ApplicationException("Invalid flags."),
|
||||||
case CredUiReturnCodes.ErrorNoSuchLogonSession:
|
_ => throw new ApplicationException("Unknown credential result encountered.")
|
||||||
throw new ApplicationException("No such logon session.");
|
};
|
||||||
case CredUiReturnCodes.ErrorNotFound:
|
|
||||||
throw new ApplicationException("Not found.");
|
|
||||||
case CredUiReturnCodes.ErrorInvalidAccountName:
|
|
||||||
throw new ApplicationException("Invalid account name.");
|
|
||||||
case CredUiReturnCodes.ErrorInsufficientBuffer:
|
|
||||||
throw new ApplicationException("Insufficient buffer.");
|
|
||||||
case CredUiReturnCodes.ErrorInvalidParameter:
|
|
||||||
throw new ApplicationException("Invalid parameter.");
|
|
||||||
case CredUiReturnCodes.ErrorInvalidFlags:
|
|
||||||
throw new ApplicationException("Invalid flags.");
|
|
||||||
default:
|
|
||||||
throw new ApplicationException("Unknown credential result encountered.");
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// http://www.pinvoke.net/default.aspx/credui.CredUIPromptForCredentialsW
|
/// http://www.pinvoke.net/default.aspx/credui.CredUIPromptForCredentialsW
|
||||||
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/creduipromptforcredentials.asp
|
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/creduipromptforcredentials.asp
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -56,12 +56,10 @@ namespace Greenshot.Addons.Core
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>bool</returns>
|
/// <returns>bool</returns>
|
||||||
public static bool HasMapi()
|
public static bool HasMapi()
|
||||||
{
|
{
|
||||||
using (var key = Registry.LocalMachine.OpenSubKey(MapiLocationKey, false))
|
using var key = Registry.LocalMachine.OpenSubKey(MapiLocationKey, false);
|
||||||
{
|
return key != null && "1".Equals(key.GetValue(MapiKey, "0"));
|
||||||
return key != null && "1".Equals(key.GetValue(MapiKey, "0"));
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the path of Outlook from the registry
|
/// Get the path of Outlook from the registry
|
||||||
|
|
|
@ -67,12 +67,10 @@ namespace Greenshot.Addons.Core
|
||||||
UseShellExecute = true
|
UseShellExecute = true
|
||||||
};
|
};
|
||||||
// Start the explorer process and select the file
|
// Start the explorer process and select the file
|
||||||
using (var explorer = Process.Start(processStartInfo))
|
using var explorer = Process.Start(processStartInfo);
|
||||||
{
|
explorer?.WaitForInputIdle(500);
|
||||||
explorer?.WaitForInputIdle(500);
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
@ -96,7 +96,7 @@ namespace Greenshot.Addons.Core
|
||||||
// Set the text
|
// Set the text
|
||||||
var byteString = Encoding.ASCII.GetBytes(text + " ");
|
var byteString = Encoding.ASCII.GetBytes(text + " ");
|
||||||
// Set Zero byte for String end.
|
// Set Zero byte for String end.
|
||||||
byteString[byteString.Length - 1] = 0;
|
byteString[^1] = 0;
|
||||||
propertyItem.Value = byteString;
|
propertyItem.Value = byteString;
|
||||||
propertyItem.Len = text.Length + 1;
|
propertyItem.Len = text.Length + 1;
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ namespace Greenshot.Addons.Core
|
||||||
if (CoreConfiguration.OutputFilePromptQuality)
|
if (CoreConfiguration.OutputFilePromptQuality)
|
||||||
{
|
{
|
||||||
// TODO: Use factory
|
// TODO: Use factory
|
||||||
var qualityDialog = new QualityDialog(outputSettings, CoreConfiguration, GreenshotLanguage);
|
using var qualityDialog = new QualityDialog(outputSettings, CoreConfiguration, GreenshotLanguage);
|
||||||
qualityDialog.ShowDialog();
|
qualityDialog.ShowDialog();
|
||||||
}
|
}
|
||||||
// TODO: For now we always overwrite, should be changed
|
// TODO: For now we always overwrite, should be changed
|
||||||
|
@ -309,25 +309,19 @@ namespace Greenshot.Addons.Core
|
||||||
}
|
}
|
||||||
var imageStream = new MemoryStream();
|
var imageStream = new MemoryStream();
|
||||||
if (bitmap.Width == size && bitmap.Height == size)
|
if (bitmap.Width == size && bitmap.Height == size)
|
||||||
{
|
{
|
||||||
using (var clonedImage = bitmap.CloneBitmap(PixelFormat.Format32bppArgb))
|
using var clonedImage = bitmap.CloneBitmap(PixelFormat.Format32bppArgb);
|
||||||
{
|
clonedImage.NativeBitmap.Save(imageStream, ImageFormat.Png);
|
||||||
clonedImage.NativeBitmap.Save(imageStream, ImageFormat.Png);
|
imageSizes.Add(new Size(size, size));
|
||||||
imageSizes.Add(new Size(size, size));
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Resize to the specified size, first make sure the image is 32bpp
|
// Resize to the specified size, first make sure the image is 32bpp
|
||||||
using (var clonedImage = bitmap.CloneBitmap(PixelFormat.Format32bppArgb))
|
using var clonedImage = bitmap.CloneBitmap(PixelFormat.Format32bppArgb);
|
||||||
{
|
using var resizedImage = clonedImage.Resize(true, true, Color.Empty, size, size, null);
|
||||||
using (var resizedImage = clonedImage.Resize(true, true, Color.Empty, size, size, null))
|
resizedImage.NativeBitmap.Save(imageStream, ImageFormat.Png);
|
||||||
{
|
imageSizes.Add(resizedImage.Size);
|
||||||
resizedImage.NativeBitmap.Save(imageStream, ImageFormat.Png);
|
}
|
||||||
imageSizes.Add(resizedImage.Size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
imageStream.Seek(0, SeekOrigin.Begin);
|
imageStream.Seek(0, SeekOrigin.Begin);
|
||||||
encodedImages.Add(imageStream);
|
encodedImages.Add(imageStream);
|
||||||
|
@ -395,13 +389,11 @@ namespace Greenshot.Addons.Core
|
||||||
Log.Info().WriteLine("Greenshot file format: {0}", greenshotMarker);
|
Log.Info().WriteLine("Greenshot file format: {0}", greenshotMarker);
|
||||||
const int filesizeLocation = 8 + markerSize;
|
const int filesizeLocation = 8 + markerSize;
|
||||||
surfaceFileStream.Seek(-filesizeLocation, SeekOrigin.End);
|
surfaceFileStream.Seek(-filesizeLocation, SeekOrigin.End);
|
||||||
using (var reader = new BinaryReader(surfaceFileStream))
|
using var reader = new BinaryReader(surfaceFileStream);
|
||||||
{
|
var bytesWritten = reader.ReadInt64();
|
||||||
var bytesWritten = reader.ReadInt64();
|
surfaceFileStream.Seek(-(bytesWritten + filesizeLocation), SeekOrigin.End);
|
||||||
surfaceFileStream.Seek(-(bytesWritten + filesizeLocation), SeekOrigin.End);
|
returnSurface.LoadElementsFromStream(surfaceFileStream);
|
||||||
returnSurface.LoadElementsFromStream(surfaceFileStream);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fileImage == null)
|
if (fileImage == null)
|
||||||
{
|
{
|
||||||
return returnSurface;
|
return returnSurface;
|
||||||
|
@ -566,20 +558,16 @@ namespace Greenshot.Addons.Core
|
||||||
|
|
||||||
// Output the surface elements, size and marker to the stream
|
// Output the surface elements, size and marker to the stream
|
||||||
if (outputSettings.Format == OutputFormats.greenshot)
|
if (outputSettings.Format == OutputFormats.greenshot)
|
||||||
{
|
{
|
||||||
using (var tmpStream = new MemoryStream())
|
using var tmpStream = new MemoryStream();
|
||||||
{
|
var bytesWritten = surface.SaveElementsToStream(tmpStream);
|
||||||
var bytesWritten = surface.SaveElementsToStream(tmpStream);
|
using var writer = new BinaryWriter(tmpStream);
|
||||||
using (var writer = new BinaryWriter(tmpStream))
|
writer.Write(bytesWritten);
|
||||||
{
|
var v = Assembly.GetExecutingAssembly().GetName().Version;
|
||||||
writer.Write(bytesWritten);
|
var marker = Encoding.ASCII.GetBytes($"Greenshot{v.Major:00}.{v.Minor:00}");
|
||||||
var v = Assembly.GetExecutingAssembly().GetName().Version;
|
writer.Write(marker);
|
||||||
var marker = Encoding.ASCII.GetBytes($"Greenshot{v.Major:00}.{v.Minor:00}");
|
tmpStream.WriteTo(stream);
|
||||||
writer.Write(marker);
|
}
|
||||||
tmpStream.WriteTo(stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -630,28 +618,26 @@ namespace Greenshot.Addons.Core
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
UseShellExecute = true
|
UseShellExecute = true
|
||||||
};
|
};
|
||||||
using (var process = Process.Start(processStartInfo))
|
using var process = Process.Start(processStartInfo);
|
||||||
{
|
if (process != null)
|
||||||
if (process != null)
|
{
|
||||||
{
|
process.WaitForExit();
|
||||||
process.WaitForExit();
|
if (process.ExitCode == 0)
|
||||||
if (process.ExitCode == 0)
|
{
|
||||||
{
|
if (Log.IsDebugEnabled())
|
||||||
if (Log.IsDebugEnabled())
|
{
|
||||||
{
|
Log.Debug().WriteLine("File size after processing {0}", new FileInfo(tmpFileName).Length);
|
||||||
Log.Debug().WriteLine("File size after processing {0}", new FileInfo(tmpFileName).Length);
|
Log.Debug().WriteLine("Reading back tmp file: {0}", tmpFileName);
|
||||||
Log.Debug().WriteLine("Reading back tmp file: {0}", tmpFileName);
|
}
|
||||||
}
|
var processedImage = File.ReadAllBytes(tmpFileName);
|
||||||
var processedImage = File.ReadAllBytes(tmpFileName);
|
targetStream.Write(processedImage, 0, processedImage.Length);
|
||||||
targetStream.Write(processedImage, 0, processedImage.Length);
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
Log.Error().WriteLine("Error while processing PNG image: {0}", process.ExitCode);
|
||||||
Log.Error().WriteLine("Error while processing PNG image: {0}", process.ExitCode);
|
Log.Error().WriteLine("Output: {0}", process.StandardOutput.ReadToEnd());
|
||||||
Log.Error().WriteLine("Output: {0}", process.StandardOutput.ReadToEnd());
|
Log.Error().WriteLine("Error: {0}", process.StandardError.ReadToEnd());
|
||||||
Log.Error().WriteLine("Error: {0}", process.StandardError.ReadToEnd());
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Log.Error().WriteLine(e, "Error while processing PNG image: ");
|
Log.Error().WriteLine(e, "Error while processing PNG image: ");
|
||||||
|
@ -721,33 +707,31 @@ namespace Greenshot.Addons.Core
|
||||||
}
|
}
|
||||||
var isAlpha = Image.IsAlphaPixelFormat(bitmapToSave.PixelFormat);
|
var isAlpha = Image.IsAlphaPixelFormat(bitmapToSave.PixelFormat);
|
||||||
if (outputSettings.ReduceColors || !isAlpha && CoreConfiguration.OutputFileAutoReduceColors)
|
if (outputSettings.ReduceColors || !isAlpha && CoreConfiguration.OutputFileAutoReduceColors)
|
||||||
{
|
{
|
||||||
using (var quantizer = new WuQuantizer(bitmapToSave))
|
using var quantizer = new WuQuantizer(bitmapToSave);
|
||||||
{
|
var colorCount = quantizer.GetColorCount();
|
||||||
var colorCount = quantizer.GetColorCount();
|
Log.Info().WriteLine("Image with format {0} has {1} colors", bitmapToSave.PixelFormat, colorCount);
|
||||||
Log.Info().WriteLine("Image with format {0} has {1} colors", bitmapToSave.PixelFormat, colorCount);
|
if (!outputSettings.ReduceColors && colorCount >= 256)
|
||||||
if (!outputSettings.ReduceColors && colorCount >= 256)
|
{
|
||||||
{
|
return disposeImage;
|
||||||
return disposeImage;
|
}
|
||||||
}
|
try
|
||||||
try
|
{
|
||||||
{
|
Log.Info().WriteLine("Reducing colors on bitmap to 256.");
|
||||||
Log.Info().WriteLine("Reducing colors on bitmap to 256.");
|
tmpBitmap = quantizer.GetQuantizedImage(CoreConfiguration.OutputFileReduceColorsTo);
|
||||||
tmpBitmap = quantizer.GetQuantizedImage(CoreConfiguration.OutputFileReduceColorsTo);
|
if (disposeImage)
|
||||||
if (disposeImage)
|
{
|
||||||
{
|
bitmapToSave.Dispose();
|
||||||
bitmapToSave.Dispose();
|
}
|
||||||
}
|
bitmapToSave = tmpBitmap;
|
||||||
bitmapToSave = tmpBitmap;
|
// Make sure the "new" image is disposed
|
||||||
// Make sure the "new" image is disposed
|
disposeImage = true;
|
||||||
disposeImage = true;
|
}
|
||||||
}
|
catch (Exception e)
|
||||||
catch (Exception e)
|
{
|
||||||
{
|
Log.Warn().WriteLine(e, "Error occurred while Quantizing the image, ignoring and using original. Error: ");
|
||||||
Log.Warn().WriteLine(e, "Error occurred while Quantizing the image, ignoring and using original. Error: ");
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (isAlpha && !outputSettings.ReduceColors)
|
else if (isAlpha && !outputSettings.ReduceColors)
|
||||||
{
|
{
|
||||||
Log.Info().WriteLine("Skipping 'optional' color reduction as the image has alpha");
|
Log.Info().WriteLine("Skipping 'optional' color reduction as the image has alpha");
|
||||||
|
@ -837,14 +821,12 @@ namespace Greenshot.Addons.Core
|
||||||
|
|
||||||
// TODO: This should not be done here, remove this!!
|
// TODO: This should not be done here, remove this!!
|
||||||
if (copyPathToClipboard)
|
if (copyPathToClipboard)
|
||||||
{
|
{
|
||||||
using (var clipboardAccessToken = ClipboardNative.Access())
|
using var clipboardAccessToken = ClipboardNative.Access();
|
||||||
{
|
clipboardAccessToken.ClearContents();
|
||||||
clipboardAccessToken.ClearContents();
|
// TODO: File??
|
||||||
// TODO: File??
|
clipboardAccessToken.SetAsUnicodeString(fullPath);
|
||||||
clipboardAccessToken.SetAsUnicodeString(fullPath);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -187,36 +187,34 @@ namespace Greenshot.Addons.Core
|
||||||
{
|
{
|
||||||
// Assume using it's own location
|
// Assume using it's own location
|
||||||
formLocation = windowRectangle.Location;
|
formLocation = windowRectangle.Location;
|
||||||
using (var workingArea = new Region(Screen.PrimaryScreen.Bounds))
|
using var workingArea = new Region(Screen.PrimaryScreen.Bounds);
|
||||||
|
// Find the screen where the window is and check if it fits
|
||||||
|
foreach (var screen in Screen.AllScreens)
|
||||||
{
|
{
|
||||||
// Find the screen where the window is and check if it fits
|
if (!Equals(screen, Screen.PrimaryScreen))
|
||||||
|
{
|
||||||
|
workingArea.Union(screen.Bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the formLocation is not inside the visible area
|
||||||
|
if (!workingArea.AreRectangleCornersVisisble(windowRectangle))
|
||||||
|
{
|
||||||
|
// If none found we find the biggest screen
|
||||||
foreach (var screen in Screen.AllScreens)
|
foreach (var screen in Screen.AllScreens)
|
||||||
{
|
{
|
||||||
if (!Equals(screen, Screen.PrimaryScreen))
|
var newWindowRectangle = new NativeRect(screen.WorkingArea.Location, windowRectangle.Size);
|
||||||
|
if (workingArea.AreRectangleCornersVisisble(newWindowRectangle))
|
||||||
{
|
{
|
||||||
workingArea.Union(screen.Bounds);
|
formLocation = screen.Bounds.Location;
|
||||||
|
doesCaptureFit = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// If the formLocation is not inside the visible area
|
else
|
||||||
if (!workingArea.AreRectangleCornersVisisble(windowRectangle))
|
{
|
||||||
{
|
doesCaptureFit = true;
|
||||||
// If none found we find the biggest screen
|
|
||||||
foreach (var screen in Screen.AllScreens)
|
|
||||||
{
|
|
||||||
var newWindowRectangle = new NativeRect(screen.WorkingArea.Location, windowRectangle.Size);
|
|
||||||
if (workingArea.AreRectangleCornersVisisble(newWindowRectangle))
|
|
||||||
{
|
|
||||||
formLocation = screen.Bounds.Location;
|
|
||||||
doesCaptureFit = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
doesCaptureFit = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!WindowsVersion.IsWindows8OrLater)
|
else if (!WindowsVersion.IsWindows8OrLater)
|
||||||
|
@ -251,13 +249,11 @@ namespace Greenshot.Addons.Core
|
||||||
if (!doesCaptureFit)
|
if (!doesCaptureFit)
|
||||||
{
|
{
|
||||||
// if GDI is allowed.. (a screenshot won't be better than we comes if we continue)
|
// if GDI is allowed.. (a screenshot won't be better than we comes if we continue)
|
||||||
using (var thisWindowProcess = Process.GetProcessById(interopWindow.GetProcessId()))
|
using var thisWindowProcess = Process.GetProcessById(interopWindow.GetProcessId());
|
||||||
|
if (!interopWindow.IsApp() && WindowCapture.IsGdiAllowed(thisWindowProcess))
|
||||||
{
|
{
|
||||||
if (!interopWindow.IsApp() && WindowCapture.IsGdiAllowed(thisWindowProcess))
|
// we return null which causes the capturing code to try another method.
|
||||||
{
|
return null;
|
||||||
// we return null which causes the capturing code to try another method.
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -289,25 +285,21 @@ namespace Greenshot.Addons.Core
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var whiteBitmap = WindowCapture.CaptureRectangle(captureRectangle))
|
using var whiteBitmap = WindowCapture.CaptureRectangle(captureRectangle);
|
||||||
|
// Apply a white color
|
||||||
|
tempForm.BackColor = Color.Black;
|
||||||
|
// Make sure everything is visible
|
||||||
|
tempForm.Refresh();
|
||||||
|
if (!interopWindow.IsApp())
|
||||||
{
|
{
|
||||||
// Apply a white color
|
// Make sure the application window is active, so the colors & buttons are right
|
||||||
tempForm.BackColor = Color.Black;
|
// TODO: Await?
|
||||||
// Make sure everything is visible
|
interopWindow.ToForegroundAsync();
|
||||||
tempForm.Refresh();
|
|
||||||
if (!interopWindow.IsApp())
|
|
||||||
{
|
|
||||||
// Make sure the application window is active, so the colors & buttons are right
|
|
||||||
// TODO: Await?
|
|
||||||
interopWindow.ToForegroundAsync();
|
|
||||||
}
|
|
||||||
// Make sure all changes are processed and visible
|
|
||||||
Application.DoEvents();
|
|
||||||
using (var blackBitmap = WindowCapture.CaptureRectangle(captureRectangle))
|
|
||||||
{
|
|
||||||
capturedBitmap = ApplyTransparency(blackBitmap, whiteBitmap);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// Make sure all changes are processed and visible
|
||||||
|
Application.DoEvents();
|
||||||
|
using var blackBitmap = WindowCapture.CaptureRectangle(captureRectangle);
|
||||||
|
capturedBitmap = ApplyTransparency(blackBitmap, whiteBitmap);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -400,17 +392,15 @@ namespace Greenshot.Addons.Core
|
||||||
/// <param name="image">The bitmap to remove the corners from.</param>
|
/// <param name="image">The bitmap to remove the corners from.</param>
|
||||||
private static void RemoveCorners(IBitmapWithNativeSupport image)
|
private static void RemoveCorners(IBitmapWithNativeSupport image)
|
||||||
{
|
{
|
||||||
using (var fastBitmap = FastBitmapFactory.Create(image))
|
using var fastBitmap = FastBitmapFactory.Create(image);
|
||||||
|
for (var y = 0; y < CoreConfiguration.WindowCornerCutShape.Count; y++)
|
||||||
{
|
{
|
||||||
for (var y = 0; y < CoreConfiguration.WindowCornerCutShape.Count; y++)
|
for (var x = 0; x < CoreConfiguration.WindowCornerCutShape[y]; x++)
|
||||||
{
|
{
|
||||||
for (var x = 0; x < CoreConfiguration.WindowCornerCutShape[y]; x++)
|
fastBitmap.SetColorAt(x, y, ref _transparentColor);
|
||||||
{
|
fastBitmap.SetColorAt(image.Width - 1 - x, y, ref _transparentColor);
|
||||||
fastBitmap.SetColorAt(x, y, ref _transparentColor);
|
fastBitmap.SetColorAt(image.Width - 1 - x, image.Height - 1 - y, ref _transparentColor);
|
||||||
fastBitmap.SetColorAt(image.Width - 1 - x, y, ref _transparentColor);
|
fastBitmap.SetColorAt(x, image.Height - 1 - y, ref _transparentColor);
|
||||||
fastBitmap.SetColorAt(image.Width - 1 - x, image.Height - 1 - y, ref _transparentColor);
|
|
||||||
fastBitmap.SetColorAt(x, image.Height - 1 - y, ref _transparentColor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,50 +415,46 @@ namespace Greenshot.Addons.Core
|
||||||
/// <returns>Bitmap with transparency</returns>
|
/// <returns>Bitmap with transparency</returns>
|
||||||
private static IBitmapWithNativeSupport ApplyTransparency(IBitmapWithNativeSupport blackBitmap, IBitmapWithNativeSupport whiteBitmap)
|
private static IBitmapWithNativeSupport ApplyTransparency(IBitmapWithNativeSupport blackBitmap, IBitmapWithNativeSupport whiteBitmap)
|
||||||
{
|
{
|
||||||
using (var targetBuffer = FastBitmapFactory.CreateEmpty(blackBitmap.Size, PixelFormat.Format32bppArgb, Color.Transparent))
|
using var targetBuffer = FastBitmapFactory.CreateEmpty(blackBitmap.Size, PixelFormat.Format32bppArgb, Color.Transparent);
|
||||||
|
targetBuffer.SetResolution(blackBitmap.HorizontalResolution, blackBitmap.VerticalResolution);
|
||||||
|
using (var blackBuffer = FastBitmapFactory.Create(blackBitmap))
|
||||||
{
|
{
|
||||||
targetBuffer.SetResolution(blackBitmap.HorizontalResolution, blackBitmap.VerticalResolution);
|
using var whiteBuffer = FastBitmapFactory.Create(whiteBitmap);
|
||||||
using (var blackBuffer = FastBitmapFactory.Create(blackBitmap))
|
for (var y = 0; y < blackBuffer.Height; y++)
|
||||||
{
|
{
|
||||||
using (var whiteBuffer = FastBitmapFactory.Create(whiteBitmap))
|
for (var x = 0; x < blackBuffer.Width; x++)
|
||||||
{
|
{
|
||||||
for (var y = 0; y < blackBuffer.Height; y++)
|
var c0 = blackBuffer.GetColorAt(x, y);
|
||||||
|
var c1 = whiteBuffer.GetColorAt(x, y);
|
||||||
|
// Calculate alpha as double in range 0-1
|
||||||
|
var alpha = c0.R - c1.R + 255;
|
||||||
|
if (alpha == 255)
|
||||||
{
|
{
|
||||||
for (var x = 0; x < blackBuffer.Width; x++)
|
// Alpha == 255 means no change!
|
||||||
{
|
targetBuffer.SetColorAt(x, y, ref c0);
|
||||||
var c0 = blackBuffer.GetColorAt(x, y);
|
}
|
||||||
var c1 = whiteBuffer.GetColorAt(x, y);
|
else if (alpha == 0)
|
||||||
// Calculate alpha as double in range 0-1
|
{
|
||||||
var alpha = c0.R - c1.R + 255;
|
// Complete transparency, use transparent pixel
|
||||||
if (alpha == 255)
|
targetBuffer.SetColorAt(x, y, ref _transparentColor);
|
||||||
{
|
}
|
||||||
// Alpha == 255 means no change!
|
else
|
||||||
targetBuffer.SetColorAt(x, y, ref c0);
|
{
|
||||||
}
|
// Calculate original color
|
||||||
else if (alpha == 0)
|
var originalAlpha = (byte) Math.Min(255, alpha);
|
||||||
{
|
var alphaFactor = alpha / 255d;
|
||||||
// Complete transparency, use transparent pixel
|
//Log.Debug().WriteLine("Alpha {0} & c0 {1} & c1 {2}", alpha, c0, c1);
|
||||||
targetBuffer.SetColorAt(x, y, ref _transparentColor);
|
var originalRed = (byte) Math.Min(255, c0.R / alphaFactor);
|
||||||
}
|
var originalGreen = (byte) Math.Min(255, c0.G / alphaFactor);
|
||||||
else
|
var originalBlue = (byte) Math.Min(255, c0.B / alphaFactor);
|
||||||
{
|
var originalColor = Color.FromArgb(originalAlpha, originalRed, originalGreen, originalBlue);
|
||||||
// Calculate original color
|
//Color originalColor = Color.FromArgb(originalAlpha, originalRed, c0.G, c0.B);
|
||||||
var originalAlpha = (byte) Math.Min(255, alpha);
|
targetBuffer.SetColorAt(x, y, ref originalColor);
|
||||||
var alphaFactor = alpha / 255d;
|
|
||||||
//Log.Debug().WriteLine("Alpha {0} & c0 {1} & c1 {2}", alpha, c0, c1);
|
|
||||||
var originalRed = (byte) Math.Min(255, c0.R / alphaFactor);
|
|
||||||
var originalGreen = (byte) Math.Min(255, c0.G / alphaFactor);
|
|
||||||
var originalBlue = (byte) Math.Min(255, c0.B / alphaFactor);
|
|
||||||
var originalColor = Color.FromArgb(originalAlpha, originalRed, originalGreen, originalBlue);
|
|
||||||
//Color originalColor = Color.FromArgb(originalAlpha, originalRed, c0.G, c0.B);
|
|
||||||
targetBuffer.SetColorAt(x, y, ref originalColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return targetBuffer.UnlockAndReturnBitmap();
|
|
||||||
}
|
}
|
||||||
|
return targetBuffer.UnlockAndReturnBitmap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -52,13 +52,11 @@ namespace Greenshot.Addons.Core
|
||||||
}
|
}
|
||||||
|
|
||||||
IFormatter formatter = new BinaryFormatter();
|
IFormatter formatter = new BinaryFormatter();
|
||||||
using (var stream = new MemoryStream())
|
using var stream = new MemoryStream();
|
||||||
{
|
formatter.Serialize(stream, source);
|
||||||
formatter.Serialize(stream, source);
|
stream.Seek(0, SeekOrigin.Begin);
|
||||||
stream.Seek(0, SeekOrigin.Begin);
|
return (T) formatter.Deserialize(stream);
|
||||||
return (T) formatter.Deserialize(stream);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clone the content from source to destination
|
/// Clone the content from source to destination
|
||||||
|
|
|
@ -116,10 +116,8 @@ namespace Greenshot.Addons.Core
|
||||||
// Set the location
|
// Set the location
|
||||||
capture.CursorLocation = new NativePoint(x, y);
|
capture.CursorLocation = new NativePoint(x, y);
|
||||||
|
|
||||||
using (var icon = Icon.FromHandle(safeIcon.DangerousGetHandle()))
|
using var icon = Icon.FromHandle(safeIcon.DangerousGetHandle());
|
||||||
{
|
capture.Cursor = icon;
|
||||||
capture.Cursor = icon;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return capture;
|
return capture;
|
||||||
|
@ -305,121 +303,113 @@ namespace Greenshot.Addons.Core
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a device context we can copy to
|
// create a device context we can copy to
|
||||||
using (var safeCompatibleDcHandle = Gdi32Api.CreateCompatibleDC(desktopDcHandle))
|
using var safeCompatibleDcHandle = Gdi32Api.CreateCompatibleDC(desktopDcHandle);
|
||||||
|
// Check if the device context is there, if not throw an error with as much info as possible!
|
||||||
|
if (safeCompatibleDcHandle.IsInvalid)
|
||||||
{
|
{
|
||||||
// Check if the device context is there, if not throw an error with as much info as possible!
|
// Get Exception before the error is lost
|
||||||
if (safeCompatibleDcHandle.IsInvalid)
|
var exceptionToThrow = CreateCaptureException("CreateCompatibleDC", captureBounds);
|
||||||
|
// throw exception
|
||||||
|
throw exceptionToThrow;
|
||||||
|
}
|
||||||
|
// Create BitmapInfoHeader for CreateDIBSection
|
||||||
|
var bmi = BitmapInfoHeader.Create(captureBounds.Width, captureBounds.Height, 24);
|
||||||
|
|
||||||
|
// TODO: Enable when the function is available again
|
||||||
|
// Make sure the last error is set to 0
|
||||||
|
Win32.SetLastError(0);
|
||||||
|
|
||||||
|
// create a bitmap we can copy it to, using GetDeviceCaps to get the width/height
|
||||||
|
// the returned (out) IntPtr _ is not used for our purposes. It returns a pointer to the raw bits that make up the bitmap.
|
||||||
|
using var safeDibSectionHandle = Gdi32Api.CreateDIBSection(desktopDcHandle, ref bmi, DibColors.PalColors, out _, IntPtr.Zero, 0);
|
||||||
|
if (safeDibSectionHandle.IsInvalid)
|
||||||
|
{
|
||||||
|
// Get Exception before the error is lost
|
||||||
|
var exceptionToThrow = CreateCaptureException("CreateDIBSection", captureBounds);
|
||||||
|
exceptionToThrow.Data.Add("hdcDest", safeCompatibleDcHandle.DangerousGetHandle().ToInt32());
|
||||||
|
exceptionToThrow.Data.Add("hdcSrc", desktopDcHandle.DangerousGetHandle().ToInt32());
|
||||||
|
|
||||||
|
// Throw so people can report the problem
|
||||||
|
throw exceptionToThrow;
|
||||||
|
}
|
||||||
|
// select the bitmap object and store the old handle
|
||||||
|
using (safeCompatibleDcHandle.SelectObject(safeDibSectionHandle))
|
||||||
|
{
|
||||||
|
// bit-blt over (make copy)
|
||||||
|
// ReSharper disable once BitwiseOperatorOnEnumWithoutFlags
|
||||||
|
Gdi32Api.BitBlt(safeCompatibleDcHandle, 0, 0, captureBounds.Width, captureBounds.Height, desktopDcHandle, captureBounds.X, captureBounds.Y,
|
||||||
|
RasterOperations.SourceCopy | RasterOperations.CaptureBlt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get a .NET image object for it
|
||||||
|
// A suggestion for the "A generic error occurred in GDI+." E_FAIL/0x80004005 error is to re-try...
|
||||||
|
ExternalException exception = null;
|
||||||
|
for (var i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
// Get Exception before the error is lost
|
// Collect all screens inside this capture
|
||||||
var exceptionToThrow = CreateCaptureException("CreateCompatibleDC", captureBounds);
|
var screensInsideCapture = new List<Screen>();
|
||||||
// throw exception
|
foreach (var screen in Screen.AllScreens)
|
||||||
throw exceptionToThrow;
|
|
||||||
}
|
|
||||||
// Create BitmapInfoHeader for CreateDIBSection
|
|
||||||
var bmi = BitmapInfoHeader.Create(captureBounds.Width, captureBounds.Height, 24);
|
|
||||||
|
|
||||||
// TODO: Enable when the function is available again
|
|
||||||
// Make sure the last error is set to 0
|
|
||||||
Win32.SetLastError(0);
|
|
||||||
|
|
||||||
// create a bitmap we can copy it to, using GetDeviceCaps to get the width/height
|
|
||||||
// the returned (out) IntPtr _ is not used for our purposes. It returns a pointer to the raw bits that make up the bitmap.
|
|
||||||
using (var safeDibSectionHandle = Gdi32Api.CreateDIBSection(desktopDcHandle, ref bmi, DibColors.PalColors, out _, IntPtr.Zero, 0))
|
|
||||||
{
|
|
||||||
if (safeDibSectionHandle.IsInvalid)
|
|
||||||
{
|
{
|
||||||
// Get Exception before the error is lost
|
if (screen.Bounds.IntersectsWith(captureBounds))
|
||||||
var exceptionToThrow = CreateCaptureException("CreateDIBSection", captureBounds);
|
|
||||||
exceptionToThrow.Data.Add("hdcDest", safeCompatibleDcHandle.DangerousGetHandle().ToInt32());
|
|
||||||
exceptionToThrow.Data.Add("hdcSrc", desktopDcHandle.DangerousGetHandle().ToInt32());
|
|
||||||
|
|
||||||
// Throw so people can report the problem
|
|
||||||
throw exceptionToThrow;
|
|
||||||
}
|
|
||||||
// select the bitmap object and store the old handle
|
|
||||||
using (safeCompatibleDcHandle.SelectObject(safeDibSectionHandle))
|
|
||||||
{
|
|
||||||
// bit-blt over (make copy)
|
|
||||||
// ReSharper disable once BitwiseOperatorOnEnumWithoutFlags
|
|
||||||
Gdi32Api.BitBlt(safeCompatibleDcHandle, 0, 0, captureBounds.Width, captureBounds.Height, desktopDcHandle, captureBounds.X, captureBounds.Y,
|
|
||||||
RasterOperations.SourceCopy | RasterOperations.CaptureBlt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get a .NET image object for it
|
|
||||||
// A suggestion for the "A generic error occurred in GDI+." E_FAIL/0x80004005 error is to re-try...
|
|
||||||
ExternalException exception = null;
|
|
||||||
for (var i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
// Collect all screens inside this capture
|
screensInsideCapture.Add(screen);
|
||||||
var screensInsideCapture = new List<Screen>();
|
}
|
||||||
|
}
|
||||||
|
// Check all all screens are of an equal size
|
||||||
|
bool offscreenContent;
|
||||||
|
using (var captureRegion = new Region(captureBounds))
|
||||||
|
{
|
||||||
|
// Exclude every visible part
|
||||||
|
foreach (var screen in screensInsideCapture)
|
||||||
|
{
|
||||||
|
captureRegion.Exclude(screen.Bounds);
|
||||||
|
}
|
||||||
|
// If the region is not empty, we have "offscreenContent"
|
||||||
|
using var screenGraphics = Graphics.FromHwnd(User32Api.GetDesktopWindow());
|
||||||
|
offscreenContent = !captureRegion.IsEmpty(screenGraphics);
|
||||||
|
}
|
||||||
|
// Check if we need to have a transparent background, needed for offscreen content
|
||||||
|
if (offscreenContent)
|
||||||
|
{
|
||||||
|
using var tmpBitmap = Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle());
|
||||||
|
// Create a new bitmap which has a transparent background
|
||||||
|
var returnBitmap = new UnmanagedBitmap<Bgra32>(tmpBitmap.Width, tmpBitmap.Height, tmpBitmap.HorizontalResolution, tmpBitmap.VerticalResolution);
|
||||||
|
returnBitmap.Span.Fill(Color.Transparent.FromColorWithAlpha());
|
||||||
|
// Content will be copied here
|
||||||
|
using (var graphics = Graphics.FromImage(returnBitmap.NativeBitmap))
|
||||||
|
{
|
||||||
|
// For all screens copy the content to the new bitmap
|
||||||
foreach (var screen in Screen.AllScreens)
|
foreach (var screen in Screen.AllScreens)
|
||||||
{
|
{
|
||||||
if (screen.Bounds.IntersectsWith(captureBounds))
|
// Make sure the bounds are with an offset to the capture bounds
|
||||||
{
|
var screenBounds = screen.Bounds;
|
||||||
screensInsideCapture.Add(screen);
|
screenBounds.Offset(-captureBounds.X, -captureBounds.Y);
|
||||||
}
|
graphics.DrawImage(tmpBitmap, screenBounds, screenBounds.X, screenBounds.Y, screenBounds.Width, screenBounds.Height, GraphicsUnit.Pixel);
|
||||||
}
|
}
|
||||||
// Check all all screens are of an equal size
|
}
|
||||||
bool offscreenContent;
|
|
||||||
using (var captureRegion = new Region(captureBounds))
|
|
||||||
{
|
|
||||||
// Exclude every visible part
|
|
||||||
foreach (var screen in screensInsideCapture)
|
|
||||||
{
|
|
||||||
captureRegion.Exclude(screen.Bounds);
|
|
||||||
}
|
|
||||||
// If the region is not empty, we have "offscreenContent"
|
|
||||||
using (var screenGraphics = Graphics.FromHwnd(User32Api.GetDesktopWindow()))
|
|
||||||
{
|
|
||||||
offscreenContent = !captureRegion.IsEmpty(screenGraphics);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check if we need to have a transparent background, needed for offscreen content
|
|
||||||
if (offscreenContent)
|
|
||||||
{
|
|
||||||
using (var tmpBitmap = Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle()))
|
|
||||||
{
|
|
||||||
// Create a new bitmap which has a transparent background
|
|
||||||
var returnBitmap = new UnmanagedBitmap<Bgra32>(tmpBitmap.Width, tmpBitmap.Height, tmpBitmap.HorizontalResolution, tmpBitmap.VerticalResolution);
|
|
||||||
returnBitmap.Span.Fill(Color.Transparent.FromColorWithAlpha());
|
|
||||||
// Content will be copied here
|
|
||||||
using (var graphics = Graphics.FromImage(returnBitmap.NativeBitmap))
|
|
||||||
{
|
|
||||||
// For all screens copy the content to the new bitmap
|
|
||||||
foreach (var screen in Screen.AllScreens)
|
|
||||||
{
|
|
||||||
// Make sure the bounds are with an offset to the capture bounds
|
|
||||||
var screenBounds = screen.Bounds;
|
|
||||||
screenBounds.Offset(-captureBounds.X, -captureBounds.Y);
|
|
||||||
graphics.DrawImage(tmpBitmap, screenBounds, screenBounds.X, screenBounds.Y, screenBounds.Width, screenBounds.Height, GraphicsUnit.Pixel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnBitmap;
|
return returnBitmap;
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// All screens, which are inside the capture, are of equal size
|
|
||||||
// assign image to Capture, the image will be disposed there..
|
|
||||||
// TODO: Optimize?
|
|
||||||
return BitmapWrapper.FromBitmap(Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (ExternalException ee)
|
|
||||||
{
|
|
||||||
Log.Warn().WriteLine(ee, "Problem getting bitmap at try " + i + " : ");
|
|
||||||
exception = ee;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Log.Error().WriteLine(null, "Still couldn't create Bitmap!");
|
else
|
||||||
if (exception != null)
|
|
||||||
{
|
{
|
||||||
throw exception;
|
// All screens, which are inside the capture, are of equal size
|
||||||
|
// assign image to Capture, the image will be disposed there..
|
||||||
|
// TODO: Optimize?
|
||||||
|
return BitmapWrapper.FromBitmap(Image.FromHbitmap(safeDibSectionHandle.DangerousGetHandle()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (ExternalException ee)
|
||||||
|
{
|
||||||
|
Log.Warn().WriteLine(ee, "Problem getting bitmap at try " + i + " : ");
|
||||||
|
exception = ee;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.Error().WriteLine(null, "Still couldn't create Bitmap!");
|
||||||
|
if (exception != null)
|
||||||
|
{
|
||||||
|
throw exception;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -178,14 +178,12 @@ namespace Greenshot.Addons.Extensions
|
||||||
/// <param name="outputSettings">SurfaceOutputSettings specifying how to output the surface</param>
|
/// <param name="outputSettings">SurfaceOutputSettings specifying how to output the surface</param>
|
||||||
public static void SetAsBitmap(this IClipboardAccessToken clipboardAccessToken, ISurface surface, SurfaceOutputSettings outputSettings)
|
public static void SetAsBitmap(this IClipboardAccessToken clipboardAccessToken, ISurface surface, SurfaceOutputSettings outputSettings)
|
||||||
{
|
{
|
||||||
using (var bitmapStream = new MemoryStream())
|
using var bitmapStream = new MemoryStream();
|
||||||
{
|
ImageOutput.SaveToStream(surface, bitmapStream, outputSettings);
|
||||||
ImageOutput.SaveToStream(surface, bitmapStream, outputSettings);
|
bitmapStream.Seek(0, SeekOrigin.Begin);
|
||||||
bitmapStream.Seek(0, SeekOrigin.Begin);
|
// Set the stream
|
||||||
// Set the stream
|
var clipboardFormat = ClipboardFormatExtensions.MapFormatToId(outputSettings.Format.ToString().ToUpperInvariant());
|
||||||
var clipboardFormat = ClipboardFormatExtensions.MapFormatToId(outputSettings.Format.ToString().ToUpperInvariant());
|
clipboardAccessToken.SetAsStream(clipboardFormat, bitmapStream);
|
||||||
clipboardAccessToken.SetAsStream(clipboardFormat, bitmapStream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -196,39 +194,37 @@ namespace Greenshot.Addons.Extensions
|
||||||
public static void SetAsFormat17(this IClipboardAccessToken clipboardAccessToken, ISurface surface, ICoreConfiguration coreConfiguration)
|
public static void SetAsFormat17(this IClipboardAccessToken clipboardAccessToken, ISurface surface, ICoreConfiguration coreConfiguration)
|
||||||
{
|
{
|
||||||
// Create the stream for the clipboard
|
// Create the stream for the clipboard
|
||||||
using (var dibV5Stream = new MemoryStream())
|
using var dibV5Stream = new MemoryStream();
|
||||||
|
var outputSettings = new SurfaceOutputSettings(coreConfiguration, OutputFormats.bmp, 100, false);
|
||||||
|
bool dispose = ImageOutput.CreateBitmapFromSurface(surface, outputSettings, out var bitmapToSave);
|
||||||
|
// Create the BITMAPINFOHEADER
|
||||||
|
var header = BitmapInfoHeader.Create(bitmapToSave.Width, bitmapToSave.Height, 32);
|
||||||
|
// Make sure we have BI_BITFIELDS, this seems to be normal for Format17?
|
||||||
|
header.Compression = BitmapCompressionMethods.BI_BITFIELDS;
|
||||||
|
|
||||||
|
var headerBytes = BinaryStructHelper.ToByteArray(header);
|
||||||
|
// Write the BITMAPINFOHEADER to the stream
|
||||||
|
dibV5Stream.Write(headerBytes, 0, headerBytes.Length);
|
||||||
|
|
||||||
|
// As we have specified BI_COMPRESSION.BI_BITFIELDS, the BitfieldColorMask needs to be added
|
||||||
|
var colorMask = BitfieldColorMask.Create();
|
||||||
|
// Create the byte[] from the struct
|
||||||
|
var colorMaskBytes = BinaryStructHelper.ToByteArray(colorMask);
|
||||||
|
Array.Reverse(colorMaskBytes);
|
||||||
|
// Write to the stream
|
||||||
|
dibV5Stream.Write(colorMaskBytes, 0, colorMaskBytes.Length);
|
||||||
|
|
||||||
|
// Create the raw bytes for the pixels only
|
||||||
|
var bitmapBytes = BitmapToByteArray(bitmapToSave);
|
||||||
|
// Write to the stream
|
||||||
|
dibV5Stream.Write(bitmapBytes, 0, bitmapBytes.Length);
|
||||||
|
// Reset the stream to the beginning so it can be written
|
||||||
|
dibV5Stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
// Set the DIBv5 to the clipboard DataObject
|
||||||
|
clipboardAccessToken.SetAsStream("Format17", dibV5Stream);
|
||||||
|
if (dispose)
|
||||||
{
|
{
|
||||||
var outputSettings = new SurfaceOutputSettings(coreConfiguration, OutputFormats.bmp, 100, false);
|
bitmapToSave.Dispose();
|
||||||
bool dispose = ImageOutput.CreateBitmapFromSurface(surface, outputSettings, out var bitmapToSave);
|
|
||||||
// Create the BITMAPINFOHEADER
|
|
||||||
var header = BitmapInfoHeader.Create(bitmapToSave.Width, bitmapToSave.Height, 32);
|
|
||||||
// Make sure we have BI_BITFIELDS, this seems to be normal for Format17?
|
|
||||||
header.Compression = BitmapCompressionMethods.BI_BITFIELDS;
|
|
||||||
|
|
||||||
var headerBytes = BinaryStructHelper.ToByteArray(header);
|
|
||||||
// Write the BITMAPINFOHEADER to the stream
|
|
||||||
dibV5Stream.Write(headerBytes, 0, headerBytes.Length);
|
|
||||||
|
|
||||||
// As we have specified BI_COMPRESSION.BI_BITFIELDS, the BitfieldColorMask needs to be added
|
|
||||||
var colorMask = BitfieldColorMask.Create();
|
|
||||||
// Create the byte[] from the struct
|
|
||||||
var colorMaskBytes = BinaryStructHelper.ToByteArray(colorMask);
|
|
||||||
Array.Reverse(colorMaskBytes);
|
|
||||||
// Write to the stream
|
|
||||||
dibV5Stream.Write(colorMaskBytes, 0, colorMaskBytes.Length);
|
|
||||||
|
|
||||||
// Create the raw bytes for the pixels only
|
|
||||||
var bitmapBytes = BitmapToByteArray(bitmapToSave);
|
|
||||||
// Write to the stream
|
|
||||||
dibV5Stream.Write(bitmapBytes, 0, bitmapBytes.Length);
|
|
||||||
// Reset the stream to the beginning so it can be written
|
|
||||||
dibV5Stream.Seek(0, SeekOrigin.Begin);
|
|
||||||
// Set the DIBv5 to the clipboard DataObject
|
|
||||||
clipboardAccessToken.SetAsStream("Format17", dibV5Stream);
|
|
||||||
if (dispose)
|
|
||||||
{
|
|
||||||
bitmapToSave.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,13 +265,11 @@ namespace Greenshot.Addons.Extensions
|
||||||
/// <param name="surface">ISurface</param>
|
/// <param name="surface">ISurface</param>
|
||||||
public static void SetAsDeviceIndependendBitmap(this IClipboardAccessToken clipboardAccessToken, ISurface surface, ICoreConfiguration coreConfiguration)
|
public static void SetAsDeviceIndependendBitmap(this IClipboardAccessToken clipboardAccessToken, ISurface surface, ICoreConfiguration coreConfiguration)
|
||||||
{
|
{
|
||||||
using (var bitmapStream = new MemoryStream())
|
using var bitmapStream = new MemoryStream();
|
||||||
{
|
ImageOutput.SaveToStream(surface, bitmapStream, new SurfaceOutputSettings(coreConfiguration) {Format = OutputFormats.bmp});
|
||||||
ImageOutput.SaveToStream(surface, bitmapStream, new SurfaceOutputSettings(coreConfiguration) {Format = OutputFormats.bmp});
|
bitmapStream.Seek(Marshal.SizeOf(typeof(BitmapFileHeader)), SeekOrigin.Begin);
|
||||||
bitmapStream.Seek(Marshal.SizeOf(typeof(BitmapFileHeader)), SeekOrigin.Begin);
|
// Set the stream
|
||||||
// Set the stream
|
clipboardAccessToken.SetAsStream(StandardClipboardFormats.DeviceIndependentBitmap, bitmapStream);
|
||||||
clipboardAccessToken.SetAsStream(StandardClipboardFormats.DeviceIndependentBitmap, bitmapStream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,15 +155,13 @@ EndSelection:<<<<<<<4
|
||||||
/// <param name="coreConfiguration">ICoreConfiguration</param>
|
/// <param name="coreConfiguration">ICoreConfiguration</param>
|
||||||
public static void SetAsEmbeddedHtml(this IClipboardAccessToken clipboardAccessToken, ISurface surface, ICoreConfiguration coreConfiguration)
|
public static void SetAsEmbeddedHtml(this IClipboardAccessToken clipboardAccessToken, ISurface surface, ICoreConfiguration coreConfiguration)
|
||||||
{
|
{
|
||||||
using (var pngStream = new MemoryStream())
|
using var pngStream = new MemoryStream();
|
||||||
{
|
var pngOutputSettings = new SurfaceOutputSettings(coreConfiguration, OutputFormats.png, 100, false);
|
||||||
var pngOutputSettings = new SurfaceOutputSettings(coreConfiguration, OutputFormats.png, 100, false);
|
ImageOutput.SaveToStream(surface, pngStream, pngOutputSettings);
|
||||||
ImageOutput.SaveToStream(surface, pngStream, pngOutputSettings);
|
pngStream.Seek(0, SeekOrigin.Begin);
|
||||||
pngStream.Seek(0, SeekOrigin.Begin);
|
// Set the PNG stream
|
||||||
// Set the PNG stream
|
var htmlText = GenerateHtmlDataUrlString(new NativeSize(surface.Width, surface.Height), pngStream);
|
||||||
var htmlText = GenerateHtmlDataUrlString(new NativeSize(surface.Width, surface.Height), pngStream);
|
clipboardAccessToken.SetAsHtml(htmlText);
|
||||||
clipboardAccessToken.SetAsHtml(htmlText);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -16,10 +16,10 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Dapplo.CaliburnMicro.Configuration" Version="2.1.3" />
|
<PackageReference Include="Dapplo.CaliburnMicro.Configuration" Version="2.1.4" />
|
||||||
<PackageReference Include="Dapplo.CaliburnMicro.Metro" Version="2.1.3" />
|
<PackageReference Include="Dapplo.CaliburnMicro.Metro" Version="2.1.4" />
|
||||||
<PackageReference Include="Dapplo.CaliburnMicro.Toasts" Version="2.1.3" />
|
<PackageReference Include="Dapplo.CaliburnMicro.Toasts" Version="2.1.4" />
|
||||||
<PackageReference Include="Dapplo.CaliburnMicro.Translations" Version="2.1.3" />
|
<PackageReference Include="Dapplo.CaliburnMicro.Translations" Version="2.1.4" />
|
||||||
<PackageReference Include="Dapplo.HttpExtensions" Version="0.10.7" />
|
<PackageReference Include="Dapplo.HttpExtensions" Version="0.10.7" />
|
||||||
<PackageReference Include="Dapplo.HttpExtensions.JsonNet" Version="0.10.7" />
|
<PackageReference Include="Dapplo.HttpExtensions.JsonNet" Version="0.10.7" />
|
||||||
<PackageReference Include="Dapplo.HttpExtensions.OAuth" Version="0.10.7" />
|
<PackageReference Include="Dapplo.HttpExtensions.OAuth" Version="0.10.7" />
|
||||||
|
@ -27,9 +27,9 @@
|
||||||
<PackageReference Include="Dapplo.Windows.Clipboard" Version="0.11.6" />
|
<PackageReference Include="Dapplo.Windows.Clipboard" Version="0.11.6" />
|
||||||
<PackageReference Include="Dapplo.Windows.Dpi" Version="0.11.6" />
|
<PackageReference Include="Dapplo.Windows.Dpi" Version="0.11.6" />
|
||||||
<PackageReference Include="Dapplo.Windows.Icons" Version="0.11.6" />
|
<PackageReference Include="Dapplo.Windows.Icons" Version="0.11.6" />
|
||||||
<PackageReference Include="gong-wpf-dragdrop" Version="2.1.0" />
|
<PackageReference Include="gong-wpf-dragdrop" Version="2.2.0" />
|
||||||
<PackageReference Include="MahApps.Metro.IconPacks" Version="3.0.0-alpha0223" />
|
<PackageReference Include="MahApps.Metro.IconPacks" Version="3.0.0" />
|
||||||
<PackageReference Include="Svg" Version="3.0.49" />
|
<PackageReference Include="Svg" Version="3.0.84" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -47,11 +47,9 @@ namespace Greenshot.Addons.Resources
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>BitmapSource</returns>
|
/// <returns>BitmapSource</returns>
|
||||||
public BitmapSource GreenshotIconAsBitmapSource()
|
public BitmapSource GreenshotIconAsBitmapSource()
|
||||||
{
|
{
|
||||||
using (var icon = GetGreenshotIcon())
|
using var icon = GetGreenshotIcon();
|
||||||
{
|
return icon.ToBitmapSource();
|
||||||
return icon.ToBitmapSource();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -70,12 +68,10 @@ namespace Greenshot.Addons.Resources
|
||||||
/// <param name="type">Type</param>
|
/// <param name="type">Type</param>
|
||||||
/// <returns>Icon</returns>
|
/// <returns>Icon</returns>
|
||||||
public Icon GetIcon(string name, Type type = null)
|
public Icon GetIcon(string name, Type type = null)
|
||||||
{
|
{
|
||||||
using (var iconStream = _resourceProvider.ResourceAsStream((type ?? GetType()).Assembly, "Resources", $"{name}.Icon.ico"))
|
using var iconStream = _resourceProvider.ResourceAsStream((type ?? GetType()).Assembly, "Resources", $"{name}.Icon.ico");
|
||||||
{
|
return new Icon(iconStream);
|
||||||
return new Icon(iconStream);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the Greenshot logo as a Bitmap
|
/// Get the Greenshot logo as a Bitmap
|
||||||
|
@ -99,11 +95,10 @@ namespace Greenshot.Addons.Resources
|
||||||
name += ".png";
|
name += ".png";
|
||||||
|
|
||||||
}
|
}
|
||||||
using (var imageStream = _resourceProvider.ResourceAsStream((type ?? GetType()).Assembly, "Resources", name))
|
|
||||||
{
|
using var imageStream = _resourceProvider.ResourceAsStream((type ?? GetType()).Assembly, "Resources", name);
|
||||||
return BitmapHelper.FromStream(imageStream);
|
return BitmapHelper.FromStream(imageStream);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a byte[] from an embedded resource
|
/// Get a byte[] from an embedded resource
|
||||||
|
@ -113,12 +108,10 @@ namespace Greenshot.Addons.Resources
|
||||||
/// <returns>bate[]</returns>
|
/// <returns>bate[]</returns>
|
||||||
public byte[] GetBytes(string name, Type type = null)
|
public byte[] GetBytes(string name, Type type = null)
|
||||||
{
|
{
|
||||||
using (var stream = _resourceProvider.ResourceAsStream((type ?? GetType()).Assembly, "Resources", name))
|
using var stream = _resourceProvider.ResourceAsStream((type ?? GetType()).Assembly, "Resources", name);
|
||||||
using (var memoryStream = new MemoryStream())
|
using var memoryStream = new MemoryStream();
|
||||||
{
|
stream.CopyTo(memoryStream);
|
||||||
stream.CopyTo(memoryStream);
|
return memoryStream.ToArray();
|
||||||
return memoryStream.ToArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -63,10 +63,8 @@ namespace Greenshot.Addons.ViewModels
|
||||||
Information = exportInformation;
|
Information = exportInformation;
|
||||||
Source = source;
|
Source = source;
|
||||||
|
|
||||||
using (var bitmap = exportedSurface.GetBitmapForExport())
|
using var bitmap = exportedSurface.GetBitmapForExport();
|
||||||
{
|
ExportBitmapSource = bitmap.NativeBitmap.ToBitmapSource();
|
||||||
ExportBitmapSource = bitmap.NativeBitmap.ToBitmapSource();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -112,17 +112,17 @@ namespace Greenshot.Addons.ViewModels
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SelectOutputPath()
|
public void SelectOutputPath()
|
||||||
{
|
{
|
||||||
using (var folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog())
|
using var folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog
|
||||||
{
|
{
|
||||||
// Get the storage location and replace the environment variables
|
SelectedPath = FilenameHelper.FillVariables(CoreConfiguration.OutputFilePath, false)
|
||||||
folderBrowserDialog.SelectedPath = FilenameHelper.FillVariables(CoreConfiguration.OutputFilePath, false);
|
};
|
||||||
if (folderBrowserDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
|
// Get the storage location and replace the environment variables
|
||||||
|
if (folderBrowserDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
|
||||||
|
{
|
||||||
|
// Only change if there is a change, otherwise we might overwrite the environment variables
|
||||||
|
if (folderBrowserDialog.SelectedPath != null && !folderBrowserDialog.SelectedPath.Equals(FilenameHelper.FillVariables(CoreConfiguration.OutputFilePath, false)))
|
||||||
{
|
{
|
||||||
// Only change if there is a change, otherwise we might overwrite the environment variables
|
CoreConfiguration.OutputFilePath = folderBrowserDialog.SelectedPath;
|
||||||
if (folderBrowserDialog.SelectedPath != null && !folderBrowserDialog.SelectedPath.Equals(FilenameHelper.FillVariables(CoreConfiguration.OutputFilePath, false)))
|
|
||||||
{
|
|
||||||
CoreConfiguration.OutputFilePath = folderBrowserDialog.SelectedPath;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,36 +166,34 @@ namespace Greenshot.Core.Extensions
|
||||||
{
|
{
|
||||||
// Assume using it's own location
|
// Assume using it's own location
|
||||||
formLocation = windowRectangle.Location;
|
formLocation = windowRectangle.Location;
|
||||||
using (var workingArea = new Region())
|
using var workingArea = new Region();
|
||||||
|
// Find the screen where the window is and check if it fits
|
||||||
|
foreach (var displayInfo in DisplayInfo.AllDisplayInfos)
|
||||||
{
|
{
|
||||||
// Find the screen where the window is and check if it fits
|
workingArea.Union(displayInfo.WorkingArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the formLocation is not inside the visible area
|
||||||
|
if (!workingArea.AreRectangleCornersVisisble(windowRectangle))
|
||||||
|
{
|
||||||
|
// If none found we find the biggest screen
|
||||||
foreach (var displayInfo in DisplayInfo.AllDisplayInfos)
|
foreach (var displayInfo in DisplayInfo.AllDisplayInfos)
|
||||||
{
|
{
|
||||||
workingArea.Union(displayInfo.WorkingArea);
|
var newWindowRectangle = new NativeRect(displayInfo.WorkingArea.Location, windowRectangle.Size);
|
||||||
}
|
if (!workingArea.AreRectangleCornersVisisble(newWindowRectangle))
|
||||||
|
|
||||||
// If the formLocation is not inside the visible area
|
|
||||||
if (!workingArea.AreRectangleCornersVisisble(windowRectangle))
|
|
||||||
{
|
|
||||||
// If none found we find the biggest screen
|
|
||||||
foreach (var displayInfo in DisplayInfo.AllDisplayInfos)
|
|
||||||
{
|
{
|
||||||
var newWindowRectangle = new NativeRect(displayInfo.WorkingArea.Location, windowRectangle.Size);
|
continue;
|
||||||
if (!workingArea.AreRectangleCornersVisisble(newWindowRectangle))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
formLocation = displayInfo.Bounds.Location;
|
|
||||||
doesCaptureFit = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
formLocation = displayInfo.Bounds.Location;
|
||||||
{
|
|
||||||
doesCaptureFit = true;
|
doesCaptureFit = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
doesCaptureFit = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!WindowsVersion.IsWindows8OrLater)
|
else if (!WindowsVersion.IsWindows8OrLater)
|
||||||
{
|
{
|
||||||
|
@ -229,13 +227,11 @@ namespace Greenshot.Core.Extensions
|
||||||
if (!doesCaptureFit)
|
if (!doesCaptureFit)
|
||||||
{
|
{
|
||||||
// if GDI is allowed.. (a screenshot won't be better than we comes if we continue)
|
// if GDI is allowed.. (a screenshot won't be better than we comes if we continue)
|
||||||
using (var thisWindowProcess = Process.GetProcessById(interopWindow.GetProcessId()))
|
using var thisWindowProcess = Process.GetProcessById(interopWindow.GetProcessId());
|
||||||
|
if (!interopWindow.IsApp() && IsGdiAllowed(thisWindowProcess, captureConfiguration))
|
||||||
{
|
{
|
||||||
if (!interopWindow.IsApp() && IsGdiAllowed(thisWindowProcess, captureConfiguration))
|
// we return null which causes the capturing code to try another method.
|
||||||
{
|
return null;
|
||||||
// we return null which causes the capturing code to try another method.
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,85 +95,79 @@ namespace Greenshot.Core.Sources
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a device context we can copy to
|
// create a device context we can copy to
|
||||||
using (var safeCompatibleDcHandle = Gdi32Api.CreateCompatibleDC(desktopDcHandle))
|
using var safeCompatibleDcHandle = Gdi32Api.CreateCompatibleDC(desktopDcHandle);
|
||||||
|
// Check if the device context is there, if not throw an error with as much info as possible!
|
||||||
|
if (safeCompatibleDcHandle.IsInvalid)
|
||||||
{
|
{
|
||||||
// Check if the device context is there, if not throw an error with as much info as possible!
|
// Get Exception before the error is lost
|
||||||
if (safeCompatibleDcHandle.IsInvalid)
|
var exceptionToThrow = CreateCaptureException("CreateCompatibleDC", captureBounds);
|
||||||
|
// throw exception
|
||||||
|
throw exceptionToThrow;
|
||||||
|
}
|
||||||
|
// Create BITMAPINFOHEADER for CreateDIBSection
|
||||||
|
var bmi = BitmapInfoHeader.Create(captureBounds.Width, captureBounds.Height, 24);
|
||||||
|
|
||||||
|
// Make sure the last error is set to 0
|
||||||
|
Win32.SetLastError(0);
|
||||||
|
|
||||||
|
// create a bitmap we can copy it to, using GetDeviceCaps to get the width/height
|
||||||
|
using var safeDibSectionHandle = Gdi32Api.CreateDIBSection(desktopDcHandle, ref bmi, 0, out var _, IntPtr.Zero, 0);
|
||||||
|
if (safeDibSectionHandle.IsInvalid)
|
||||||
|
{
|
||||||
|
// Get Exception before the error is lost
|
||||||
|
var exceptionToThrow = CreateCaptureException("CreateDIBSection", captureBounds);
|
||||||
|
exceptionToThrow.Data.Add("hdcDest", safeCompatibleDcHandle.DangerousGetHandle().ToInt32());
|
||||||
|
exceptionToThrow.Data.Add("hdcSrc", desktopDcHandle.DangerousGetHandle().ToInt32());
|
||||||
|
|
||||||
|
// Throw so people can report the problem
|
||||||
|
throw exceptionToThrow;
|
||||||
|
}
|
||||||
|
// select the bitmap object and store the old handle
|
||||||
|
using (safeCompatibleDcHandle.SelectObject(safeDibSectionHandle))
|
||||||
|
{
|
||||||
|
// bitblt over (make copy)
|
||||||
|
// ReSharper disable once BitwiseOperatorOnEnumWithoutFlags
|
||||||
|
Gdi32Api.BitBlt(safeCompatibleDcHandle, 0, 0, captureBounds.Width, captureBounds.Height, desktopDcHandle, captureBounds.X, captureBounds.Y,
|
||||||
|
RasterOperations.SourceCopy | RasterOperations.CaptureBlt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create BitmapSource from the DibSection
|
||||||
|
capturedBitmapSource = Imaging.CreateBitmapSourceFromHBitmap(safeDibSectionHandle.DangerousGetHandle(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
|
||||||
|
|
||||||
|
// Now cut away invisible parts
|
||||||
|
|
||||||
|
// Collect all screens inside this capture
|
||||||
|
var displaysInsideCapture = new List<DisplayInfo>();
|
||||||
|
foreach (var displayInfo in DisplayInfo.AllDisplayInfos)
|
||||||
|
{
|
||||||
|
if (displayInfo.Bounds.IntersectsWith(captureBounds))
|
||||||
{
|
{
|
||||||
// Get Exception before the error is lost
|
displaysInsideCapture.Add(displayInfo);
|
||||||
var exceptionToThrow = CreateCaptureException("CreateCompatibleDC", captureBounds);
|
|
||||||
// throw exception
|
|
||||||
throw exceptionToThrow;
|
|
||||||
}
|
}
|
||||||
// Create BITMAPINFOHEADER for CreateDIBSection
|
}
|
||||||
var bmi = BitmapInfoHeader.Create(captureBounds.Width, captureBounds.Height, 24);
|
// Check all all screens are of an equal size
|
||||||
|
bool offscreenContent;
|
||||||
// Make sure the last error is set to 0
|
using (var captureRegion = new Region(captureBounds))
|
||||||
Win32.SetLastError(0);
|
{
|
||||||
|
// Exclude every visible part
|
||||||
// create a bitmap we can copy it to, using GetDeviceCaps to get the width/height
|
foreach (var displayInfo in displaysInsideCapture)
|
||||||
using (var safeDibSectionHandle = Gdi32Api.CreateDIBSection(desktopDcHandle, ref bmi, 0, out var _, IntPtr.Zero, 0))
|
|
||||||
{
|
{
|
||||||
if (safeDibSectionHandle.IsInvalid)
|
captureRegion.Exclude(displayInfo.Bounds);
|
||||||
{
|
|
||||||
// Get Exception before the error is lost
|
|
||||||
var exceptionToThrow = CreateCaptureException("CreateDIBSection", captureBounds);
|
|
||||||
exceptionToThrow.Data.Add("hdcDest", safeCompatibleDcHandle.DangerousGetHandle().ToInt32());
|
|
||||||
exceptionToThrow.Data.Add("hdcSrc", desktopDcHandle.DangerousGetHandle().ToInt32());
|
|
||||||
|
|
||||||
// Throw so people can report the problem
|
|
||||||
throw exceptionToThrow;
|
|
||||||
}
|
|
||||||
// select the bitmap object and store the old handle
|
|
||||||
using (safeCompatibleDcHandle.SelectObject(safeDibSectionHandle))
|
|
||||||
{
|
|
||||||
// bitblt over (make copy)
|
|
||||||
// ReSharper disable once BitwiseOperatorOnEnumWithoutFlags
|
|
||||||
Gdi32Api.BitBlt(safeCompatibleDcHandle, 0, 0, captureBounds.Width, captureBounds.Height, desktopDcHandle, captureBounds.X, captureBounds.Y,
|
|
||||||
RasterOperations.SourceCopy | RasterOperations.CaptureBlt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create BitmapSource from the DibSection
|
|
||||||
capturedBitmapSource = Imaging.CreateBitmapSourceFromHBitmap(safeDibSectionHandle.DangerousGetHandle(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
|
|
||||||
|
|
||||||
// Now cut away invisible parts
|
|
||||||
|
|
||||||
// Collect all screens inside this capture
|
|
||||||
var displaysInsideCapture = new List<DisplayInfo>();
|
|
||||||
foreach (var displayInfo in DisplayInfo.AllDisplayInfos)
|
|
||||||
{
|
|
||||||
if (displayInfo.Bounds.IntersectsWith(captureBounds))
|
|
||||||
{
|
|
||||||
displaysInsideCapture.Add(displayInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check all all screens are of an equal size
|
|
||||||
bool offscreenContent;
|
|
||||||
using (var captureRegion = new Region(captureBounds))
|
|
||||||
{
|
|
||||||
// Exclude every visible part
|
|
||||||
foreach (var displayInfo in displaysInsideCapture)
|
|
||||||
{
|
|
||||||
captureRegion.Exclude(displayInfo.Bounds);
|
|
||||||
}
|
|
||||||
// If the region is not empty, we have "offscreenContent"
|
|
||||||
using (var screenGraphics = Graphics.FromHwnd(User32Api.GetDesktopWindow()))
|
|
||||||
{
|
|
||||||
offscreenContent = !captureRegion.IsEmpty(screenGraphics);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check if we need to have a transparent background, needed for offscreen content
|
|
||||||
if (offscreenContent)
|
|
||||||
{
|
|
||||||
var modifiedImage = new WriteableBitmap(capturedBitmapSource.PixelWidth, capturedBitmapSource.PixelHeight, capturedBitmapSource.DpiX, capturedBitmapSource.DpiY, PixelFormats.Bgr32, capturedBitmapSource.Palette);
|
|
||||||
foreach (var displayInfo in DisplayInfo.AllDisplayInfos)
|
|
||||||
{
|
|
||||||
modifiedImage.CopyPixels(capturedBitmapSource, displayInfo.Bounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
capturedBitmapSource = modifiedImage;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// If the region is not empty, we have "offscreenContent"
|
||||||
|
using var screenGraphics = Graphics.FromHwnd(User32Api.GetDesktopWindow());
|
||||||
|
offscreenContent = !captureRegion.IsEmpty(screenGraphics);
|
||||||
|
}
|
||||||
|
// Check if we need to have a transparent background, needed for offscreen content
|
||||||
|
if (offscreenContent)
|
||||||
|
{
|
||||||
|
var modifiedImage = new WriteableBitmap(capturedBitmapSource.PixelWidth, capturedBitmapSource.PixelHeight, capturedBitmapSource.DpiX, capturedBitmapSource.DpiY, PixelFormats.Bgr32, capturedBitmapSource.Palette);
|
||||||
|
foreach (var displayInfo in DisplayInfo.AllDisplayInfos)
|
||||||
|
{
|
||||||
|
modifiedImage.CopyPixels(capturedBitmapSource, displayInfo.Bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
capturedBitmapSource = modifiedImage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var result = new CaptureElement<BitmapSource>(captureBounds.Location, capturedBitmapSource)
|
var result = new CaptureElement<BitmapSource>(captureBounds.Location, capturedBitmapSource)
|
||||||
|
|
|
@ -171,22 +171,20 @@ namespace Greenshot.Gfx
|
||||||
// Make sure both images have the same resolution
|
// Make sure both images have the same resolution
|
||||||
newImage.SetResolution(sourceBitmap.HorizontalResolution, sourceBitmap.VerticalResolution);
|
newImage.SetResolution(sourceBitmap.HorizontalResolution, sourceBitmap.VerticalResolution);
|
||||||
|
|
||||||
using (var graphics = Graphics.FromImage(newImage))
|
using var graphics = Graphics.FromImage(newImage);
|
||||||
|
if (fromTransparentToNon)
|
||||||
{
|
{
|
||||||
if (fromTransparentToNon)
|
// Rule 2: Make sure the background color is white
|
||||||
{
|
graphics.Clear(Color.White);
|
||||||
// Rule 2: Make sure the background color is white
|
}
|
||||||
graphics.Clear(Color.White);
|
// decide fastest copy method
|
||||||
}
|
if (isAreaEqual)
|
||||||
// decide fastest copy method
|
{
|
||||||
if (isAreaEqual)
|
graphics.DrawImageUnscaled(sourceBitmap.NativeBitmap, 0, 0);
|
||||||
{
|
}
|
||||||
graphics.DrawImageUnscaled(sourceBitmap.NativeBitmap, 0, 0);
|
else
|
||||||
}
|
{
|
||||||
else
|
graphics.DrawImage(sourceBitmap.NativeBitmap, 0, 0, sourceRect, GraphicsUnit.Pixel);
|
||||||
{
|
|
||||||
graphics.DrawImage(sourceBitmap.NativeBitmap, 0, 0, sourceRect, GraphicsUnit.Pixel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -462,13 +462,11 @@ namespace Greenshot.Gfx
|
||||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||||
// draw original with a TextureBrush so we have nice anti-aliasing!
|
// draw original with a TextureBrush so we have nice anti-aliasing!
|
||||||
using (Brush textureBrush = new TextureBrush(sourceBitmap.NativeBitmap, WrapMode.Clamp))
|
using Brush textureBrush = new TextureBrush(sourceBitmap.NativeBitmap, WrapMode.Clamp);
|
||||||
{
|
// We need to do a translate-transform otherwise the image is wrapped
|
||||||
// We need to do a translate-transform otherwise the image is wrapped
|
graphics.TranslateTransform(offset.X, offset.Y);
|
||||||
graphics.TranslateTransform(offset.X, offset.Y);
|
graphics.FillRectangle(textureBrush, 0, 0, sourceBitmap.Width, sourceBitmap.Height);
|
||||||
graphics.FillRectangle(textureBrush, 0, 0, sourceBitmap.Width, sourceBitmap.Height);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnImage;
|
return returnImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,14 +489,12 @@ namespace Greenshot.Gfx
|
||||||
/// <param name="dest">Image to copy to</param>
|
/// <param name="dest">Image to copy to</param>
|
||||||
/// <param name="colorMatrix">ColorMatrix to apply</param>
|
/// <param name="colorMatrix">ColorMatrix to apply</param>
|
||||||
public static void ApplyColorMatrix(this IBitmapWithNativeSupport source, NativeRect sourceRect, IBitmapWithNativeSupport dest, NativeRect destRect, ColorMatrix colorMatrix)
|
public static void ApplyColorMatrix(this IBitmapWithNativeSupport source, NativeRect sourceRect, IBitmapWithNativeSupport dest, NativeRect destRect, ColorMatrix colorMatrix)
|
||||||
{
|
{
|
||||||
using (var imageAttributes = new ImageAttributes())
|
using var imageAttributes = new ImageAttributes();
|
||||||
{
|
imageAttributes.ClearColorMatrix();
|
||||||
imageAttributes.ClearColorMatrix();
|
imageAttributes.SetColorMatrix(colorMatrix);
|
||||||
imageAttributes.SetColorMatrix(colorMatrix);
|
source.ApplyImageAttributes(sourceRect, dest, destRect, imageAttributes);
|
||||||
source.ApplyImageAttributes(sourceRect, dest, destRect, imageAttributes);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Apply image attributes to the image
|
/// Apply image attributes to the image
|
||||||
|
@ -532,18 +528,17 @@ namespace Greenshot.Gfx
|
||||||
{
|
{
|
||||||
destRect = new NativeRect(0, 0, dest.Width, dest.Height);
|
destRect = new NativeRect(0, 0, dest.Width, dest.Height);
|
||||||
}
|
}
|
||||||
using (var graphics = Graphics.FromImage(dest.NativeBitmap))
|
|
||||||
{
|
|
||||||
// Make sure we draw with the best quality!
|
|
||||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
|
||||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
|
||||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
|
||||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
|
||||||
graphics.CompositingMode = CompositingMode.SourceCopy;
|
|
||||||
|
|
||||||
graphics.DrawImage(source.NativeBitmap, destRect, sourceRect.X, sourceRect.Y, sourceRect.Width, sourceRect.Height, GraphicsUnit.Pixel, imageAttributes);
|
using var graphics = Graphics.FromImage(dest.NativeBitmap);
|
||||||
}
|
// Make sure we draw with the best quality!
|
||||||
}
|
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||||
|
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||||
|
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||||
|
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||||
|
graphics.CompositingMode = CompositingMode.SourceCopy;
|
||||||
|
|
||||||
|
graphics.DrawImage(source.NativeBitmap, destRect, sourceRect.X, sourceRect.Y, sourceRect.Width, sourceRect.Height, GraphicsUnit.Pixel, imageAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if the supplied Bitmap has a PixelFormat we support
|
/// Checks if the supplied Bitmap has a PixelFormat we support
|
||||||
|
@ -712,12 +707,10 @@ namespace Greenshot.Gfx
|
||||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||||
graphics.InterpolationMode = interpolationMode;
|
graphics.InterpolationMode = interpolationMode;
|
||||||
using (var wrapMode = new ImageAttributes())
|
using var wrapMode = new ImageAttributes();
|
||||||
{
|
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
|
||||||
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
|
graphics.DrawImage(sourceImage.NativeBitmap, new NativeRect(destX, destY, destWidth, destHeight), 0, 0, sourceImage.Width, sourceImage.Height, GraphicsUnit.Pixel, wrapMode);
|
||||||
graphics.DrawImage(sourceImage.NativeBitmap, new NativeRect(destX, destY, destWidth, destHeight), 0, 0, sourceImage.Width, sourceImage.Height, GraphicsUnit.Pixel, wrapMode);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return newBitmap;
|
return newBitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,35 +730,34 @@ namespace Greenshot.Gfx
|
||||||
{
|
{
|
||||||
toCount = toCount & 0xffffff;
|
toCount = toCount & 0xffffff;
|
||||||
}
|
}
|
||||||
using (var bb = FastBitmapFactory.Create(sourceImage))
|
|
||||||
{
|
|
||||||
Parallel.For(0, bb.Height, () => 0, (y, state, initialColorCount) =>
|
|
||||||
{
|
|
||||||
var currentColors = initialColorCount;
|
|
||||||
for (var x = 0; x < bb.Width; x++)
|
|
||||||
{
|
|
||||||
var bitmapcolor = bb.GetColorAt(x, y).ToArgb();
|
|
||||||
if (!includeAlpha)
|
|
||||||
{
|
|
||||||
bitmapcolor = bitmapcolor & 0xffffff;
|
|
||||||
}
|
|
||||||
if (bitmapcolor == toCount)
|
|
||||||
{
|
|
||||||
currentColors++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return currentColors;
|
|
||||||
}, lineColorCount =>
|
|
||||||
{
|
|
||||||
lock (lockObject)
|
|
||||||
{
|
|
||||||
colors += lineColorCount;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return colors;
|
using var bb = FastBitmapFactory.Create(sourceImage);
|
||||||
}
|
Parallel.For(0, bb.Height, () => 0, (y, state, initialColorCount) =>
|
||||||
}
|
{
|
||||||
|
var currentColors = initialColorCount;
|
||||||
|
for (var x = 0; x < bb.Width; x++)
|
||||||
|
{
|
||||||
|
var bitmapcolor = bb.GetColorAt(x, y).ToArgb();
|
||||||
|
if (!includeAlpha)
|
||||||
|
{
|
||||||
|
bitmapcolor = bitmapcolor & 0xffffff;
|
||||||
|
}
|
||||||
|
if (bitmapcolor == toCount)
|
||||||
|
{
|
||||||
|
currentColors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return currentColors;
|
||||||
|
}, lineColorCount =>
|
||||||
|
{
|
||||||
|
lock (lockObject)
|
||||||
|
{
|
||||||
|
colors += lineColorCount;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create an image from a stream, if an extension is supplied more formats are supported.
|
/// Create an image from a stream, if an extension is supplied more formats are supported.
|
||||||
|
@ -833,12 +825,10 @@ namespace Greenshot.Gfx
|
||||||
return original.Scale3X();
|
return original.Scale3X();
|
||||||
}
|
}
|
||||||
if (width == original.Width * 4)
|
if (width == original.Width * 4)
|
||||||
{
|
{
|
||||||
using (var scale2X = original.Scale2X())
|
using var scale2X = original.Scale2X();
|
||||||
{
|
return scale2X.Scale2X();
|
||||||
return scale2X.Scale2X();
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return original.Resize(true, width, width, interpolationMode: InterpolationMode.NearestNeighbor);
|
return original.Resize(true, width, width, interpolationMode: InterpolationMode.NearestNeighbor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,30 +855,31 @@ namespace Greenshot.Gfx
|
||||||
}
|
}
|
||||||
bool result = true;
|
bool result = true;
|
||||||
using (var fastBitmap1 = FastBitmapFactory.Create(bitmap1))
|
using (var fastBitmap1 = FastBitmapFactory.Create(bitmap1))
|
||||||
using (var fastBitmap2 = FastBitmapFactory.Create(bitmap2))
|
{
|
||||||
{
|
using var fastBitmap2 = FastBitmapFactory.Create(bitmap2);
|
||||||
Parallel.For(0, fastBitmap1.Height, (y, state) =>
|
Parallel.For(0, fastBitmap1.Height, (y, state) =>
|
||||||
{
|
{
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
var tmpColor1 = stackalloc byte[4];
|
var tmpColor1 = stackalloc byte[4];
|
||||||
var tmpColor2 = stackalloc byte[4];
|
var tmpColor2 = stackalloc byte[4];
|
||||||
for (int x = 0; x < fastBitmap1.Width; x++)
|
for (int x = 0; x < fastBitmap1.Width; x++)
|
||||||
{
|
{
|
||||||
fastBitmap1.GetColorAt(x, y, tmpColor1);
|
fastBitmap1.GetColorAt(x, y, tmpColor1);
|
||||||
fastBitmap2.GetColorAt(x, y, tmpColor2);
|
fastBitmap2.GetColorAt(x, y, tmpColor2);
|
||||||
if (AreColorsSame(tmpColor1, tmpColor2, fastBitmap1.HasAlphaChannel))
|
if (AreColorsSame(tmpColor1, tmpColor2, fastBitmap1.HasAlphaChannel))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Log.Debug().WriteLine("Different colors at {0},{1}", x, y);
|
Log.Debug().WriteLine("Different colors at {0},{1}", x, y);
|
||||||
result = false;
|
result = false;
|
||||||
state.Break();
|
state.Break();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -36,10 +36,8 @@ namespace Greenshot.Gfx
|
||||||
public static void ApplyBoxBlur(this IBitmapWithNativeSupport destinationBitmap, int range)
|
public static void ApplyBoxBlur(this IBitmapWithNativeSupport destinationBitmap, int range)
|
||||||
{
|
{
|
||||||
// We only need one fastbitmap as we use it as source and target (the reading is done for one line H/V, writing after "parsing" one line H/V)
|
// We only need one fastbitmap as we use it as source and target (the reading is done for one line H/V, writing after "parsing" one line H/V)
|
||||||
using (var fastBitmap = FastBitmapFactory.Create(destinationBitmap))
|
using var fastBitmap = FastBitmapFactory.Create(destinationBitmap);
|
||||||
{
|
fastBitmap.ApplyBoxBlur(range);
|
||||||
fastBitmap.ApplyBoxBlur(range);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -76,22 +76,19 @@ namespace Greenshot.Gfx.Effects
|
||||||
using (var path = new GraphicsPath())
|
using (var path = new GraphicsPath())
|
||||||
{
|
{
|
||||||
path.AddRectangle(new NativeRect(borderSize >> 1, borderSize >> 1, newImage.Width - borderSize, newImage.Height - borderSize));
|
path.AddRectangle(new NativeRect(borderSize >> 1, borderSize >> 1, newImage.Width - borderSize, newImage.Height - borderSize));
|
||||||
using (var pen = new Pen(borderColor, borderSize))
|
using var pen = new Pen(borderColor, borderSize) {
|
||||||
{
|
LineJoin = LineJoin.Round,
|
||||||
pen.LineJoin = LineJoin.Round;
|
StartCap = LineCap.Round,
|
||||||
pen.StartCap = LineCap.Round;
|
EndCap = LineCap.Round
|
||||||
pen.EndCap = LineCap.Round;
|
};
|
||||||
graphics.DrawPath(pen, path);
|
graphics.DrawPath(pen, path);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// draw original with a TextureBrush so we have nice anti-aliasing!
|
// draw original with a TextureBrush so we have nice anti-aliasing!
|
||||||
using (Brush textureBrush = new TextureBrush(sourceBitmap.NativeBitmap, WrapMode.Clamp))
|
using Brush textureBrush = new TextureBrush(sourceBitmap.NativeBitmap, WrapMode.Clamp);
|
||||||
{
|
// We need to do a translate-tranform otherwise the image is wrapped
|
||||||
// We need to do a translate-tranform otherwise the image is wrapped
|
graphics.TranslateTransform(offset.X, offset.Y);
|
||||||
graphics.TranslateTransform(offset.X, offset.Y);
|
graphics.FillRectangle(textureBrush, 0, 0, sourceBitmap.Width, sourceBitmap.Height);
|
||||||
graphics.FillRectangle(textureBrush, 0, 0, sourceBitmap.Width, sourceBitmap.Height);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return newImage;
|
return newImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,23 +50,21 @@ namespace Greenshot.Gfx.Effects
|
||||||
/// <param name="threshold">Threshold for monochrome filter (0 - 255), lower value means less black</param>
|
/// <param name="threshold">Threshold for monochrome filter (0 - 255), lower value means less black</param>
|
||||||
/// <returns>b/w bitmap</returns>
|
/// <returns>b/w bitmap</returns>
|
||||||
public static IBitmapWithNativeSupport CreateMonochrome(IBitmapWithNativeSupport sourceBitmap, byte threshold)
|
public static IBitmapWithNativeSupport CreateMonochrome(IBitmapWithNativeSupport sourceBitmap, byte threshold)
|
||||||
{
|
{
|
||||||
using (var fastBitmap = FastBitmapFactory.CreateCloneOf(sourceBitmap, sourceBitmap.PixelFormat))
|
using var fastBitmap = FastBitmapFactory.CreateCloneOf(sourceBitmap, sourceBitmap.PixelFormat);
|
||||||
{
|
Parallel.For(0, fastBitmap.Height, y =>
|
||||||
Parallel.For(0, fastBitmap.Height, y =>
|
{
|
||||||
{
|
// TODO: use stackalloc / unsafe
|
||||||
// TODO: use stackalloc / unsafe
|
for (var x = 0; x < fastBitmap.Width; x++)
|
||||||
for (var x = 0; x < fastBitmap.Width; x++)
|
{
|
||||||
{
|
var color = fastBitmap.GetColorAt(x, y);
|
||||||
var color = fastBitmap.GetColorAt(x, y);
|
var colorBrightness = (color.R + color.G + color.B) / 3 > threshold ? 255 : 0;
|
||||||
var colorBrightness = (color.R + color.G + color.B) / 3 > threshold ? 255 : 0;
|
var monoColor = Color.FromArgb(color.A, colorBrightness, colorBrightness, colorBrightness);
|
||||||
var monoColor = Color.FromArgb(color.A, colorBrightness, colorBrightness, colorBrightness);
|
fastBitmap.SetColorAt(x, y, ref monoColor);
|
||||||
fastBitmap.SetColorAt(x, y, ref monoColor);
|
}
|
||||||
}
|
});
|
||||||
});
|
return fastBitmap.UnlockAndReturnBitmap();
|
||||||
return fastBitmap.UnlockAndReturnBitmap();
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,19 +193,15 @@ namespace Greenshot.Gfx.Effects
|
||||||
path.CloseFigure();
|
path.CloseFigure();
|
||||||
|
|
||||||
// Draw the created figure with the original image by using a TextureBrush so we have anti-aliasing
|
// Draw the created figure with the original image by using a TextureBrush so we have anti-aliasing
|
||||||
using (var graphics = Graphics.FromImage(returnBitmap.NativeBitmap))
|
using var graphics = Graphics.FromImage(returnBitmap.NativeBitmap);
|
||||||
{
|
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
using Brush brush = new TextureBrush(sourceBitmap.NativeBitmap);
|
||||||
using (Brush brush = new TextureBrush(sourceBitmap.NativeBitmap))
|
// Important note: If the target wouldn't be at 0,0 we need to translate-transform!!
|
||||||
{
|
graphics.FillPath(brush, path);
|
||||||
// Important note: If the target wouldn't be at 0,0 we need to translate-transform!!
|
}
|
||||||
graphics.FillPath(brush, path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnBitmap;
|
return returnBitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,35 +34,25 @@ namespace Greenshot.Gfx.Extensions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="bitmap">IBitmapWithNativeSupport</param>
|
/// <param name="bitmap">IBitmapWithNativeSupport</param>
|
||||||
/// <returns>IBitmapWithNativeSupport</returns>
|
/// <returns>IBitmapWithNativeSupport</returns>
|
||||||
public static IBitmapWithNativeSupport Scale2X(this IBitmapWithNativeSupport bitmap)
|
public static IBitmapWithNativeSupport Scale2X(this IBitmapWithNativeSupport bitmap) =>
|
||||||
{
|
bitmap switch
|
||||||
switch (bitmap)
|
|
||||||
{
|
{
|
||||||
case UnmanagedBitmap<Bgra32> unmanagedBitmap:
|
UnmanagedBitmap<Bgra32> unmanagedBitmap => unmanagedBitmap.Scale2X(),
|
||||||
return unmanagedBitmap.Scale2X();
|
UnmanagedBitmap<Bgr32> unmanagedBitmap => unmanagedBitmap.Scale2X(),
|
||||||
case UnmanagedBitmap<Bgr32> unmanagedBitmap:
|
_ => ScaleX.Scale2X(bitmap)
|
||||||
return unmanagedBitmap.Scale2X();
|
};
|
||||||
}
|
|
||||||
|
|
||||||
return ScaleX.Scale2X(bitmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Scale3x
|
/// Scale3x
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="bitmap">IBitmapWithNativeSupport</param>
|
/// <param name="bitmap">IBitmapWithNativeSupport</param>
|
||||||
/// <returns>IBitmapWithNativeSupport</returns>
|
/// <returns>IBitmapWithNativeSupport</returns>
|
||||||
public static IBitmapWithNativeSupport Scale3X(this IBitmapWithNativeSupport bitmap)
|
public static IBitmapWithNativeSupport Scale3X(this IBitmapWithNativeSupport bitmap) =>
|
||||||
{
|
bitmap switch
|
||||||
switch (bitmap)
|
|
||||||
{
|
{
|
||||||
case UnmanagedBitmap<Bgra32> unmanagedBitmap:
|
UnmanagedBitmap<Bgra32> unmanagedBitmap => unmanagedBitmap.Scale3X(),
|
||||||
return unmanagedBitmap.Scale3X();
|
UnmanagedBitmap<Bgr32> unmanagedBitmap => unmanagedBitmap.Scale3X(),
|
||||||
case UnmanagedBitmap<Bgr32> unmanagedBitmap:
|
_ => ScaleX.Scale3X(bitmap)
|
||||||
return unmanagedBitmap.Scale3X();
|
};
|
||||||
}
|
|
||||||
|
|
||||||
return ScaleX.Scale3X(bitmap);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -20,15 +19,13 @@ namespace Greenshot.Gfx.Formats
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IBitmapWithNativeSupport Read(Stream stream, string extension = null)
|
public IBitmapWithNativeSupport Read(Stream stream, string extension = null)
|
||||||
{
|
{
|
||||||
using (var tmpImage = Image.FromStream(stream, true, true))
|
using var tmpImage = Image.FromStream(stream, true, true);
|
||||||
|
if (!(tmpImage is Bitmap bitmap))
|
||||||
{
|
{
|
||||||
if (!(tmpImage is Bitmap bitmap))
|
return null;
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Log.Debug().WriteLine("Loaded bitmap with Size {0}x{1} and PixelFormat {2}", bitmap.Width, bitmap.Height, bitmap.PixelFormat);
|
|
||||||
return bitmap.CloneBitmap(PixelFormat.Format32bppArgb);
|
|
||||||
}
|
}
|
||||||
|
Log.Debug().WriteLine("Loaded bitmap with Size {0}x{1} and PixelFormat {2}", bitmap.Width, bitmap.Height, bitmap.PixelFormat);
|
||||||
|
return bitmap.CloneBitmap(PixelFormat.Format32bppArgb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,12 +28,10 @@ namespace Greenshot.Gfx.Formats
|
||||||
// Icon logic, try to get the Vista icon, else the biggest possible
|
// Icon logic, try to get the Vista icon, else the biggest possible
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var tmpBitmap = ExtractVistaIcon(stream))
|
using var tmpBitmap = ExtractVistaIcon(stream);
|
||||||
|
if (tmpBitmap != null)
|
||||||
{
|
{
|
||||||
if (tmpBitmap != null)
|
return tmpBitmap.CloneBitmap(PixelFormat.Format32bppArgb);
|
||||||
{
|
|
||||||
return tmpBitmap.CloneBitmap(PixelFormat.Format32bppArgb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception vistaIconException)
|
catch (Exception vistaIconException)
|
||||||
|
@ -45,13 +43,9 @@ namespace Greenshot.Gfx.Formats
|
||||||
// No vista icon, try normal icon
|
// No vista icon, try normal icon
|
||||||
stream.Position = 0;
|
stream.Position = 0;
|
||||||
// We create a copy of the bitmap, so everything else can be disposed
|
// We create a copy of the bitmap, so everything else can be disposed
|
||||||
using (var tmpIcon = new Icon(stream, new Size(1024, 1024)))
|
using var tmpIcon = new Icon(stream, new Size(1024, 1024));
|
||||||
{
|
using var tmpImage = tmpIcon.ToBitmap();
|
||||||
using (var tmpImage = tmpIcon.ToBitmap())
|
return tmpImage.CloneBitmap(PixelFormat.Format32bppArgb);
|
||||||
{
|
|
||||||
return tmpImage.CloneBitmap(PixelFormat.Format32bppArgb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception iconException)
|
catch (Exception iconException)
|
||||||
{
|
{
|
||||||
|
@ -89,12 +83,10 @@ namespace Greenshot.Gfx.Formats
|
||||||
}
|
}
|
||||||
var iImageSize = BitConverter.ToInt32(srcBuf, sizeIconDir + sizeIconDirEntry * iIndex + 8);
|
var iImageSize = BitConverter.ToInt32(srcBuf, sizeIconDir + sizeIconDirEntry * iIndex + 8);
|
||||||
var iImageOffset = BitConverter.ToInt32(srcBuf, sizeIconDir + sizeIconDirEntry * iIndex + 12);
|
var iImageOffset = BitConverter.ToInt32(srcBuf, sizeIconDir + sizeIconDirEntry * iIndex + 12);
|
||||||
using (var destStream = new MemoryStream())
|
using var destStream = new MemoryStream();
|
||||||
{
|
destStream.Write(srcBuf, iImageOffset, iImageSize);
|
||||||
destStream.Write(srcBuf, iImageOffset, iImageSize);
|
destStream.Seek(0, SeekOrigin.Begin);
|
||||||
destStream.Seek(0, SeekOrigin.Begin);
|
bmpPngExtracted = BitmapWrapper.FromBitmap(new Bitmap(destStream)); // This is PNG! :)
|
||||||
bmpPngExtracted = BitmapWrapper.FromBitmap(new Bitmap(destStream)); // This is PNG! :)
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<PackageReference Include="Dapplo.Log" Version="1.3.26" />
|
<PackageReference Include="Dapplo.Log" Version="1.3.26" />
|
||||||
<PackageReference Include="Dapplo.Windows" Version="0.11.6" />
|
<PackageReference Include="Dapplo.Windows" Version="0.11.6" />
|
||||||
<PackageReference Include="Dapplo.Windows.Dpi" Version="0.11.6" />
|
<PackageReference Include="Dapplo.Windows.Dpi" Version="0.11.6" />
|
||||||
<PackageReference Include="Svg" Version="3.0.49" />
|
<PackageReference Include="Svg" Version="3.0.84" />
|
||||||
<PackageReference Include="System.Memory" Version="4.5.3" />
|
<PackageReference Include="System.Memory" Version="4.5.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -105,53 +105,49 @@ namespace Greenshot.Gfx.Quantizer
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use a bitmap to store the initial match, which is just as good as an array and saves us 2x the storage
|
// Use a bitmap to store the initial match, which is just as good as an array and saves us 2x the storage
|
||||||
using (var sourceFastBitmap = FastBitmapFactory.Create(sourceBitmap))
|
using var sourceFastBitmap = FastBitmapFactory.Create(sourceBitmap);
|
||||||
{
|
sourceFastBitmap.Lock();
|
||||||
sourceFastBitmap.Lock();
|
using var destinationFastBitmap = FastBitmapFactory.CreateEmpty(sourceBitmap.Size, PixelFormat.Format8bppIndexed, Color.White) as FastChunkyBitmap;
|
||||||
using (var destinationFastBitmap = FastBitmapFactory.CreateEmpty(sourceBitmap.Size, PixelFormat.Format8bppIndexed, Color.White) as FastChunkyBitmap)
|
for (var y = 0; y < sourceFastBitmap.Height; y++)
|
||||||
{
|
{
|
||||||
for (var y = 0; y < sourceFastBitmap.Height; y++)
|
for (var x = 0; x < sourceFastBitmap.Width; x++)
|
||||||
{
|
{
|
||||||
for (var x = 0; x < sourceFastBitmap.Width; x++)
|
Color color;
|
||||||
{
|
if (!(sourceFastBitmap is IFastBitmapWithBlend sourceFastBitmapWithBlend))
|
||||||
Color color;
|
{
|
||||||
if (!(sourceFastBitmap is IFastBitmapWithBlend sourceFastBitmapWithBlend))
|
color = sourceFastBitmap.GetColorAt(x, y);
|
||||||
{
|
}
|
||||||
color = sourceFastBitmap.GetColorAt(x, y);
|
else
|
||||||
}
|
{
|
||||||
else
|
color = sourceFastBitmapWithBlend.GetBlendedColorAt(x, y);
|
||||||
{
|
}
|
||||||
color = sourceFastBitmapWithBlend.GetBlendedColorAt(x, y);
|
// To count the colors
|
||||||
}
|
var index = color.ToArgb() & 0x00ffffff;
|
||||||
// To count the colors
|
// Check if we already have this color
|
||||||
var index = color.ToArgb() & 0x00ffffff;
|
if (!bitArray.Get(index))
|
||||||
// Check if we already have this color
|
{
|
||||||
if (!bitArray.Get(index))
|
// If not, add 1 to the single colors
|
||||||
{
|
_colorCount++;
|
||||||
// If not, add 1 to the single colors
|
bitArray.Set(index, true);
|
||||||
_colorCount++;
|
}
|
||||||
bitArray.Set(index, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
var indexRed = (color.R >> 3) + 1;
|
var indexRed = (color.R >> 3) + 1;
|
||||||
var indexGreen = (color.G >> 3) + 1;
|
var indexGreen = (color.G >> 3) + 1;
|
||||||
var indexBlue = (color.B >> 3) + 1;
|
var indexBlue = (color.B >> 3) + 1;
|
||||||
|
|
||||||
_weights[indexRed, indexGreen, indexBlue]++;
|
_weights[indexRed, indexGreen, indexBlue]++;
|
||||||
_momentsRed[indexRed, indexGreen, indexBlue] += color.R;
|
_momentsRed[indexRed, indexGreen, indexBlue] += color.R;
|
||||||
_momentsGreen[indexRed, indexGreen, indexBlue] += color.G;
|
_momentsGreen[indexRed, indexGreen, indexBlue] += color.G;
|
||||||
_momentsBlue[indexRed, indexGreen, indexBlue] += color.B;
|
_momentsBlue[indexRed, indexGreen, indexBlue] += color.B;
|
||||||
_moments[indexRed, indexGreen, indexBlue] += table[color.R] + table[color.G] + table[color.B];
|
_moments[indexRed, indexGreen, indexBlue] += table[color.R] + table[color.G] + table[color.B];
|
||||||
|
|
||||||
// Store the initial "match"
|
// Store the initial "match"
|
||||||
var paletteIndex = (indexRed << 10) + (indexRed << 6) + indexRed + (indexGreen << 5) + indexGreen + indexBlue;
|
var paletteIndex = (indexRed << 10) + (indexRed << 6) + indexRed + (indexGreen << 5) + indexGreen + indexBlue;
|
||||||
destinationFastBitmap.SetColorIndexAt(x, y, (byte) (paletteIndex & 0xff));
|
destinationFastBitmap.SetColorIndexAt(x, y, (byte) (paletteIndex & 0xff));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_resultBitmap = destinationFastBitmap.UnlockAndReturnBitmap();
|
_resultBitmap = destinationFastBitmap.UnlockAndReturnBitmap();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -200,38 +196,36 @@ namespace Greenshot.Gfx.Quantizer
|
||||||
using (var bbbDest = FastBitmapFactory.Create(_resultBitmap) as FastChunkyBitmap)
|
using (var bbbDest = FastBitmapFactory.Create(_resultBitmap) as FastChunkyBitmap)
|
||||||
{
|
{
|
||||||
bbbDest.Lock();
|
bbbDest.Lock();
|
||||||
using (var bbbSrc = FastBitmapFactory.Create(_sourceBitmap))
|
using var bbbSrc = FastBitmapFactory.Create(_sourceBitmap);
|
||||||
{
|
bbbSrc.Lock();
|
||||||
bbbSrc.Lock();
|
for (var y = 0; y < bbbSrc.Height; y++)
|
||||||
for (var y = 0; y < bbbSrc.Height; y++)
|
{
|
||||||
{
|
for (var x = 0; x < bbbSrc.Width; x++)
|
||||||
for (var x = 0; x < bbbSrc.Width; x++)
|
{
|
||||||
{
|
Color color;
|
||||||
Color color;
|
if (bbbSrc is IFastBitmapWithBlend bbbSrcBlend)
|
||||||
if (bbbSrc is IFastBitmapWithBlend bbbSrcBlend)
|
{
|
||||||
{
|
color = bbbSrcBlend.GetBlendedColorAt(x, y);
|
||||||
color = bbbSrcBlend.GetBlendedColorAt(x, y);
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
color = bbbSrc.GetColorAt(x, y);
|
||||||
color = bbbSrc.GetColorAt(x, y);
|
}
|
||||||
}
|
byte index;
|
||||||
byte index;
|
if (lookup.ContainsKey(color))
|
||||||
if (lookup.ContainsKey(color))
|
{
|
||||||
{
|
index = lookup[color];
|
||||||
index = lookup[color];
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
colors.Add(color);
|
||||||
colors.Add(color);
|
index = (byte) (colors.Count - 1);
|
||||||
index = (byte) (colors.Count - 1);
|
lookup.Add(color, index);
|
||||||
lookup.Add(color, index);
|
}
|
||||||
}
|
bbbDest.SetColorIndexAt(x, y, index);
|
||||||
bbbDest.SetColorIndexAt(x, y, index);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// generates palette
|
// generates palette
|
||||||
var imagePalette = _resultBitmap.NativeBitmap.Palette;
|
var imagePalette = _resultBitmap.NativeBitmap.Palette;
|
||||||
|
@ -348,71 +342,69 @@ namespace Greenshot.Gfx.Quantizer
|
||||||
Log.Info().WriteLine("Starting bitmap reconstruction...");
|
Log.Info().WriteLine("Starting bitmap reconstruction...");
|
||||||
|
|
||||||
using (var dest = FastBitmapFactory.Create(_resultBitmap) as FastChunkyBitmap)
|
using (var dest = FastBitmapFactory.Create(_resultBitmap) as FastChunkyBitmap)
|
||||||
{
|
{
|
||||||
using (var src = FastBitmapFactory.Create(_sourceBitmap))
|
using var src = FastBitmapFactory.Create(_sourceBitmap);
|
||||||
{
|
var lookup = new Dictionary<Color, byte>();
|
||||||
var lookup = new Dictionary<Color, byte>();
|
for (var y = 0; y < src.Height; y++)
|
||||||
for (var y = 0; y < src.Height; y++)
|
{
|
||||||
{
|
for (var x = 0; x < src.Width; x++)
|
||||||
for (var x = 0; x < src.Width; x++)
|
{
|
||||||
{
|
Color color;
|
||||||
Color color;
|
if (src is IFastBitmapWithBlend srcBlend)
|
||||||
if (src is IFastBitmapWithBlend srcBlend)
|
{
|
||||||
{
|
// WithoutAlpha, this makes it possible to ignore the alpha
|
||||||
// WithoutAlpha, this makes it possible to ignore the alpha
|
color = srcBlend.GetBlendedColorAt(x, y);
|
||||||
color = srcBlend.GetBlendedColorAt(x, y);
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
color = src.GetColorAt(x, y);
|
||||||
color = src.GetColorAt(x, y);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we already matched the color
|
// Check if we already matched the color
|
||||||
byte bestMatch;
|
byte bestMatch;
|
||||||
if (!lookup.ContainsKey(color))
|
if (!lookup.ContainsKey(color))
|
||||||
{
|
{
|
||||||
// If not we need to find the best match
|
// If not we need to find the best match
|
||||||
|
|
||||||
// First get initial match
|
// First get initial match
|
||||||
bestMatch = dest.GetColorIndexAt(x, y);
|
bestMatch = dest.GetColorIndexAt(x, y);
|
||||||
bestMatch = _tag[bestMatch];
|
bestMatch = _tag[bestMatch];
|
||||||
|
|
||||||
var bestDistance = 100000000;
|
var bestDistance = 100000000;
|
||||||
for (var lookupIndex = 0; lookupIndex < allowedColorCount; lookupIndex++)
|
for (var lookupIndex = 0; lookupIndex < allowedColorCount; lookupIndex++)
|
||||||
{
|
{
|
||||||
var foundRed = lookupRed[lookupIndex];
|
var foundRed = lookupRed[lookupIndex];
|
||||||
var foundGreen = lookupGreen[lookupIndex];
|
var foundGreen = lookupGreen[lookupIndex];
|
||||||
var foundBlue = lookupBlue[lookupIndex];
|
var foundBlue = lookupBlue[lookupIndex];
|
||||||
var deltaRed = color.R - foundRed;
|
var deltaRed = color.R - foundRed;
|
||||||
var deltaGreen = color.G - foundGreen;
|
var deltaGreen = color.G - foundGreen;
|
||||||
var deltaBlue = color.B - foundBlue;
|
var deltaBlue = color.B - foundBlue;
|
||||||
|
|
||||||
var distance = deltaRed * deltaRed + deltaGreen * deltaGreen + deltaBlue * deltaBlue;
|
var distance = deltaRed * deltaRed + deltaGreen * deltaGreen + deltaBlue * deltaBlue;
|
||||||
|
|
||||||
if (distance < bestDistance)
|
if (distance < bestDistance)
|
||||||
{
|
{
|
||||||
bestDistance = distance;
|
bestDistance = distance;
|
||||||
bestMatch = (byte) lookupIndex;
|
bestMatch = (byte) lookupIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lookup.Add(color, bestMatch);
|
lookup.Add(color, bestMatch);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Already matched, so we just use the lookup
|
// Already matched, so we just use the lookup
|
||||||
bestMatch = lookup[color];
|
bestMatch = lookup[color];
|
||||||
}
|
}
|
||||||
|
|
||||||
_reds[bestMatch] += color.R;
|
_reds[bestMatch] += color.R;
|
||||||
_greens[bestMatch] += color.G;
|
_greens[bestMatch] += color.G;
|
||||||
_blues[bestMatch] += color.B;
|
_blues[bestMatch] += color.B;
|
||||||
_sums[bestMatch]++;
|
_sums[bestMatch]++;
|
||||||
|
|
||||||
dest.SetColorIndexAt(x, y, bestMatch);
|
dest.SetColorIndexAt(x, y, bestMatch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// generates palette
|
// generates palette
|
||||||
|
@ -524,63 +516,46 @@ namespace Greenshot.Gfx.Quantizer
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Splits the cube in given position, and color direction.
|
/// Splits the cube in given position, and color direction.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static long Top(WuColorCube cube, int direction, int position, long[,,] moment)
|
private static long Top(WuColorCube cube, int direction, int position, long[,,] moment) =>
|
||||||
{
|
direction switch
|
||||||
switch (direction)
|
{
|
||||||
{
|
Red => (moment[position, cube.GreenMaximum, cube.BlueMaximum] -
|
||||||
case Red:
|
moment[position, cube.GreenMaximum, cube.BlueMinimum] -
|
||||||
return moment[position, cube.GreenMaximum, cube.BlueMaximum] -
|
moment[position, cube.GreenMinimum, cube.BlueMaximum] +
|
||||||
moment[position, cube.GreenMaximum, cube.BlueMinimum] -
|
moment[position, cube.GreenMinimum, cube.BlueMinimum]),
|
||||||
moment[position, cube.GreenMinimum, cube.BlueMaximum] +
|
Green => (moment[cube.RedMaximum, position, cube.BlueMaximum] -
|
||||||
moment[position, cube.GreenMinimum, cube.BlueMinimum];
|
moment[cube.RedMaximum, position, cube.BlueMinimum] -
|
||||||
|
moment[cube.RedMinimum, position, cube.BlueMaximum] +
|
||||||
|
moment[cube.RedMinimum, position, cube.BlueMinimum]),
|
||||||
|
Blue => (moment[cube.RedMaximum, cube.GreenMaximum, position] -
|
||||||
|
moment[cube.RedMaximum, cube.GreenMinimum, position] -
|
||||||
|
moment[cube.RedMinimum, cube.GreenMaximum, position] +
|
||||||
|
moment[cube.RedMinimum, cube.GreenMinimum, position]),
|
||||||
|
_ => 0
|
||||||
|
};
|
||||||
|
|
||||||
case Green:
|
/// <summary>
|
||||||
return moment[cube.RedMaximum, position, cube.BlueMaximum] -
|
|
||||||
moment[cube.RedMaximum, position, cube.BlueMinimum] -
|
|
||||||
moment[cube.RedMinimum, position, cube.BlueMaximum] +
|
|
||||||
moment[cube.RedMinimum, position, cube.BlueMinimum];
|
|
||||||
|
|
||||||
case Blue:
|
|
||||||
return moment[cube.RedMaximum, cube.GreenMaximum, position] -
|
|
||||||
moment[cube.RedMaximum, cube.GreenMinimum, position] -
|
|
||||||
moment[cube.RedMinimum, cube.GreenMaximum, position] +
|
|
||||||
moment[cube.RedMinimum, cube.GreenMinimum, position];
|
|
||||||
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Splits the cube in a given color direction at its minimum.
|
/// Splits the cube in a given color direction at its minimum.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static long Bottom(WuColorCube cube, int direction, long[,,] moment)
|
private static long Bottom(WuColorCube cube, int direction, long[,,] moment) =>
|
||||||
{
|
direction switch
|
||||||
switch (direction)
|
{
|
||||||
{
|
Red => (-moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMaximum] +
|
||||||
case Red:
|
moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] +
|
||||||
return -moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMaximum] +
|
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] -
|
||||||
moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] +
|
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]),
|
||||||
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] -
|
Green => (-moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMaximum] +
|
||||||
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum];
|
moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] +
|
||||||
|
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] -
|
||||||
|
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]),
|
||||||
|
Blue => (-moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMinimum] +
|
||||||
|
moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] +
|
||||||
|
moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] -
|
||||||
|
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]),
|
||||||
|
_ => 0
|
||||||
|
};
|
||||||
|
|
||||||
case Green:
|
/// <summary>
|
||||||
return -moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMaximum] +
|
|
||||||
moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] +
|
|
||||||
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] -
|
|
||||||
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum];
|
|
||||||
|
|
||||||
case Blue:
|
|
||||||
return -moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMinimum] +
|
|
||||||
moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] +
|
|
||||||
moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] -
|
|
||||||
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum];
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates statistical variance for a given cube.
|
/// Calculates statistical variance for a given cube.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private float CalculateVariance(WuColorCube cube)
|
private float CalculateVariance(WuColorCube cube)
|
||||||
|
|
|
@ -36,56 +36,54 @@ namespace Greenshot.Gfx
|
||||||
/// <param name="original">Bitmap to scale 2x</param>
|
/// <param name="original">Bitmap to scale 2x</param>
|
||||||
public static IBitmapWithNativeSupport Scale2X(IBitmapWithNativeSupport original)
|
public static IBitmapWithNativeSupport Scale2X(IBitmapWithNativeSupport original)
|
||||||
{
|
{
|
||||||
using (var source = (IFastBitmapWithClip)FastBitmapFactory.Create(original))
|
using var source = (IFastBitmapWithClip)FastBitmapFactory.Create(original);
|
||||||
using (var destination = (IFastBitmapWithClip)FastBitmapFactory.CreateEmpty(new Size(original.Width << 1, original.Height << 1), original.PixelFormat))
|
using var destination = (IFastBitmapWithClip)FastBitmapFactory.CreateEmpty(new Size(original.Width << 1, original.Height << 1), original.PixelFormat);
|
||||||
|
// Every pixel from input texture produces 4 output pixels, for more details check out http://scale2x.sourceforge.net/algorithm.html
|
||||||
|
Parallel.For(0, source.Height, y =>
|
||||||
{
|
{
|
||||||
// Every pixel from input texture produces 4 output pixels, for more details check out http://scale2x.sourceforge.net/algorithm.html
|
unsafe
|
||||||
Parallel.For(0, source.Height, y =>
|
|
||||||
{
|
{
|
||||||
unsafe
|
var colorB = stackalloc byte[4];
|
||||||
|
var colorD = stackalloc byte[4];
|
||||||
|
var colorE = stackalloc byte[4];
|
||||||
|
var colorF = stackalloc byte[4];
|
||||||
|
var colorH = stackalloc byte[4];
|
||||||
|
var x = 0;
|
||||||
|
while (x < source.Width)
|
||||||
{
|
{
|
||||||
var colorB = stackalloc byte[4];
|
source.GetColorAt(x, y - 1, colorB);
|
||||||
var colorD = stackalloc byte[4];
|
source.GetColorAt(x, y + 1, colorH);
|
||||||
var colorE = stackalloc byte[4];
|
source.GetColorAt(x - 1, y, colorD);
|
||||||
var colorF = stackalloc byte[4];
|
source.GetColorAt(x + 1, y, colorF);
|
||||||
var colorH = stackalloc byte[4];
|
source.GetColorAt(x, y, colorE);
|
||||||
var x = 0;
|
|
||||||
while (x < source.Width)
|
byte* colorE0, colorE1, colorE2, colorE3;
|
||||||
|
if (!AreColorsSame(colorB, colorH) && !AreColorsSame(colorD, colorF))
|
||||||
{
|
{
|
||||||
source.GetColorAt(x, y - 1, colorB);
|
colorE0 = AreColorsSame(colorD, colorB) ? colorD : colorE;
|
||||||
source.GetColorAt(x, y + 1, colorH);
|
colorE1 = AreColorsSame(colorB, colorF) ? colorF : colorE;
|
||||||
source.GetColorAt(x - 1, y, colorD);
|
colorE2 = AreColorsSame(colorD, colorH) ? colorD : colorE;
|
||||||
source.GetColorAt(x + 1, y, colorF);
|
colorE3 = AreColorsSame(colorH, colorF) ? colorF : colorE;
|
||||||
source.GetColorAt(x, y, colorE);
|
}
|
||||||
|
else
|
||||||
byte* colorE0, colorE1, colorE2, colorE3;
|
{
|
||||||
if (!AreColorsSame(colorB, colorH) && !AreColorsSame(colorD, colorF))
|
colorE0 = colorE;
|
||||||
{
|
colorE1 = colorE;
|
||||||
colorE0 = AreColorsSame(colorD, colorB) ? colorD : colorE;
|
colorE2 = colorE;
|
||||||
colorE1 = AreColorsSame(colorB, colorF) ? colorF : colorE;
|
colorE3 = colorE;
|
||||||
colorE2 = AreColorsSame(colorD, colorH) ? colorD : colorE;
|
|
||||||
colorE3 = AreColorsSame(colorH, colorF) ? colorF : colorE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
colorE0 = colorE;
|
|
||||||
colorE1 = colorE;
|
|
||||||
colorE2 = colorE;
|
|
||||||
colorE3 = colorE;
|
|
||||||
}
|
|
||||||
|
|
||||||
destination.SetColorAt(x << 1, y << 1, colorE0);
|
|
||||||
destination.SetColorAt((x << 1) + 1, y << 1, colorE1);
|
|
||||||
destination.SetColorAt(x << 1, (y << 1) + 1, colorE2);
|
|
||||||
destination.SetColorAt((x << 1) + 1, (y << 1) + 1, colorE3);
|
|
||||||
|
|
||||||
x++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
destination.SetColorAt(x << 1, y << 1, colorE0);
|
||||||
|
destination.SetColorAt((x << 1) + 1, y << 1, colorE1);
|
||||||
|
destination.SetColorAt(x << 1, (y << 1) + 1, colorE2);
|
||||||
|
destination.SetColorAt((x << 1) + 1, (y << 1) + 1, colorE3);
|
||||||
|
|
||||||
|
x++;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
return destination.UnlockAndReturnBitmap();
|
}
|
||||||
}
|
});
|
||||||
|
return destination.UnlockAndReturnBitmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -95,89 +93,87 @@ namespace Greenshot.Gfx
|
||||||
[SuppressMessage("ReSharper", "AccessToDisposedClosure")]
|
[SuppressMessage("ReSharper", "AccessToDisposedClosure")]
|
||||||
public static IBitmapWithNativeSupport Scale3X(IBitmapWithNativeSupport original)
|
public static IBitmapWithNativeSupport Scale3X(IBitmapWithNativeSupport original)
|
||||||
{
|
{
|
||||||
using (var source = (IFastBitmapWithClip)FastBitmapFactory.Create(original))
|
using var source = (IFastBitmapWithClip)FastBitmapFactory.Create(original);
|
||||||
using (var destination = (IFastBitmapWithClip)FastBitmapFactory.CreateEmpty(new Size(original.Width * 3, original.Height * 3), original.PixelFormat))
|
using var destination = (IFastBitmapWithClip)FastBitmapFactory.CreateEmpty(new Size(original.Width * 3, original.Height * 3), original.PixelFormat);
|
||||||
|
// Every pixel from input texture produces 6 output pixels, for more details check out http://scale2x.sourceforge.net/algorithm.html
|
||||||
|
Parallel.For(0, source.Height, y =>
|
||||||
{
|
{
|
||||||
// Every pixel from input texture produces 6 output pixels, for more details check out http://scale2x.sourceforge.net/algorithm.html
|
unsafe
|
||||||
Parallel.For(0, source.Height, y =>
|
|
||||||
{
|
{
|
||||||
unsafe
|
var x = 0;
|
||||||
|
var colorA = stackalloc byte[4];
|
||||||
|
var colorB = stackalloc byte[4];
|
||||||
|
var colorC = stackalloc byte[4];
|
||||||
|
var colorD = stackalloc byte[4];
|
||||||
|
var colorE = stackalloc byte[4];
|
||||||
|
var colorF = stackalloc byte[4];
|
||||||
|
var colorG = stackalloc byte[4];
|
||||||
|
var colorH = stackalloc byte[4];
|
||||||
|
var colorI = stackalloc byte[4];
|
||||||
|
while (x < source.Width)
|
||||||
{
|
{
|
||||||
var x = 0;
|
source.GetColorAt(x - 1, y - 1, colorA);
|
||||||
var colorA = stackalloc byte[4];
|
source.GetColorAt(x, y - 1, colorB);
|
||||||
var colorB = stackalloc byte[4];
|
source.GetColorAt(x + 1, y - 1, colorC);
|
||||||
var colorC = stackalloc byte[4];
|
|
||||||
var colorD = stackalloc byte[4];
|
source.GetColorAt(x - 1, y, colorD);
|
||||||
var colorE = stackalloc byte[4];
|
source.GetColorAt(x, y, colorE);
|
||||||
var colorF = stackalloc byte[4];
|
source.GetColorAt(x + 1, y, colorF);
|
||||||
var colorG = stackalloc byte[4];
|
|
||||||
var colorH = stackalloc byte[4];
|
source.GetColorAt(x - 1, y + 1, colorG);
|
||||||
var colorI = stackalloc byte[4];
|
source.GetColorAt(x, y + 1, colorH);
|
||||||
while (x < source.Width)
|
source.GetColorAt(x + 1, y + 1, colorI);
|
||||||
|
|
||||||
|
byte* colorE0, colorE1, colorE2, colorE3, colorE4, colorE5, colorE6, colorE7, colorE8;
|
||||||
|
|
||||||
|
if (!AreColorsSame(colorB, colorH) && !AreColorsSame(colorD, colorF))
|
||||||
{
|
{
|
||||||
source.GetColorAt(x - 1, y - 1, colorA);
|
colorE0 = AreColorsSame(colorD, colorB) ? colorD : colorE;
|
||||||
source.GetColorAt(x, y - 1, colorB);
|
colorE1 = AreColorsSame(colorD, colorB) && !AreColorsSame(colorE, colorC) || AreColorsSame(colorB, colorF) && !AreColorsSame(colorE, colorA) ? colorB : colorE;
|
||||||
source.GetColorAt(x + 1, y - 1, colorC);
|
colorE2 = AreColorsSame(colorB, colorF) ? colorF : colorE;
|
||||||
|
colorE3 = AreColorsSame(colorD, colorB) && !AreColorsSame(colorE, colorG) || AreColorsSame(colorD, colorH) && !AreColorsSame(colorE, colorA) ? colorD : colorE;
|
||||||
|
|
||||||
source.GetColorAt(x - 1, y, colorD);
|
colorE4 = colorE;
|
||||||
source.GetColorAt(x, y, colorE);
|
colorE5 = AreColorsSame(colorB, colorF) && !AreColorsSame(colorE, colorI) || AreColorsSame(colorH, colorF) && !AreColorsSame(colorE, colorC) ? colorF : colorE;
|
||||||
source.GetColorAt(x + 1, y, colorF);
|
colorE6 = AreColorsSame(colorD, colorH) ? colorD : colorE;
|
||||||
|
colorE7 = AreColorsSame(colorD, colorH) && !AreColorsSame(colorE, colorI) || AreColorsSame(colorH, colorF) && !AreColorsSame(colorE, colorG) ? colorH : colorE;
|
||||||
source.GetColorAt(x - 1, y + 1, colorG);
|
colorE8 = AreColorsSame(colorH, colorF) ? colorF : colorE;
|
||||||
source.GetColorAt(x, y + 1, colorH);
|
|
||||||
source.GetColorAt(x + 1, y + 1, colorI);
|
|
||||||
|
|
||||||
byte* colorE0, colorE1, colorE2, colorE3, colorE4, colorE5, colorE6, colorE7, colorE8;
|
|
||||||
|
|
||||||
if (!AreColorsSame(colorB, colorH) && !AreColorsSame(colorD, colorF))
|
|
||||||
{
|
|
||||||
colorE0 = AreColorsSame(colorD, colorB) ? colorD : colorE;
|
|
||||||
colorE1 = AreColorsSame(colorD, colorB) && !AreColorsSame(colorE, colorC) || AreColorsSame(colorB, colorF) && !AreColorsSame(colorE, colorA) ? colorB : colorE;
|
|
||||||
colorE2 = AreColorsSame(colorB, colorF) ? colorF : colorE;
|
|
||||||
colorE3 = AreColorsSame(colorD, colorB) && !AreColorsSame(colorE, colorG) || AreColorsSame(colorD, colorH) && !AreColorsSame(colorE, colorA) ? colorD : colorE;
|
|
||||||
|
|
||||||
colorE4 = colorE;
|
|
||||||
colorE5 = AreColorsSame(colorB, colorF) && !AreColorsSame(colorE, colorI) || AreColorsSame(colorH, colorF) && !AreColorsSame(colorE, colorC) ? colorF : colorE;
|
|
||||||
colorE6 = AreColorsSame(colorD, colorH) ? colorD : colorE;
|
|
||||||
colorE7 = AreColorsSame(colorD, colorH) && !AreColorsSame(colorE, colorI) || AreColorsSame(colorH, colorF) && !AreColorsSame(colorE, colorG) ? colorH : colorE;
|
|
||||||
colorE8 = AreColorsSame(colorH, colorF) ? colorF : colorE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
colorE0 = colorE;
|
|
||||||
colorE1 = colorE;
|
|
||||||
colorE2 = colorE;
|
|
||||||
colorE3 = colorE;
|
|
||||||
colorE4 = colorE;
|
|
||||||
colorE5 = colorE;
|
|
||||||
colorE6 = colorE;
|
|
||||||
colorE7 = colorE;
|
|
||||||
colorE8 = colorE;
|
|
||||||
}
|
|
||||||
var multipliedX = 3 * x;
|
|
||||||
var multipliedY = 3 * y;
|
|
||||||
|
|
||||||
destination.SetColorAt(multipliedX, multipliedY, colorE0);
|
|
||||||
destination.SetColorAt(multipliedX + 1, multipliedY, colorE1);
|
|
||||||
destination.SetColorAt(multipliedX + 2, multipliedY, colorE2);
|
|
||||||
|
|
||||||
multipliedY++;
|
|
||||||
destination.SetColorAt(multipliedX, multipliedY, colorE3);
|
|
||||||
destination.SetColorAt(multipliedX + 1, multipliedY, colorE4);
|
|
||||||
destination.SetColorAt(multipliedX + 2, multipliedY, colorE5);
|
|
||||||
|
|
||||||
multipliedY++;
|
|
||||||
destination.SetColorAt(multipliedX, multipliedY, colorE6);
|
|
||||||
destination.SetColorAt(multipliedX + 1, multipliedY, colorE7);
|
|
||||||
destination.SetColorAt(multipliedX + 2, multipliedY, colorE8);
|
|
||||||
|
|
||||||
x++;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colorE0 = colorE;
|
||||||
|
colorE1 = colorE;
|
||||||
|
colorE2 = colorE;
|
||||||
|
colorE3 = colorE;
|
||||||
|
colorE4 = colorE;
|
||||||
|
colorE5 = colorE;
|
||||||
|
colorE6 = colorE;
|
||||||
|
colorE7 = colorE;
|
||||||
|
colorE8 = colorE;
|
||||||
|
}
|
||||||
|
var multipliedX = 3 * x;
|
||||||
|
var multipliedY = 3 * y;
|
||||||
|
|
||||||
|
destination.SetColorAt(multipliedX, multipliedY, colorE0);
|
||||||
|
destination.SetColorAt(multipliedX + 1, multipliedY, colorE1);
|
||||||
|
destination.SetColorAt(multipliedX + 2, multipliedY, colorE2);
|
||||||
|
|
||||||
|
multipliedY++;
|
||||||
|
destination.SetColorAt(multipliedX, multipliedY, colorE3);
|
||||||
|
destination.SetColorAt(multipliedX + 1, multipliedY, colorE4);
|
||||||
|
destination.SetColorAt(multipliedX + 2, multipliedY, colorE5);
|
||||||
|
|
||||||
|
multipliedY++;
|
||||||
|
destination.SetColorAt(multipliedX, multipliedY, colorE6);
|
||||||
|
destination.SetColorAt(multipliedX + 1, multipliedY, colorE7);
|
||||||
|
destination.SetColorAt(multipliedX + 2, multipliedY, colorE8);
|
||||||
|
|
||||||
|
x++;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
return destination.UnlockAndReturnBitmap();
|
}
|
||||||
}
|
});
|
||||||
|
return destination.UnlockAndReturnBitmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -133,24 +133,14 @@ namespace Greenshot.Gfx
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
PixelFormat format;
|
|
||||||
TPixelLayout empty = default;
|
TPixelLayout empty = default;
|
||||||
switch (empty)
|
return empty switch
|
||||||
{
|
{
|
||||||
case Bgr24 _:
|
Bgr24 _ => PixelFormat.Format24bppRgb,
|
||||||
format = PixelFormat.Format24bppRgb;
|
Bgra32 _ => PixelFormat.Format32bppArgb,
|
||||||
break;
|
Bgr32 _ => PixelFormat.Format32bppRgb,
|
||||||
case Bgra32 _:
|
_ => throw new NotSupportedException("Unknown pixel format")
|
||||||
format = PixelFormat.Format32bppArgb;
|
};
|
||||||
break;
|
|
||||||
case Bgr32 _:
|
|
||||||
format = PixelFormat.Format32bppRgb;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new NotSupportedException("Unknown pixel format");
|
|
||||||
}
|
|
||||||
|
|
||||||
return format;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,17 +152,13 @@ namespace Greenshot.Gfx
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
TPixelLayout empty = default;
|
TPixelLayout empty = default;
|
||||||
switch (empty)
|
return empty switch
|
||||||
{
|
{
|
||||||
case Bgr24 _:
|
Bgr24 _ => PixelFormats.Bgr24,
|
||||||
return PixelFormats.Bgr24;
|
Bgra32 _ => PixelFormats.Bgra32,
|
||||||
case Bgra32 _:
|
Bgr32 _ => PixelFormats.Bgr32,
|
||||||
return PixelFormats.Bgra32;
|
_ => throw new NotSupportedException("Unknown pixel format")
|
||||||
case Bgr32 _:
|
};
|
||||||
return PixelFormats.Bgr32;
|
|
||||||
default:
|
|
||||||
throw new NotSupportedException("Unknown pixel format");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Drawing.Imaging;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using BenchmarkDotNet.Attributes;
|
using BenchmarkDotNet.Attributes;
|
||||||
using Dapplo.Log;
|
using Dapplo.Log;
|
||||||
|
@ -75,16 +74,14 @@ namespace Greenshot.PerformanceTests
|
||||||
//[Benchmark]
|
//[Benchmark]
|
||||||
public void Capture()
|
public void Capture()
|
||||||
{
|
{
|
||||||
using (var capture = WindowCapture.CaptureScreen())
|
using var capture = WindowCapture.CaptureScreen();
|
||||||
|
if (capture.Bitmap == null)
|
||||||
{
|
{
|
||||||
if (capture.Bitmap == null)
|
throw new NotSupportedException();
|
||||||
{
|
}
|
||||||
throw new NotSupportedException();
|
if (capture.Bitmap.Width <= 0 || capture.Bitmap.Height <= 0)
|
||||||
}
|
{
|
||||||
if (capture.Bitmap.Width <= 0 || capture.Bitmap.Height <= 0)
|
throw new NotSupportedException();
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,11 +40,9 @@ namespace Greenshot.PerformanceTests
|
||||||
{
|
{
|
||||||
_unmanagedTestBitmap = new UnmanagedBitmap<Bgr32>(400, 400);
|
_unmanagedTestBitmap = new UnmanagedBitmap<Bgr32>(400, 400);
|
||||||
_unmanagedTestBitmap.Span.Fill(new Bgr32 { B = 255, G = 255, R = 255, Unused = 0});
|
_unmanagedTestBitmap.Span.Fill(new Bgr32 { B = 255, G = 255, R = 255, Unused = 0});
|
||||||
using (var graphics = Graphics.FromImage(_unmanagedTestBitmap.NativeBitmap))
|
using var graphics = Graphics.FromImage(_unmanagedTestBitmap.NativeBitmap);
|
||||||
using (var pen = new SolidBrush(Color.Blue))
|
using var pen = new SolidBrush(Color.Blue);
|
||||||
{
|
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
||||||
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[GlobalCleanup]
|
[GlobalCleanup]
|
||||||
|
@ -60,19 +58,16 @@ namespace Greenshot.PerformanceTests
|
||||||
[Arguments(PixelFormat.Format32bppArgb)]
|
[Arguments(PixelFormat.Format32bppArgb)]
|
||||||
public void WuQuantizer(PixelFormat pixelFormat)
|
public void WuQuantizer(PixelFormat pixelFormat)
|
||||||
{
|
{
|
||||||
using (var bitmap = BitmapFactory.CreateEmpty(400, 400, pixelFormat, Color.White))
|
using var bitmap = BitmapFactory.CreateEmpty(400, 400, pixelFormat, Color.White);
|
||||||
|
using (var graphics = Graphics.FromImage(bitmap.NativeBitmap))
|
||||||
{
|
{
|
||||||
using (var graphics = Graphics.FromImage(bitmap.NativeBitmap))
|
using var pen = new SolidBrush(Color.Blue);
|
||||||
using (var pen = new SolidBrush(Color.Blue))
|
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
||||||
{
|
|
||||||
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
|
||||||
}
|
|
||||||
var quantizer = new WuQuantizer(bitmap);
|
|
||||||
using (var quantizedImage = quantizer.GetQuantizedImage())
|
|
||||||
{
|
|
||||||
quantizedImage.NativeBitmap.Save(@"quantized.png", ImageFormat.Png);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var quantizer = new WuQuantizer(bitmap);
|
||||||
|
using var quantizedImage = quantizer.GetQuantizedImage();
|
||||||
|
quantizedImage.NativeBitmap.Save(@"quantized.png", ImageFormat.Png);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
|
@ -81,45 +76,41 @@ namespace Greenshot.PerformanceTests
|
||||||
[Arguments(PixelFormat.Format32bppArgb)]
|
[Arguments(PixelFormat.Format32bppArgb)]
|
||||||
public void Blur_FastBitmap(PixelFormat pixelFormat)
|
public void Blur_FastBitmap(PixelFormat pixelFormat)
|
||||||
{
|
{
|
||||||
using (var bitmap = BitmapFactory.CreateEmpty(400, 400, pixelFormat, Color.White))
|
using var bitmap = BitmapFactory.CreateEmpty(400, 400, pixelFormat, Color.White);
|
||||||
|
using (var graphics = Graphics.FromImage(bitmap.NativeBitmap))
|
||||||
{
|
{
|
||||||
using (var graphics = Graphics.FromImage(bitmap.NativeBitmap))
|
using var pen = new SolidBrush(Color.Blue);
|
||||||
using (var pen = new SolidBrush(Color.Blue))
|
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
||||||
{
|
|
||||||
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
|
||||||
}
|
|
||||||
bitmap.ApplyBoxBlur(10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitmap.ApplyBoxBlur(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public void Blur_UnmanagedBitmap()
|
public void Blur_UnmanagedBitmap()
|
||||||
{
|
{
|
||||||
using (var unmanagedBitmap = new UnmanagedBitmap<Bgr32>(400, 400))
|
using var unmanagedBitmap = new UnmanagedBitmap<Bgr32>(400, 400);
|
||||||
|
unmanagedBitmap.Span.Fill(new Bgr32 { B = 255, G = 255, R = 255 });
|
||||||
|
using (var graphics = Graphics.FromImage(unmanagedBitmap.NativeBitmap))
|
||||||
{
|
{
|
||||||
unmanagedBitmap.Span.Fill(new Bgr32 { B = 255, G = 255, R = 255 });
|
using var pen = new SolidBrush(Color.Blue);
|
||||||
using (var graphics = Graphics.FromImage(unmanagedBitmap.NativeBitmap))
|
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
||||||
using (var pen = new SolidBrush(Color.Blue))
|
|
||||||
{
|
|
||||||
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
|
||||||
}
|
|
||||||
|
|
||||||
unmanagedBitmap.ApplyBoxBlur(10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unmanagedBitmap.ApplyBoxBlur(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
public void Blur_Old()
|
public void Blur_Old()
|
||||||
{
|
{
|
||||||
using (var bitmap = BitmapFactory.CreateEmpty(400, 400, PixelFormat.Format32bppRgb, Color.White))
|
using var bitmap = BitmapFactory.CreateEmpty(400, 400, PixelFormat.Format32bppRgb, Color.White);
|
||||||
|
using (var graphics = Graphics.FromImage(bitmap.NativeBitmap))
|
||||||
{
|
{
|
||||||
using (var graphics = Graphics.FromImage(bitmap.NativeBitmap))
|
using var pen = new SolidBrush(Color.Blue);
|
||||||
using (var pen = new SolidBrush(Color.Blue))
|
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
||||||
{
|
|
||||||
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
|
||||||
}
|
|
||||||
BoxBlurOld.ApplyOldBoxBlur(bitmap, 10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BoxBlurOld.ApplyOldBoxBlur(bitmap, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BenchmarkDotNet" Version="0.11.5" />
|
<PackageReference Include="BenchmarkDotNet" Version="0.12.0" />
|
||||||
<PackageReference Include="CommandLineParser" Version="2.6.0" />
|
<PackageReference Include="CommandLineParser" Version="2.6.0" />
|
||||||
<PackageReference Include="Microsoft.DotNet.PlatformAbstractions" Version="3.0.0" />
|
<PackageReference Include="Microsoft.DotNet.PlatformAbstractions" Version="3.1.0" />
|
||||||
<PackageReference Include="SharpAvi" Version="2.1.2" />
|
<PackageReference Include="SharpAvi" Version="2.1.2" />
|
||||||
<PackageReference Include="System.Memory" Version="4.5.3" />
|
<PackageReference Include="System.Memory" Version="4.5.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -37,54 +37,54 @@ namespace Greenshot.Tests
|
||||||
[InlineData(PixelFormat.Format32bppArgb)]
|
[InlineData(PixelFormat.Format32bppArgb)]
|
||||||
public void Test_Blur(PixelFormat pixelFormat)
|
public void Test_Blur(PixelFormat pixelFormat)
|
||||||
{
|
{
|
||||||
using (var bitmapNew = BitmapFactory.CreateEmpty(400, 400, pixelFormat, Color.White))
|
using var bitmapNew = BitmapFactory.CreateEmpty(400, 400, pixelFormat, Color.White);
|
||||||
using (var bitmapOld = BitmapFactory.CreateEmpty(400, 400, pixelFormat, Color.White))
|
using var bitmapOld = BitmapFactory.CreateEmpty(400, 400, pixelFormat, Color.White);
|
||||||
|
using (var graphics = Graphics.FromImage(bitmapNew.NativeBitmap))
|
||||||
{
|
{
|
||||||
using (var graphics = Graphics.FromImage(bitmapNew.NativeBitmap))
|
using var pen = new SolidBrush(Color.Blue);
|
||||||
using (var pen = new SolidBrush(Color.Blue))
|
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
||||||
{
|
bitmapNew.ApplyBoxBlur(10);
|
||||||
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
|
||||||
bitmapNew.ApplyBoxBlur(10);
|
|
||||||
}
|
|
||||||
using (var graphics = Graphics.FromImage(bitmapOld.NativeBitmap))
|
|
||||||
using (var pen = new SolidBrush(Color.Blue))
|
|
||||||
{
|
|
||||||
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
|
||||||
BoxBlurOld.ApplyOldBoxBlur(bitmapOld, 10);
|
|
||||||
}
|
|
||||||
bitmapOld.NativeBitmap.Save(@"old.png", ImageFormat.Png);
|
|
||||||
bitmapNew.NativeBitmap.Save(@"new.png", ImageFormat.Png);
|
|
||||||
|
|
||||||
Assert.True(bitmapOld.IsEqualTo(bitmapNew), "New blur doesn't compare to old.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using (var graphics = Graphics.FromImage(bitmapOld.NativeBitmap))
|
||||||
|
{
|
||||||
|
using var pen = new SolidBrush(Color.Blue);
|
||||||
|
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
||||||
|
BoxBlurOld.ApplyOldBoxBlur(bitmapOld, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmapOld.NativeBitmap.Save(@"old.png", ImageFormat.Png);
|
||||||
|
bitmapNew.NativeBitmap.Save(@"new.png", ImageFormat.Png);
|
||||||
|
|
||||||
|
Assert.True(bitmapOld.IsEqualTo(bitmapNew), "New blur doesn't compare to old.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Test_Blur_UnmanagedBitmap()
|
public void Test_Blur_UnmanagedBitmap()
|
||||||
{
|
{
|
||||||
using (var bitmapNew = new UnmanagedBitmap<Bgr32>(400, 400))
|
using var bitmapNew = new UnmanagedBitmap<Bgr32>(400, 400);
|
||||||
using (var bitmapOld = BitmapFactory.CreateEmpty(400, 400, PixelFormat.Format32bppRgb, Color.White))
|
using var bitmapOld = BitmapFactory.CreateEmpty(400, 400, PixelFormat.Format32bppRgb, Color.White);
|
||||||
|
using (var graphics = Graphics.FromImage(bitmapOld.NativeBitmap))
|
||||||
{
|
{
|
||||||
using (var graphics = Graphics.FromImage(bitmapOld.NativeBitmap))
|
using var pen = new SolidBrush(Color.Blue);
|
||||||
using (var pen = new SolidBrush(Color.Blue))
|
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
||||||
{
|
|
||||||
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
|
||||||
}
|
|
||||||
BoxBlurOld.ApplyOldBoxBlur(bitmapOld, 10);
|
|
||||||
bitmapOld.NativeBitmap.Save(@"old.png", ImageFormat.Png);
|
|
||||||
|
|
||||||
bitmapNew.Span.Fill(new Bgr32 { B = 255, G = 255, R = 255 });
|
|
||||||
using (var graphics = Graphics.FromImage(bitmapNew.NativeBitmap))
|
|
||||||
using (var pen = new SolidBrush(Color.Blue))
|
|
||||||
{
|
|
||||||
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
|
||||||
}
|
|
||||||
bitmapNew.ApplyBoxBlur(10);
|
|
||||||
bitmapNew.NativeBitmap.Save(@"new.png", ImageFormat.Png);
|
|
||||||
|
|
||||||
Assert.True(bitmapOld.IsEqualTo(bitmapNew), "New blur doesn't compare to old.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BoxBlurOld.ApplyOldBoxBlur(bitmapOld, 10);
|
||||||
|
bitmapOld.NativeBitmap.Save(@"old.png", ImageFormat.Png);
|
||||||
|
|
||||||
|
bitmapNew.Span.Fill(new Bgr32 { B = 255, G = 255, R = 255 });
|
||||||
|
using (var graphics = Graphics.FromImage(bitmapNew.NativeBitmap))
|
||||||
|
{
|
||||||
|
using var pen = new SolidBrush(Color.Blue);
|
||||||
|
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmapNew.ApplyBoxBlur(10);
|
||||||
|
bitmapNew.NativeBitmap.Save(@"new.png", ImageFormat.Png);
|
||||||
|
|
||||||
|
Assert.True(bitmapOld.IsEqualTo(bitmapNew), "New blur doesn't compare to old.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,12 +86,11 @@ namespace Greenshot.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Test_GdiScreenCapture()
|
public void Test_GdiScreenCapture()
|
||||||
{
|
{
|
||||||
using (var gdiScreenCapture = new GdiScreenCapture())
|
using var gdiScreenCapture = new GdiScreenCapture();
|
||||||
|
gdiScreenCapture.CaptureFrame();
|
||||||
|
using (var bitmap = gdiScreenCapture.CurrentFrameAsBitmap())
|
||||||
{
|
{
|
||||||
gdiScreenCapture.CaptureFrame();
|
Assert.True(bitmap.Width > 0);
|
||||||
using (var bitmap = gdiScreenCapture.CurrentFrameAsBitmap())
|
|
||||||
{
|
|
||||||
Assert.True(bitmap.Width > 0);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Write the capture to a file, for analysis
|
// Write the capture to a file, for analysis
|
||||||
|
@ -100,13 +99,12 @@ namespace Greenshot.Tests
|
||||||
ImageOutput.SaveToStream(bitmap, null, stream, new SurfaceOutputSettings(null, OutputFormats.png));
|
ImageOutput.SaveToStream(bitmap, null, stream, new SurfaceOutputSettings(null, OutputFormats.png));
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
var bitmapSource = gdiScreenCapture.CurrentFrameAsBitmapSource();
|
|
||||||
Assert.True(bitmapSource.Width > 0);
|
|
||||||
|
|
||||||
gdiScreenCapture.CaptureFrame();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var bitmapSource = gdiScreenCapture.CurrentFrameAsBitmapSource();
|
||||||
|
Assert.True(bitmapSource.Width > 0);
|
||||||
|
|
||||||
|
gdiScreenCapture.CaptureFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -144,11 +142,12 @@ namespace Greenshot.Tests
|
||||||
var template = new SimpleTemplate();
|
var template = new SimpleTemplate();
|
||||||
var bitmapSource = template.Apply(capture).ToBitmapSource();
|
var bitmapSource = template.Apply(capture).ToBitmapSource();
|
||||||
using (var outputStream = bitmapSource.ToStream(OutputFormats.png))
|
using (var outputStream = bitmapSource.ToStream(OutputFormats.png))
|
||||||
using (var fileStream = File.Create("Test_CaptureFlow_DwmWindowSource.png"))
|
|
||||||
{
|
{
|
||||||
|
using var fileStream = File.Create("Test_CaptureFlow_DwmWindowSource.png");
|
||||||
outputStream.Seek(0, SeekOrigin.Begin);
|
outputStream.Seek(0, SeekOrigin.Begin);
|
||||||
await outputStream.CopyToAsync(fileStream);
|
await outputStream.CopyToAsync(fileStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.Equal(bounds.Size, bitmapSource.Size());
|
Assert.Equal(bounds.Size, bitmapSource.Size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,26 +158,22 @@ namespace Greenshot.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Test_BitmapCapture()
|
public void Test_BitmapCapture()
|
||||||
{
|
{
|
||||||
using (var screenBitmapCapture = new BitmapScreenCapture())
|
using var screenBitmapCapture = new BitmapScreenCapture();
|
||||||
|
screenBitmapCapture.CaptureFrame();
|
||||||
|
|
||||||
|
Assert.NotNull(screenBitmapCapture.CurrentFrameAsBitmap());
|
||||||
|
|
||||||
|
var testFile1 = Path.Combine(Path.GetTempPath(), @"test-bitmap.png");
|
||||||
|
screenBitmapCapture.CurrentFrameAsBitmap().NativeBitmap.Save(testFile1, ImageFormat.Png);
|
||||||
|
|
||||||
|
var testFile2 = Path.Combine(Path.GetTempPath(), @"test-bitmapsource.png");
|
||||||
|
using var fileStream = new FileStream(testFile2, FileMode.Create);
|
||||||
|
var encoder = new PngBitmapEncoder
|
||||||
{
|
{
|
||||||
screenBitmapCapture.CaptureFrame();
|
Interlace = PngInterlaceOption.Off
|
||||||
|
};
|
||||||
Assert.NotNull(screenBitmapCapture.CurrentFrameAsBitmap());
|
encoder.Frames.Add(BitmapFrame.Create(screenBitmapCapture.CurrentFrameAsBitmap().NativeBitmapSource));
|
||||||
|
encoder.Save(fileStream);
|
||||||
var testFile1 = Path.Combine(Path.GetTempPath(), @"test-bitmap.png");
|
|
||||||
screenBitmapCapture.CurrentFrameAsBitmap().NativeBitmap.Save(testFile1, ImageFormat.Png);
|
|
||||||
|
|
||||||
var testFile2 = Path.Combine(Path.GetTempPath(), @"test-bitmapsource.png");
|
|
||||||
using (var fileStream = new FileStream(testFile2, FileMode.Create))
|
|
||||||
{
|
|
||||||
var encoder = new PngBitmapEncoder
|
|
||||||
{
|
|
||||||
Interlace = PngInterlaceOption.Off
|
|
||||||
};
|
|
||||||
encoder.Frames.Add(BitmapFrame.Create(screenBitmapCapture.CurrentFrameAsBitmap().NativeBitmapSource));
|
|
||||||
encoder.Save(fileStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,27 +19,27 @@ namespace Greenshot.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TestBlur()
|
public void TestBlur()
|
||||||
{
|
{
|
||||||
using (var bitmap1 = BitmapFactory.CreateEmpty(400, 400, PixelFormat.Format24bppRgb, Color.White))
|
using var bitmap1 = BitmapFactory.CreateEmpty(400, 400, PixelFormat.Format24bppRgb, Color.White);
|
||||||
using (var bitmap2 = BitmapFactory.CreateEmpty(400, 400, PixelFormat.Format24bppRgb, Color.White))
|
using var bitmap2 = BitmapFactory.CreateEmpty(400, 400, PixelFormat.Format24bppRgb, Color.White);
|
||||||
|
using (var graphics = Graphics.FromImage(bitmap1.NativeBitmap))
|
||||||
{
|
{
|
||||||
using (var graphics = Graphics.FromImage(bitmap1.NativeBitmap))
|
using var pen = new SolidBrush(Color.Blue);
|
||||||
using (var pen = new SolidBrush(Color.Blue))
|
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
||||||
{
|
|
||||||
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
|
||||||
}
|
|
||||||
bitmap1.NativeBitmap.Save("bitmap0.png", ImageFormat.Png);
|
|
||||||
bitmap1.ApplyBoxBlur(10);
|
|
||||||
bitmap1.NativeBitmap.Save("bitmap1.png", ImageFormat.Png);
|
|
||||||
|
|
||||||
using (var graphics = Graphics.FromImage(bitmap2.NativeBitmap))
|
|
||||||
using (var pen = new SolidBrush(Color.Blue))
|
|
||||||
{
|
|
||||||
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
|
||||||
}
|
|
||||||
BoxBlurOld.ApplyOldBoxBlur(bitmap2, 10);
|
|
||||||
bitmap2.NativeBitmap.Save("bitmap2.png", ImageFormat.Png);
|
|
||||||
Assert.True(bitmap1.IsEqualTo(bitmap2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitmap1.NativeBitmap.Save("bitmap0.png", ImageFormat.Png);
|
||||||
|
bitmap1.ApplyBoxBlur(10);
|
||||||
|
bitmap1.NativeBitmap.Save("bitmap1.png", ImageFormat.Png);
|
||||||
|
|
||||||
|
using (var graphics = Graphics.FromImage(bitmap2.NativeBitmap))
|
||||||
|
{
|
||||||
|
using var pen = new SolidBrush(Color.Blue);
|
||||||
|
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
|
||||||
|
}
|
||||||
|
|
||||||
|
BoxBlurOld.ApplyOldBoxBlur(bitmap2, 10);
|
||||||
|
bitmap2.NativeBitmap.Save("bitmap2.png", ImageFormat.Png);
|
||||||
|
Assert.True(bitmap1.IsEqualTo(bitmap2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BenchmarkDotNet" Version="0.11.5" />
|
<PackageReference Include="BenchmarkDotNet" Version="0.12.0" />
|
||||||
<PackageReference Include="CommandLineParser" Version="2.6.0" />
|
<PackageReference Include="CommandLineParser" Version="2.6.0" />
|
||||||
<PackageReference Include="Dapplo.Log.XUnit" Version="1.3.26" />
|
<PackageReference Include="Dapplo.Log.XUnit" Version="1.3.26" />
|
||||||
<PackageReference Include="Dapplo.Windows" Version="0.11.6" />
|
<PackageReference Include="Dapplo.Windows" Version="0.11.6" />
|
||||||
|
|
|
@ -18,10 +18,8 @@ namespace Greenshot.Tests.Implementation
|
||||||
public static void ApplyOldBoxBlur(this IBitmapWithNativeSupport destinationBitmap, int range)
|
public static void ApplyOldBoxBlur(this IBitmapWithNativeSupport destinationBitmap, int range)
|
||||||
{
|
{
|
||||||
// We only need one fastbitmap as we use it as source and target (the reading is done for one line H/V, writing after "parsing" one line H/V)
|
// We only need one fastbitmap as we use it as source and target (the reading is done for one line H/V, writing after "parsing" one line H/V)
|
||||||
using (var fastBitmap = FastBitmapFactory.Create(destinationBitmap))
|
using var fastBitmap = FastBitmapFactory.Create(destinationBitmap);
|
||||||
{
|
fastBitmap.ApplyOldBoxBlur(range);
|
||||||
fastBitmap.ApplyOldBoxBlur(range);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue