Repository: dajuric/dot-imaging
Branch: master
Commit: 27d39aad31a5
Files: 91
Total size: 432.8 KB
Directory structure:
gitextract_pvk6qki_/
├── .gitignore
├── Deploy/
│ ├── Licence.txt
│ ├── Logo/
│ │ └── DotImaging.pptx
│ └── Nuget/
│ └── Push.ps1
├── Directory.Build.props
├── DotImaging.sln
├── README.md
├── Samples/
│ ├── Sample.Basic/
│ │ ├── Program.cs
│ │ └── Sample.Basic.csproj
│ ├── Sample.Capture/
│ │ ├── Program.cs
│ │ └── Sample.Capture.csproj
│ ├── Sample.CaptureAndRecord/
│ │ ├── Program.cs
│ │ └── Sample.CaptureAndRecord.csproj
│ ├── Sample.ImageExtractor/
│ │ ├── Program.cs
│ │ └── Sample.ImageExtractor.csproj
│ ├── Sample.Interop/
│ │ ├── Program.cs
│ │ └── Sample.Interop.csproj
│ ├── Sample.MultipleCameraCapture/
│ │ ├── Program.cs
│ │ └── Sample.MultipleCameraCapture.csproj
│ ├── Sample.UI/
│ │ ├── Program.cs
│ │ └── Sample.UI.csproj
│ └── Sample.VideoStreaming/
│ ├── Program.cs
│ └── Sample.VideoStreaming.csproj
└── Source/
├── BitmapInterop/
│ ├── .nuSpec/
│ │ └── readmeImage.Bitmap.txt
│ ├── BmpExtensions/
│ │ ├── BitmapConversion.cs
│ │ ├── BmpIO.cs
│ │ └── ColorConversion.cs
│ └── Image.BitmapInterop.csproj
├── IO/
│ ├── .nuSpec/
│ │ └── readmeIO.txt
│ ├── Base/
│ │ ├── Abstract/
│ │ │ ├── ImageStream.cs
│ │ │ ├── ImageStreamReader.cs
│ │ │ └── ImageStreamWriter.cs
│ │ └── CvInvoke.cs
│ ├── IO.csproj
│ ├── ImageIO.cs
│ ├── Readers/
│ │ ├── CameraCapture.cs
│ │ ├── FileCapture.cs
│ │ ├── ImageDirectoryCapture.cs
│ │ └── VideoCaptureBase.cs
│ ├── Utilities/
│ │ ├── NaturalSortComparer.cs
│ │ └── PathExtensions.cs
│ ├── Writers/
│ │ ├── ImageWriterExtension.cs
│ │ └── VideoWriter.cs
│ └── runtimes/
│ └── ubuntu.16.04-x64/
│ ├── libopencv_core.so.2.4
│ ├── libopencv_highgui.so.2.4
│ └── libopencv_video.so.2.4
├── IO.Web/
│ ├── .nuSpec/
│ │ └── readmeIO.Web.txt
│ ├── IO.Web.csproj
│ ├── NamedPipeExtensions.cs
│ └── WebImageExtensions.cs
├── Image/
│ ├── .nuSpec/
│ │ └── readmeImage.txt
│ ├── ColorTypeConversions/
│ │ ├── ColorInfo.cs
│ │ ├── ColorSpaces/
│ │ │ ├── Bgr.cs
│ │ │ ├── Bgra.cs
│ │ │ ├── Gray.cs
│ │ │ ├── Hsv.cs
│ │ │ ├── IColor.cs
│ │ │ └── Rgb.cs
│ │ └── Converters/
│ │ └── ColorConversionExtensions.cs
│ ├── Extensions/
│ │ ├── BasicExtensions.cs
│ │ ├── ChannelMerger.cs
│ │ ├── ChannelSplitter.cs
│ │ ├── Convert.cs
│ │ ├── Copy.cs
│ │ ├── ImageFlipping.cs
│ │ └── SpatialConvolution.cs
│ ├── Image.csproj
│ ├── Interop/
│ │ ├── CvMat.cs
│ │ └── IplImage.cs
│ ├── Linq/
│ │ └── ImagingLinq.cs
│ ├── ParallelLauncher.cs
│ ├── Slice2D.cs
│ └── Unmanaged/
│ ├── IImage.cs
│ └── Image'1.cs
├── Primitives2D/
│ ├── Box2D/
│ │ └── Box2D.cs
│ ├── Circle/
│ │ ├── Circle.cs
│ │ └── CircleF.cs
│ ├── Ellipse/
│ │ └── Ellipse.cs
│ ├── Point/
│ │ ├── Point'1.cs
│ │ └── PointExtensions.cs
│ ├── Primitives2D.csproj
│ ├── Rectangle/
│ │ └── RectangleExtensions.cs
│ └── Size/
│ └── SizeExtensions.cs
└── UI.Image/
├── .nuSpec/
│ └── readmeUI.Image.txt
├── Base/
│ ├── CvCoreInvoke.cs
│ └── CvInvoke.cs
├── Drawing.cs
├── ImageUI.cs
├── UI.Image.csproj
└── runtimes/
└── ubuntu.16.04-x64/
├── libopencv_core.so.2.4
└── libopencv_highgui.so.2.4
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
build/
bld/
[Bb]in/
[Oo]bj/
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
!packages/*/build/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
#NUNIT
*.VisualState.xml
TestResult.xml
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding addin-in
.JustCode
# TeamCity is a build add-in
# NuGet
*.nuget.props
*.nuget.targets
**/packages/*
!**/packages/build/
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
/Deploy/Nuget/NuGet.exe
================================================
FILE: Deploy/Licence.txt
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: Deploy/Nuget/Push.ps1
================================================
#--references:
# list files: https://medium.com/@victorleungtw/replace-text-in-xml-files-with-powershell-504d3e37a058
timeout /T 5
Write-Host
Write-Host Pushing packages:
$files = @(Get-ChildItem *.nupkg -Recurse)
foreach($f in $files)
{
Write-Host $f
$cmd = './nuget push "$f" -source https://www.nuget.org/api/v2/package'
iex $cmd
}
Write-Host
#pause
================================================
FILE: Directory.Build.props
================================================
netcoreapp2.2
preview
bin\
false
================================================
FILE: DotImaging.sln
================================================
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29102.190
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{80058A54-6223-480C-AA19-F99E7AE593F3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{05BDC895-7F7B-4B6F-8D69-E7916837092D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Deploy", "Deploy", "{80FC5EA1-3478-4E7F-8B05-190DF6750EA4}"
ProjectSection(SolutionItems) = preProject
Deploy\Licence.txt = Deploy\Licence.txt
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Logo", "Logo", "{817B040E-5F27-4ACD-B1E4-F46452668A0E}"
ProjectSection(SolutionItems) = preProject
Deploy\Logo\DotImaging.pptx = Deploy\Logo\DotImaging.pptx
Deploy\Logo\logo-big.png = Deploy\Logo\logo-big.png
Deploy\Logo\logo-small.png = Deploy\Logo\logo-small.png
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Image.BitmapInterop", "Source\BitmapInterop\Image.BitmapInterop.csproj", "{CE222A84-B03B-4053-8BA4-F237063382F2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Image", "Source\Image\Image.csproj", "{3CF8F155-3DA1-4529-9B28-D409E86ED4E2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IO", "Source\IO\IO.csproj", "{ED70A44E-9443-4A28-9B95-31299F8B2D08}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IO.Web", "Source\IO.Web\IO.Web.csproj", "{B8404D66-B64E-43E0-9653-35FC6782072F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.VideoStreaming", "Samples\Sample.VideoStreaming\Sample.VideoStreaming.csproj", "{CB088D8A-3438-4DB9-87C2-99425FE27F07}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Basic", "Samples\Sample.Basic\Sample.Basic.csproj", "{5F5FE08B-37C1-4C62-BB1A-DFFF61B3516A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Interop", "Samples\Sample.Interop\Sample.Interop.csproj", "{E4ED626D-359B-493C-A72E-3738A5353D1B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Capture", "Samples\Sample.Capture\Sample.Capture.csproj", "{D0C18418-5282-4BA8-ABF7-CC2A9A179517}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.CaptureAndRecord", "Samples\Sample.CaptureAndRecord\Sample.CaptureAndRecord.csproj", "{867ED0BD-FBFB-4C0C-A34B-D71361874AA0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.ImageExtractor", "Samples\Sample.ImageExtractor\Sample.ImageExtractor.csproj", "{55FF1668-9501-4007-84D8-26EF860F0D0D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.MultipleCameraCapture", "Samples\Sample.MultipleCameraCapture\Sample.MultipleCameraCapture.csproj", "{C30A145E-02FB-49B4-8F3E-6673AF9D121A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NuGet", "NuGet", "{44744CCA-2769-4607-AC90-78B6A11A2E77}"
ProjectSection(SolutionItems) = preProject
Deploy\Nuget\Push.ps1 = Deploy\Nuget\Push.ps1
Deploy\Nuget\UpdatePackageVersion.ps1 = Deploy\Nuget\UpdatePackageVersion.ps1
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UI.Image", "Source\UI.Image\UI.Image.csproj", "{F021F056-59F7-4C49-9F0F-3BE6721F920F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7C2B92C2-DD93-47F5-8ADA-BF21086EDCDD}"
ProjectSection(SolutionItems) = preProject
Directory.Build.props = Directory.Build.props
README.md = README.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Primitives2D", "Source\Primitives2D\Primitives2D.csproj", "{CF955F14-669D-4802-A3A3-0CDA7601205E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CE222A84-B03B-4053-8BA4-F237063382F2}.Debug|x64.ActiveCfg = Debug|Any CPU
{CE222A84-B03B-4053-8BA4-F237063382F2}.Debug|x64.Build.0 = Debug|Any CPU
{CE222A84-B03B-4053-8BA4-F237063382F2}.Release|x64.ActiveCfg = Release|Any CPU
{CE222A84-B03B-4053-8BA4-F237063382F2}.Release|x64.Build.0 = Release|Any CPU
{3CF8F155-3DA1-4529-9B28-D409E86ED4E2}.Debug|x64.ActiveCfg = Debug|Any CPU
{3CF8F155-3DA1-4529-9B28-D409E86ED4E2}.Debug|x64.Build.0 = Debug|Any CPU
{3CF8F155-3DA1-4529-9B28-D409E86ED4E2}.Release|x64.ActiveCfg = Release|Any CPU
{3CF8F155-3DA1-4529-9B28-D409E86ED4E2}.Release|x64.Build.0 = Release|Any CPU
{ED70A44E-9443-4A28-9B95-31299F8B2D08}.Debug|x64.ActiveCfg = Debug|x64
{ED70A44E-9443-4A28-9B95-31299F8B2D08}.Debug|x64.Build.0 = Debug|x64
{ED70A44E-9443-4A28-9B95-31299F8B2D08}.Release|x64.ActiveCfg = Release|x64
{ED70A44E-9443-4A28-9B95-31299F8B2D08}.Release|x64.Build.0 = Release|x64
{B8404D66-B64E-43E0-9653-35FC6782072F}.Debug|x64.ActiveCfg = Debug|Any CPU
{B8404D66-B64E-43E0-9653-35FC6782072F}.Debug|x64.Build.0 = Debug|Any CPU
{B8404D66-B64E-43E0-9653-35FC6782072F}.Release|x64.ActiveCfg = Release|Any CPU
{B8404D66-B64E-43E0-9653-35FC6782072F}.Release|x64.Build.0 = Release|Any CPU
{CB088D8A-3438-4DB9-87C2-99425FE27F07}.Debug|x64.ActiveCfg = Debug|x64
{CB088D8A-3438-4DB9-87C2-99425FE27F07}.Debug|x64.Build.0 = Debug|x64
{CB088D8A-3438-4DB9-87C2-99425FE27F07}.Release|x64.ActiveCfg = Release|x64
{CB088D8A-3438-4DB9-87C2-99425FE27F07}.Release|x64.Build.0 = Release|x64
{5F5FE08B-37C1-4C62-BB1A-DFFF61B3516A}.Debug|x64.ActiveCfg = Debug|x64
{5F5FE08B-37C1-4C62-BB1A-DFFF61B3516A}.Debug|x64.Build.0 = Debug|x64
{5F5FE08B-37C1-4C62-BB1A-DFFF61B3516A}.Release|x64.ActiveCfg = Release|x64
{5F5FE08B-37C1-4C62-BB1A-DFFF61B3516A}.Release|x64.Build.0 = Release|x64
{E4ED626D-359B-493C-A72E-3738A5353D1B}.Debug|x64.ActiveCfg = Debug|x64
{E4ED626D-359B-493C-A72E-3738A5353D1B}.Debug|x64.Build.0 = Debug|x64
{E4ED626D-359B-493C-A72E-3738A5353D1B}.Release|x64.ActiveCfg = Release|x64
{E4ED626D-359B-493C-A72E-3738A5353D1B}.Release|x64.Build.0 = Release|x64
{D0C18418-5282-4BA8-ABF7-CC2A9A179517}.Debug|x64.ActiveCfg = Debug|x64
{D0C18418-5282-4BA8-ABF7-CC2A9A179517}.Debug|x64.Build.0 = Debug|x64
{D0C18418-5282-4BA8-ABF7-CC2A9A179517}.Release|x64.ActiveCfg = Release|x64
{D0C18418-5282-4BA8-ABF7-CC2A9A179517}.Release|x64.Build.0 = Release|x64
{867ED0BD-FBFB-4C0C-A34B-D71361874AA0}.Debug|x64.ActiveCfg = Debug|x64
{867ED0BD-FBFB-4C0C-A34B-D71361874AA0}.Debug|x64.Build.0 = Debug|x64
{867ED0BD-FBFB-4C0C-A34B-D71361874AA0}.Release|x64.ActiveCfg = Release|x64
{867ED0BD-FBFB-4C0C-A34B-D71361874AA0}.Release|x64.Build.0 = Release|x64
{55FF1668-9501-4007-84D8-26EF860F0D0D}.Debug|x64.ActiveCfg = Debug|x64
{55FF1668-9501-4007-84D8-26EF860F0D0D}.Debug|x64.Build.0 = Debug|x64
{55FF1668-9501-4007-84D8-26EF860F0D0D}.Release|x64.ActiveCfg = Release|x64
{55FF1668-9501-4007-84D8-26EF860F0D0D}.Release|x64.Build.0 = Release|x64
{C30A145E-02FB-49B4-8F3E-6673AF9D121A}.Debug|x64.ActiveCfg = Debug|x64
{C30A145E-02FB-49B4-8F3E-6673AF9D121A}.Debug|x64.Build.0 = Debug|x64
{C30A145E-02FB-49B4-8F3E-6673AF9D121A}.Release|x64.ActiveCfg = Release|x64
{C30A145E-02FB-49B4-8F3E-6673AF9D121A}.Release|x64.Build.0 = Release|x64
{F021F056-59F7-4C49-9F0F-3BE6721F920F}.Debug|x64.ActiveCfg = Debug|x64
{F021F056-59F7-4C49-9F0F-3BE6721F920F}.Debug|x64.Build.0 = Debug|x64
{F021F056-59F7-4C49-9F0F-3BE6721F920F}.Release|x64.ActiveCfg = Release|x64
{F021F056-59F7-4C49-9F0F-3BE6721F920F}.Release|x64.Build.0 = Release|x64
{CF955F14-669D-4802-A3A3-0CDA7601205E}.Debug|x64.ActiveCfg = Debug|Any CPU
{CF955F14-669D-4802-A3A3-0CDA7601205E}.Debug|x64.Build.0 = Debug|Any CPU
{CF955F14-669D-4802-A3A3-0CDA7601205E}.Release|x64.ActiveCfg = Release|Any CPU
{CF955F14-669D-4802-A3A3-0CDA7601205E}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{817B040E-5F27-4ACD-B1E4-F46452668A0E} = {80FC5EA1-3478-4E7F-8B05-190DF6750EA4}
{CE222A84-B03B-4053-8BA4-F237063382F2} = {80058A54-6223-480C-AA19-F99E7AE593F3}
{3CF8F155-3DA1-4529-9B28-D409E86ED4E2} = {80058A54-6223-480C-AA19-F99E7AE593F3}
{ED70A44E-9443-4A28-9B95-31299F8B2D08} = {80058A54-6223-480C-AA19-F99E7AE593F3}
{B8404D66-B64E-43E0-9653-35FC6782072F} = {80058A54-6223-480C-AA19-F99E7AE593F3}
{CB088D8A-3438-4DB9-87C2-99425FE27F07} = {05BDC895-7F7B-4B6F-8D69-E7916837092D}
{5F5FE08B-37C1-4C62-BB1A-DFFF61B3516A} = {05BDC895-7F7B-4B6F-8D69-E7916837092D}
{E4ED626D-359B-493C-A72E-3738A5353D1B} = {05BDC895-7F7B-4B6F-8D69-E7916837092D}
{D0C18418-5282-4BA8-ABF7-CC2A9A179517} = {05BDC895-7F7B-4B6F-8D69-E7916837092D}
{867ED0BD-FBFB-4C0C-A34B-D71361874AA0} = {05BDC895-7F7B-4B6F-8D69-E7916837092D}
{55FF1668-9501-4007-84D8-26EF860F0D0D} = {05BDC895-7F7B-4B6F-8D69-E7916837092D}
{C30A145E-02FB-49B4-8F3E-6673AF9D121A} = {05BDC895-7F7B-4B6F-8D69-E7916837092D}
{44744CCA-2769-4607-AC90-78B6A11A2E77} = {80FC5EA1-3478-4E7F-8B05-190DF6750EA4}
{F021F056-59F7-4C49-9F0F-3BE6721F920F} = {80058A54-6223-480C-AA19-F99E7AE593F3}
{CF955F14-669D-4802-A3A3-0CDA7601205E} = {80058A54-6223-480C-AA19-F99E7AE593F3}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DEAC2BC6-C697-4361-9909-CF7055FE9B05}
EndGlobalSection
EndGlobal
================================================
FILE: README.md
================================================
**DotImaging** - .NET array as imaging object
The framework sets focus on .NET native array as primary imaging object, offers extensibility support via extensions, and provides unified platform-abstract imaging IO API.
## News
+ 5.2.0 version came out (19/02/2019)
+ Image enchacement library for DotImaging: DotDevignetting !
## So why DotImaging ?
+ Image as native .NET 2D array
+ portable*
+ lightweight
+ extensions, extensions, extensions....
*IO and Drawing assemlies depend on OpenCV
## Libraries / NuGet packages
###### Core
+
.NET image array extensions. Color and depth conversions. Slim unmanaged structure for fast pixel manipulation.
> **Tutorial:** Portable Generic Image
``` csharp
//convert to grayscale and flip
Bgr[,] image = ImageIO.LoadColor("sample.jpg"); //IO package
Gray[,] grayIm = image.ToGray()
.Flip(FlipDirection.Horizontal);
//get the modified blue channel
var modifiedImage = image.AsEnumerable()
.Select(x => x.B / 2)
.ToArray2D(image.Size());
```
+
Portable 2D drawing primitives (Extensions for Point, Size, Rectangle and additional primitives)
###### IO
+
A unified API for IO image access (camera, file, image directory). Portable image loading/saving.
> **Tutorial:** Portable Imaging IO
``` csharp
var reader = new FileCapture("sample.mp4");
reader.Open();
Bgr[,] frame = null;
while(true)
{
reader.ReadTo(ref frame);
if (frame == null)
break;
frame.Show(scaleForm: true); //UI package
}
reader.Close();
```
+
Image or video download/streaming (direct video link or Youtube links).
``` csharp
//------get an image from the Web
new Uri("http://vignette3.wikia.nocookie.net/disney/images/5/5d/Lena_headey_.jpg")
.GetBytes().DecodeAsColorImage().Show(); //(Show - UI package)
//------stream a video from Youtube
var pipeName = new Uri("https://www.youtube.com/watch?v=Vpg9yizPP_g").NamedPipeFromYoutubeUri(); //Youtube
var reader = new FileCapture(String.Format(@"\\.\pipe\{0}", pipeName)) //IO package
//... (regular stream reading - see IO package sample)
```
###### Interoperability
+
Interoperability extensions between .NET array and System.Drawing.Bitmap.
``` csharp
var image = new Gray[240, 320];
var bmp = image.ToBitmap(); //to Bitmap
var imageFromBmp = bmp.ToArray() as Bgr[,]; //from Bitmap
```
###### Extensions
+
Image preview dialog and drawing.
``` csharp
Bgr[,] image = new Bgr[480, 640];
image.Show(); //show image (non-blocking)
image.ShowDialog(); //show image (blocking)
//draw something
image.Draw(new Rectangle(50, 50, 200, 100), Bgr.Red, -1);
image.Draw(new Circle(50, 50, 25), Bgr.Blue, 5);
```
## Getting started
+ Just pick what you need. An appropriate readme file will be shown upon selected NuGet package installation.
+ Samples
## Final word
If you like the project please **star it** in order to help to spread the word. That way you will make the framework more significant and in the same time you will motivate me to improve it, so the benefit is mutual.
================================================
FILE: Samples/Sample.Basic/Program.cs
================================================
using DotImaging;
using System.Drawing;
using System;
using System.IO;
namespace BasicImageOperations
{
static class Program
{
static void Main()
{
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + ";runtimes/win10-x64/"); //only needed if projects are directly referenced
//load from the Web
var image = new Uri("http://vignette3.wikia.nocookie.net/disney/images/5/5d/Lena_headey_.jpg")
.GetBytes()
.DecodeAsColorImage();
//show image
image.Show("New Lena");
//draw something
image.DrawRectangle(new Rectangle(50, 50, 200, 100), Bgr.Red, -1);
image.DrawText("Hello world!", DotImaging.Font.Big, new Point(10, 100), Bgr.White);
//save and load
image.Save("out.png");
ImageIO.LoadColor("out.png").ShowDialog("Saved image", autoSize: true);
}
}
}
================================================
FILE: Samples/Sample.Basic/Sample.Basic.csproj
================================================
netcoreapp2.2
Exe
x64
================================================
FILE: Samples/Sample.Capture/Program.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using DotImaging;
using System;
using System.IO;
namespace Capture
{
class Program
{
[STAThread]
static void Main()
{
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + ";runtimes/win10-x64/"); //only needed if projects are directly referenced
Console.WriteLine("Press ESC to stop playing");
//var reader = new CameraCapture(0); //capture from camera
//(reader as CameraCapture).FrameSize = new Size(640, 480);
var reader = new FileCapture(Path.Combine(getResourceDir(), "Welcome.mp4")); //capture from video
//var reader = new ImageDirectoryCapture(Path.Combine(getResourceDir(), "Sequence"), "*.jpg");
reader.Open();
Bgr[,] frame = null;
do
{
reader.ReadTo(ref frame);
if (frame == null)
break;
frame.Show(autoSize: true);
}
while (!(Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape));
reader.Dispose();
ImageUI.CloseAll();
}
private static string getResourceDir()
{
return Path.Combine(new DirectoryInfo(Environment.CurrentDirectory).FullName, "Resources");
}
}
}
================================================
FILE: Samples/Sample.Capture/Sample.Capture.csproj
================================================
netcoreapp2.2
x64
DotImaging
bin\
Exe
Always
================================================
FILE: Samples/Sample.CaptureAndRecord/Program.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2016
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using DotImaging;
using System;
using System.IO;
namespace CaptureAndRecording
{
static class Program
{
static void Main()
{
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + ";runtimes/win10-x64/"); //only needed if projects are directly referenced
//var reader = new CameraCapture(0); //capture from camera
var reader = new FileCapture(Path.Combine(getResourceDir(), "Welcome.mp4"));
reader.Open();
var writer = new VideoWriter(@"output.avi", reader.FrameSize, /*reader.FrameRate does not work Cameras*/ 30); //TODO: bug: FPS does not work for cameras
writer.Open();
Bgr[,] frame = null;
do
{
reader.ReadTo(ref frame);
if (frame == null)
break;
using (var uFrame = frame.Lock())
{ writer.Write(uFrame); }
frame.Show(autoSize: true);
}
while (!(Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape));
reader.Dispose();
writer.Dispose();
ImageUI.CloseAll();
}
private static string getResourceDir()
{
return Path.Combine(new DirectoryInfo(Environment.CurrentDirectory).FullName, "Resources");
}
}
}
================================================
FILE: Samples/Sample.CaptureAndRecord/Sample.CaptureAndRecord.csproj
================================================
netcoreapp2.2
x64
DotImaging
bin\
Exe
Always
================================================
FILE: Samples/Sample.ImageExtractor/Program.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2016
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using DotImaging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace ImageExtractor
{
class Program
{
static void Main(string[] args)
{
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + ";runtimes/win10-x64/"); //only needed if projects are directly referenced
//emulate input args
string fileMask = Path.Combine(getResourceDir(), "Welcome.mp4");
if (args.Length == 1)
fileMask = args[0];
var fileNames = enumerateFiles(fileMask);
foreach (var fileName in fileNames)
{
extractVideo(fileName);
}
}
private static void extractVideo(string fileName)
{
//get output dir (same as file name and in the same folder as video)
var fileInfo = new FileInfo(fileName);
var fileNameNoExt = fileInfo.Name.Replace(fileInfo.Extension, String.Empty);
string outputDir = Path.Combine(fileInfo.DirectoryName, fileNameNoExt);
//open video
var reader = new FileCapture(fileName);
reader.Open();
reader.SaveFrames(outputDir, "{0}.jpg", p => Console.Write($"\rExtracting: {(int)(p * 100)} %"));
ImageUI.CloseAll();
}
private static IEnumerable enumerateFiles(string fileMask)
{
var pathDelimiter = Path.DirectorySeparatorChar;
fileMask = normalizePathDelimiters(fileMask, pathDelimiter.ToString());
string fileMaskWithoutPath = fileMask.Split(pathDelimiter).Last();
string path = fileMask.Replace(fileMaskWithoutPath, String.Empty);
var fileNames = Directory.EnumerateFiles(path, fileMaskWithoutPath);
return fileNames;
}
private static string getResourceDir()
{
return Path.Combine(new DirectoryInfo(Environment.CurrentDirectory).FullName, "Resources");
}
private static string normalizePathDelimiters(string path, string normalizedDelimiter) //TODO: replace with extension when available
{
return path.Replace("//", normalizedDelimiter)
.Replace(@"\", normalizedDelimiter)
.Replace(@"\\", normalizedDelimiter)
.Replace(@"/", normalizedDelimiter);
}
}
}
================================================
FILE: Samples/Sample.ImageExtractor/Sample.ImageExtractor.csproj
================================================
netcoreapp2.2
x64
DotImaging
bin\
Exe
Always
================================================
FILE: Samples/Sample.Interop/Program.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2016
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using DotImaging;
using System;
using System.IO;
namespace GenericImageInteropDemo
{
class Program
{
static void Main(string[] args)
{
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + ";runtimes/win10-x64/"); //only needed if projects are directly referenced
var img = new Bgr[480, 640];
//***********************************************************************************************************************************************************************
Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("********* TColor[,] <=> Image<> conversions (built-in) ****************"); Console.ResetColor();
//to Image<>
Image> lockedImg = img.Lock();
//from Image<>
var arr = lockedImg.Clone();
//***********************************************************************************************************************************************************************
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("********* Image<,> <=> OpenCV conversions (built-in) ****************"); Console.ResetColor();
//to IplImage
IplImage iplImage;
using (var uImg = img.Lock())
{
iplImage = uImg.AsCvIplImage(); //data is shared
}
//from IplImage
var imgFromIpl = iplImage.AsImage();
//***********************************************************************************************************************************************************************
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("*********** Image<,> <=> Bitmap conversions (BitmapInterop) ****************"); Console.ResetColor();
//to Bitmap
var bmp = img.ToBitmap();
//from Bitmap
var imgFromBmp = bmp.ToImage>();
}
}
}
================================================
FILE: Samples/Sample.Interop/Sample.Interop.csproj
================================================
netcoreapp2.2
x64
DotImaging
bin\
Exe
================================================
FILE: Samples/Sample.MultipleCameraCapture/Program.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2016
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using DotImaging;
using System.Collections.Generic;
using System.IO;
namespace MultipleCameraCapture
{
static class Program
{
static void Main()
{
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + ";runtimes/win10-x64/"); //only needed if projects are directly referenced
Console.WriteLine("Press ESC to stop playing");
List captures = new List();
var cameraCount = CameraCapture.CameraCount;
if (cameraCount == 0)
{
Console.WriteLine("No camera device is present.");
return;
}
//initialize
for (int camIdx = 0; camIdx < cameraCount; camIdx++)
{
var cap = new CameraCapture(camIdx);
cap.Open();
captures.Add(cap);
}
//grab frames
Bgr[][,] frames = new Bgr[cameraCount][,];
do
{
for (int camIdx = 0; camIdx < cameraCount; camIdx++)
{
captures[camIdx].ReadTo(ref frames[camIdx]);
if (frames[camIdx] == null)
break;
frames[camIdx].Show(String.Format("Camera {0}", camIdx), autoSize: true);
}
}
while (!(Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape));
//dispose
captures.ForEach(x => x.Dispose());
ImageUI.CloseAll();
}
}
}
================================================
FILE: Samples/Sample.MultipleCameraCapture/Sample.MultipleCameraCapture.csproj
================================================
netcoreapp2.2
x64
DotImaging
bin\
Exe
================================================
FILE: Samples/Sample.UI/Program.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2016
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using DotImaging;
using DotImaging.Linq;
using System.Linq;
using System;
using System.Threading;
using System.IO;
namespace UIDemo
{
class Program
{
[STAThread]
static void Main(string[] args)
{
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + ";runtimes/win10-x64/"); //only needed if projects are directly referenced
//select color
Bgr[,] image = new Bgr[480, 640];
Hsv color = UI.PickColor(Bgr.Red).ToHsv();
//select mask
Gray[,] mask = image.GetMask();
if (mask.AsEnumerable().Sum(x => x.Intensity) == 0) //if the mask is empty
mask.SetValue>(Byte.MaxValue);
//increase saturation incrementally
for (int s = 0; s <= Byte.MaxValue; s++)
{
color.S = (byte)s;
image.SetValue>(color.ToBgr(), mask);
image.Show(scaleForm: true);
((double)s / Byte.MaxValue).Progress(message: "Changing saturation");
Thread.Sleep(50);
}
//save last image
string fileName = UI.SaveImage();
if (fileName != null) image.Save(fileName);
//close all
UI.CloseAll();
}
}
}
================================================
FILE: Samples/Sample.UI/Sample.UI.csproj
================================================
net47
DotImaging
bin\
Exe
================================================
FILE: Samples/Sample.VideoStreaming/Program.cs
================================================
using DotImaging;
using System;
using System.Diagnostics;
using System.IO;
namespace YoutubeStreaming
{
class Program
{
public static void Main()
{
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + ";runtimes/win10-x64/"); //only needed if projects are directly referenced
var sourceName = String.Empty;
//video over pipe (direct link and Youtube) (do not support seek)
//var pipeName = new Uri("http://trailers.divx.com/divx_prod/divx_plus_hd_showcase/BigBuckBunny_DivX_HD720p_ASP.divx").NamedPipeFromVideoUri(); //web-video
var pipeName = new Uri("https://www.youtube.com/watch?v=Vpg9yizPP_g").NamedPipeFromYoutubeUri(); //Youtube
sourceName = String.Format(@"\\.\pipe\{0}", pipeName);
//video http link (Supports seek)
//sourceName = "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4";
//---------------------------------------------
ImageStreamReader reader = new FileCapture(sourceName);
reader.Open();
//seek if you can
if(reader.CanSeek)
reader.Seek((int)(reader.Length * 0.25), System.IO.SeekOrigin.Begin);
//read video frames
Bgr[,] frame = null;
while(true)
{
reader.ReadTo(ref frame);
if (frame == null)
break;
frame.Show(autoSize: false);
Console.Write($"\r Received: {reader.Position * 100 / reader.Length}%");
}
Console.WriteLine("The end.");
//---------------------------------------------------------------------------
ImageUI.CloseAll();
Console.WriteLine("Downloading video...");
string fileExtension;
var downloadPipeName = new Uri("https://www.youtube.com/watch?v=Vpg9yizPP_g").NamedPipeFromYoutubeUri(out fileExtension); //Youtube
downloadPipeName.SaveNamedPipeStream("out" + fileExtension);
Console.WriteLine("Video saved.");
Process.Start("out" + fileExtension); //open local file
}
}
}
================================================
FILE: Samples/Sample.VideoStreaming/Sample.VideoStreaming.csproj
================================================
netcoreapp2.2
x64
DotImaging
bin\
Exe
================================================
FILE: Source/BitmapInterop/.nuSpec/readmeImage.Bitmap.txt
================================================
Provides extensions for interoperability with System.Drawing.Bitmap, Point, PointF, Color and drawing extensions.
1) Array <-> Bitmap conversion:
var image = new Gray[240, 320];
var bmp = image.ToBitmap();
var imageFromBmp = bmp.ToArray() as Bgr[,];
2) System.Drawing.Color <-> DotImaging color conversion:
var aquaColor = System.Drawing.Color.Aqua.ToBgr();
3) Save bitmap with quality selection
var bmp = Bitmap.FromFile("sample.bmp");
bmp.Save("compressed.jpg", 85);
Discover more extensions as you type :)
================================================
FILE: Source/BitmapInterop/BmpExtensions/BitmapConversion.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
namespace DotImaging
{
///
/// Provides conversion extension methods between generic image and .
///
public static class BitmapConversionExtensions
{
#region Conversion from Bitmap
static Dictionary mapingTable = new Dictionary
{
{ typeof(Gray), PixelFormat.Format8bppIndexed },
{ typeof(Gray), PixelFormat.Format16bppGrayScale },
{ typeof(Bgr), PixelFormat.Format24bppRgb },
{ typeof(Bgra), PixelFormat.Format32bppArgb },
{ typeof(Bgr), PixelFormat.Format48bppRgb },
{ typeof(Bgra), PixelFormat.Format64bppArgb },
};
///
/// Converts a bitmap to an image (copies data).
///
/// Input bitmap.
/// Target color type.
/// 2D array.
public static TColor[,] ToImage(this Bitmap bmp)
where TColor: unmanaged, IColor
{
if (mapingTable.TryGetValue(typeof(TColor), out var targetPixelFmt) == false)
throw new NotSupportedException("Target mapping not found.");
TColor[,] arr = null;
using (Bitmap targetBmp = bmp.Clone(new Rectangle(0, 0, bmp.Width, bmp.Height), targetPixelFmt))
{
var bmpData = targetBmp.LockBits(ImageLockMode.ReadOnly);
arr = new TColor[targetBmp.Height, targetBmp.Width];
using (var img = arr.Lock())
{
Copy.UnsafeCopy2D(bmpData.Scan0, img.ImageData, bmpData.Stride, img.Stride, bmpData.Height);
}
targetBmp.UnlockBits(bmpData);
}
return arr;
}
#endregion
#region Conversion To Bitmap
private static Bitmap toBitmap(IImage img, PixelFormat pixelFormat)
{
var bmp = new Bitmap(img.Width, img.Height, pixelFormat);
var bmpData = bmp.LockBits(ImageLockMode.WriteOnly);
Copy.UnsafeCopy2D(img.ImageData, bmpData.Scan0, img.Stride, bmpData.Stride, bmpData.Height);
bmp.UnlockBits(bmpData);
if (pixelFormat == PixelFormat.Format8bppIndexed)
bmp.SetGrayscalePalette();
return bmp;
}
///
/// Converts an image to an bitmap.
///
/// Input image.
/// Bitmap
public static Bitmap ToBitmap(this Image> img)
{
return toBitmap(img, PixelFormat.Format8bppIndexed);
}
///
/// Converts an image to an bitmap.
///
/// Input image.
/// Bitmap
public static Bitmap ToBitmap(this Image> img)
{
return toBitmap(img, PixelFormat.Format16bppGrayScale);
}
///
/// Converts an image to an bitmap.
///
/// Input image.
/// Bitmap
public static Bitmap ToBitmap(this Image> img)
{
return toBitmap(img, PixelFormat.Format24bppRgb);
}
///
/// Converts an image to an bitmap.
///
/// Input image.
/// Bitmap
public static Bitmap ToBitmap(this Image> img)
{
return toBitmap(img, PixelFormat.Format32bppArgb);
}
///
/// Converts an image to an bitmap.
///
/// Input image.
/// Bitmap
public static Bitmap ToBitmap(this Image> img)
{
return toBitmap(img, PixelFormat.Format48bppRgb);
}
///
/// Converts an image to an bitmap.
///
/// Input image.
/// Bitmap
public static Bitmap ToBitmap(this Image> img)
{
return toBitmap(img, PixelFormat.Format64bppArgb);
}
///
/// Converts an image to an bitmap.
///
/// Input image.
/// Bitmap
public static Bitmap ToBitmap(this Gray[,] img)
{
Bitmap bmp = null;
using (var uImg = img.Lock())
{
bmp = toBitmap(uImg, PixelFormat.Format8bppIndexed);
}
return bmp;
}
///
/// Converts an image to an bitmap.
///
/// Input image.
/// Bitmap
public static Bitmap ToBitmap(this Gray[,] img)
{
Bitmap bmp = null;
using (var uImg = img.Lock())
{
bmp = toBitmap(uImg, PixelFormat.Format16bppGrayScale);
}
return bmp;
}
///
/// Converts an image to an bitmap.
///
/// Input image.
/// Bitmap
public static Bitmap ToBitmap(this Bgr[,] img)
{
Bitmap bmp = null;
using (var uImg = img.Lock())
{
bmp = toBitmap(uImg, PixelFormat.Format24bppRgb);
}
return bmp;
}
///
/// Converts an image to an bitmap.
///
/// Input image.
/// Bitmap
public static Bitmap ToBitmap(this Bgra[,] img)
{
Bitmap bmp = null;
using (var uImg = img.Lock())
{
bmp = toBitmap(uImg, PixelFormat.Format32bppArgb);
}
return bmp;
}
///
/// Converts an image to an bitmap.
///
/// Input image.
/// Bitmap
public static Bitmap ToBitmap(this Bgr[,] img)
{
Bitmap bmp = null;
using (var uImg = img.Lock())
{
bmp = toBitmap(uImg, PixelFormat.Format48bppRgb);
}
return bmp;
}
///
/// Converts an image to an bitmap.
///
/// Input image.
/// Bitmap
public static Bitmap ToBitmap(this Bgra[,] img)
{
Bitmap bmp = null;
using (var uImg = img.Lock())
{
bmp = toBitmap(uImg, PixelFormat.Format64bppArgb);
}
return bmp;
}
#endregion
#region Cast to Bitmap
private static Bitmap asBitmap(IImage img, PixelFormat pixelFormat)
{
var bmp = new Bitmap(img.Width, img.Height, img.Stride, pixelFormat, img.ImageData);
if (pixelFormat == PixelFormat.Format8bppIndexed)
bmp.SetGrayscalePalette();
return bmp;
}
///
/// Casts an image to an bitmap.
/// Notice that GDI+ does not support bitmaps which stride is not 4.
///
/// Input image.
/// Bitmap
public static Bitmap AsBitmap(this Image> img)
{
return asBitmap(img, PixelFormat.Format8bppIndexed);
}
///
/// Casts an image to an bitmap.
/// Notice that GDI+ does not support bitmaps which stride is not 4.
///
/// Input image.
/// Bitmap
public static Bitmap AsBitmap(this Image> img)
{
return asBitmap(img, PixelFormat.Format16bppGrayScale);
}
///
/// Casts an image to an bitmap.
/// Notice that GDI+ does not support bitmaps which stride is not 4.
///
/// Input image.
/// Bitmap
public static Bitmap AsBitmap(this Image> img)
{
return asBitmap(img, PixelFormat.Format24bppRgb);
}
///
/// Casts an image to an bitmap.
/// Notice that GDI+ does not support bitmaps which stride is not 4.
///
/// Input image.
/// Bitmap
public static Bitmap AsBitmap(this Image> img)
{
return asBitmap(img, PixelFormat.Format32bppArgb);
}
///
/// Casts an image to an bitmap.
/// Notice that GDI+ does not support bitmaps which stride is not 4.
///
/// Input image.
/// Bitmap
public static Bitmap AsBitmap(this Image> img)
{
return asBitmap(img, PixelFormat.Format48bppRgb);
}
///
/// Casts an image to an bitmap.
/// Notice that GDI+ does not support bitmaps which stride is not 4.
///
/// Input image.
/// Bitmap
public static Bitmap AsBitmap(this Image> img)
{
return asBitmap(img, PixelFormat.Format64bppArgb);
}
#endregion
#region Misc
///
/// Replaces color palette entries with grayscale intensities (256 entries).
///
/// The 8-bpp grayscale image.
public static void SetGrayscalePalette(this Bitmap image)
{
if (image.PixelFormat != PixelFormat.Format8bppIndexed)
throw new ArgumentException("The provided image must have 8bpp pixel format.");
var palette = image.Palette;
for (int i = 0; i < (Byte.MaxValue + 1); i++)
{
palette.Entries[i] = Color.FromArgb(i, i, i);
}
image.Palette = palette;
}
///
/// Lock a into system memory.
///
/// Bitmap to lock.
/// Specifies the access level.
/// Bitmap data.
public static BitmapData LockBits(this Bitmap bmp, ImageLockMode imageLockMode = ImageLockMode.ReadWrite)
{
return bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), imageLockMode, bmp.PixelFormat);
}
#endregion
}
}
================================================
FILE: Source/BitmapInterop/BmpExtensions/BmpIO.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO;
namespace DotImaging
{
///
/// Bitmap file save extensions.
///
public static class BmpIO
{
static Dictionary codecs = null;
static BmpIO()
{
codecs = new Dictionary();
codecs.Add(".jpg", getEncoder(ImageFormat.Jpeg));
codecs.Add(".jpeg", getEncoder(ImageFormat.Jpeg));
codecs.Add(".png", getEncoder(ImageFormat.Png));
}
private static ImageCodecInfo getEncoder(ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}
///
/// Saves the specified image.
///
/// Quality parameter is only supported for JPEG, PNG file types.
/// For other file types this value is omitted.
///
///
/// Image.
/// Target stream.
/// Image format.
/// Quality parameter [0..100] where 0 means maximum compression.
public static void Save(this System.Drawing.Image image, Stream targetStream, ImageFormat imageFormat, int quality = 90)
{
var encoder = getEncoder(imageFormat);
if (encoder != null)
{
System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;
EncoderParameters myEncoderParameters = new EncoderParameters(1);
myEncoderParameters.Param[0] = new EncoderParameter(myEncoder, quality);
image.Save(targetStream, encoder, myEncoderParameters);
}
else
{
image.Save(targetStream, imageFormat);
}
}
///
/// Saves the specified image.
///
/// Quality parameter is only supported for JPEG, PNG file types.
/// For other file types this value is omitted.
///
///
/// Image.
/// File name.
/// Quality parameter [0..100] where 0 means maximum compression.
public static void Save(this System.Drawing.Image image, string filename, int quality = 90)
{
codecs.TryGetValue(new FileInfo(filename).Extension, out ImageCodecInfo codec);
if (codec == null)
{
image.Save(filename);
return;
}
System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;
EncoderParameters myEncoderParameters = new EncoderParameters(1);
myEncoderParameters.Param[0] = new EncoderParameter(myEncoder, quality);
image.Save(filename, codec, myEncoderParameters);
}
}
}
================================================
FILE: Source/BitmapInterop/BmpExtensions/ColorConversion.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.Drawing;
namespace DotImaging
{
///
/// Contains color format conversion extensions.
///
public static class ColorConversion
{
///
/// Gets System.Drawing.Color from Bgr8 color.
///
/// Color.
/// Opacity. If color has 4 channels opacity is discarded.
/// System.Drawing.Color
public static System.Drawing.Color ToColor(this Gray color, byte opacity = Byte.MaxValue)
{
return Color.FromArgb(opacity, color.Intensity, color.Intensity, color.Intensity);
}
///
/// Gets System.Drawing.Color from Bgr8 color.
///
/// Color.
/// Opacity. If color has 4 channels opacity is discarded.
/// System.Drawing.Color
public static System.Drawing.Color ToColor(this Bgr color, byte opacity = Byte.MaxValue)
{
return Color.FromArgb(opacity, color.R, color.G, color.B);
}
///
/// Gets System.Drawing.Color from Bgra8 color.
///
/// Color.
/// System.Drawing.Color
public static System.Drawing.Color ToColor(this Bgra color)
{
return Color.FromArgb(color.A, color.R, color.G, color.B);
}
///
/// Converts (casts) the color into 32-bit BGR color.
///
/// Color.
/// Bgr representation.
public static Bgr ToBgr(this System.Drawing.Color color)
{
return new Bgr { B = color.B, G = color.G, R = color.R };
}
}
}
================================================
FILE: Source/BitmapInterop/Image.BitmapInterop.csproj
================================================
DotImaging.BitmapInterop
DotImaging
AnyCPU
bin\DotImaging.BitmapInterop.xml
true
5.3.0
DotImaging.BitmapInterop
Extensions for interoperability with System.Drawing.Bitmap.
imaging interoperability extensions, GDI
Darko Jurić
Darko Jurić
https://raw.githubusercontent.com/dajuric/dot-imaging/master/Deploy/Licence.txt
https://raw.githubusercontent.com/dajuric/dot-imaging/master/Deploy/Logo/logo-small.png
https://raw.githubusercontent.com/dajuric/dot-imaging/
https://raw.githubusercontent.com/dajuric/dot-imaging/
true
../../Deploy/NuGet/bin/
Readme.txt
================================================
FILE: Source/IO/.nuSpec/readmeIO.txt
================================================
Unified stream-like platform-abstract API for IO video access: web-camera support, various video-format reading / writing, image-directory reader.
Image loading/saving (file or in-memory).
1) image loading / saving:
Bgr[,] image = ImageIO.LoadColor("sample.jpg"); //load Bgr color image
Gray[,] hdrImage = (ImageIO.LoadUnchanged("hdrImage.png") as Image>).Clone(); //load HDR grayscale (or any other) image
image.Save("image.png");
2) image in-memory encoding / decoding
Bgr[,] bgrIm = ImageIO.LoadColor("sample.jpg");
byte[] encodedBgr = bgrIm.EncodeAsJpeg(); //or png, bmp
Bgr[,] decodedBgr = encodedBgr.DecodeAsColorImage();
3) media (camera, video, image-directory) capture:
ImageStreamReader reader = new CameraCapture(); //use specific class for device-specific properties (e.g. exposure, image name, ...)
reader.Open();
//read single frame
var frame = reader.Read().ToBgr();
reader.Close();
4) video writer:
ImageStreamWriter videoWriter = new VideoWriter("out.avi", new Size(1280, 1024));
var image = new Bgr[1024, 1280];
videoWriter.Write(image.Lock()); //write a single frame
videoWriter.Close();
5) frame extraction:
var reader = new FileCapture(fileName);
reader.Open();
reader.SaveFrames(outputDir, "{0}.jpg", (percentage) =>
{
((double)percentage).Progress(message: "Extracting video...");
});
reader.Close();
Discover more types as you type :)
================================================
FILE: Source/IO/Base/Abstract/ImageStream.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.IO;
namespace DotImaging
{
///
/// Provides the base class for the image stream.
///
/// Image type.
public abstract class ImageStream: IDisposable
{
///
/// Initializes a new instance of .
///
protected ImageStream()
{
this.CanSeek = false;
this.IsLiveStream = false;
}
///
/// When overridden in a derived class, gets the length in number of frames.
///
public abstract long Length { get; }
///
/// When overridden in a derived class, gets the next frame index.
///
public virtual long Position { get; protected set; }
///
/// Gets whether the stream is live stream meaning that its length is not constant.
/// Those streams are usually not seek-able. See also: .
///
public virtual bool IsLiveStream { get; protected set; }
///
/// Gets a value indicating whether the current stream supports seeking.
///
public virtual bool CanSeek { get; protected set; }
///
/// When overridden in a derived class, sets the position within the current stream.
///
/// A frame index offset relative to the origin parameter.
/// A value of type System.IO.SeekOrigin indicating the reference point used to obtain the new position.
/// The new position within the current stream.
/// Seek operation is not supported by the current stream.
public virtual long Seek(long offset, System.IO.SeekOrigin origin = SeekOrigin.Current)
{
if (!this.CanSeek)
throw new NotSupportedException("Seek operation is not supported by the current stream.");
long newPosition = 0;
switch (origin)
{
case SeekOrigin.Begin:
newPosition = offset;
break;
case SeekOrigin.Current:
newPosition = this.Position + offset;
break;
case SeekOrigin.End:
newPosition = this.Length + offset;
break;
}
var currentFrame = System.Math.Min(this.Length - 1, System.Math.Max(0, newPosition));
return currentFrame;
}
///
/// Closes the stream and releases all resources.
/// Use Dispose function rather than Close function.
///
public virtual void Dispose()
{
this.Close();
}
///
/// When overridden in a derived class, opens the current stream.
///
public abstract void Open();
///
/// When overridden in a derived class, closes the current stream and releases any resources associated with the current stream.
/// This function is internally called by .
///
public abstract void Close();
}
}
================================================
FILE: Source/IO/Base/Abstract/ImageStreamReader.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System;
namespace DotImaging
{
///
/// Image stream reader abstract class.
/// See generic class also.
///
public abstract class ImageStreamReader: ImageStreamReader
{ }
///
/// Image stream writer abstract class.
/// It is the base class for classes providing image stream reading.
///
/// Image type.
public abstract class ImageStreamReader : ImageStream, IEnumerable
{
///
/// Initializes a new instance of the image reader class.
///
protected ImageStreamReader()
{
this.ReadTimeout = 100;
}
///
/// Gets or sets a value, in milliseconds, that determines how long the stream will attempt to read before timing out.
///
public int ReadTimeout { get; set; }
///
/// Creates and starts the task responsible for frame reading.
/// If this function is called must be handled by a user itself.
///
/// By using this function reading from some streams can be accelerated.
///
///
/// A image reading task.
public Task ReadAsync()
{
var readTask = new Task(() =>
{
TImage result;
ReadInternal(out result);
return result;
});
readTask.Start();
return readTask;
}
///
/// Reads an image from the current stream
/// and advances the position within the stream by 1 element.
///
/// If a null is returned this can be due to has been reached.
/// Read image.
public TImage Read(out bool isExpired)
{
var readTask = ReadAsync();
readTask.Wait(this.ReadTimeout);
isExpired = !readTask.IsCompleted;
return readTask.Result;
}
///
/// Reads an image from the current stream
/// and advances the position within the stream by usually 1 element.
///
/// Read image.
public TImage Read()
{
bool isExpired;
return Read(out isExpired);
}
///
/// When overridden in a derived class returns an image and a status.
/// Position is advanced.
///
/// Read image.
///
protected abstract bool ReadInternal(out TImage image);
#region IEnumerable
///
/// Gets the enumerator for the stream.
/// If the stream does not support seek, an exception will be thrown during iteration.
///
/// Enumerator for the stream.
public IEnumerator GetEnumerator()
{
return new ImageStreamReaderEnumerator(this);
}
///
/// Gets the enumerator for the stream.
/// If the stream does not support seek, an exception will be thrown during iteration.
///
/// Enumerator for the stream.
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return (IEnumerator)GetEnumerator();
}
#endregion
}
///
/// Enumerator for the image stream.
/// Stream must support seek operation.
///
/// Image type.
public class ImageStreamReaderEnumerator : IEnumerator
{
ImageStreamReader streamableSource;
long length = -1;
int position;
///
/// Creates new image stream iterator.
///
/// Image stream.
public ImageStreamReaderEnumerator(ImageStreamReader streamableSource)
{
this.streamableSource = streamableSource;
this.length = streamableSource.Length;
Reset();
}
///
/// Moves the position of the iterator by 1.
///
/// True if the position increment is valid, false otherwise.
public bool MoveNext()
{
position++;
return position < length;
}
///
/// Resets the enumerator,
///
public void Reset()
{
streamableSource.Seek(0, SeekOrigin.Begin);
position = -1;
}
///
/// Gets the current image within the stream.
///
public TImage Current
{
get
{
var realPos = streamableSource.Position;
if (position != realPos)
streamableSource.Seek(position, SeekOrigin.Begin);
var currentImage = streamableSource.Read();
return currentImage;
}
}
///
/// Gets the current image within the stream.
///
object System.Collections.IEnumerator.Current
{
get { return this.Current; }
}
bool isDisposed = false;
///
/// Disposes the iterator and resets the position within the stream.
///
public void Dispose()
{
if (!isDisposed)
{
Reset();
isDisposed = true;
}
}
}
///
/// Provides extensions for image stream.
///
public static class ImageStreamReaderExtensions
{
///
/// Calls read function defined by the stream and converts an returned image if necessary.
/// If the image can not be read (null), null is returned.
///
/// Image stream.
/// Converted image or null if the image can not be read.
public static Image ReadAs(this ImageStreamReader imageStream)
where TColor: unmanaged
{
var image = imageStream.Read();
if (image == null)
return null;
return image as Image;
}
///
/// Reads an element form the input stream and fills the specified buffer.
/// If the read element does not match the specified type a null value will be written.
///
/// Color type.
/// Image source stream.
///
/// Buffer to write to.
/// The specified buffer can be null, as it is managed by the function itself.
///
public static void ReadTo(this ImageStreamReader imageStream, ref TColor[,] buffer)
where TColor: unmanaged
{
imageStream.ReadAs().CopyToOrCreate(ref buffer);
}
}
}
================================================
FILE: Source/IO/Base/Abstract/ImageStreamWriter.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System.Threading.Tasks;
using System;
namespace DotImaging
{
///
/// Image stream writer abstract class.
/// See generic class also.
///
public abstract class ImageStreamWriter : ImageStreamWriter
{ }
///
/// Image stream writer abstract class.
/// It is the base class for classes providing image stream reading.
///
/// Image type.
public abstract class ImageStreamWriter : ImageStream
{
///
/// Initializes a new instance of the image stream writer class.
///
protected ImageStreamWriter()
{
this.WriteTimeout = 500;
}
///
/// Gets or sets a value, in milliseconds, that determines how long the writer will attempt to write before timing out.
///
public int WriteTimeout { get; set; }
///
/// Creates and starts the task responsible for frame writing.
/// If this function is called must be handled by a user itself.
///
/// By using this function writing to some streams can be accelerated.
///
///
/// An image writing task.
public Task WriteAsync(TImage image)
{
var writeTask = new Task(() =>
{
bool success = WriteInternal(image);
return success;
});
writeTask.Start();
return writeTask;
}
///
/// Writes an image from the current stream
/// and advances the position within the stream by 1 element.
///
///
/// True if the operation is successfully completed,
/// false if the writer failed to write or the has been reached.
///
public bool Write(TImage image)
{
var writeTask = WriteAsync(image);
writeTask.Wait(this.WriteTimeout);
return writeTask.IsCompleted && writeTask.Result;
}
///
/// When overridden in a derived class returns an image and a status.
/// Position is advanced.
///
/// Image to write.
/// True if successful, false otherwise.
protected abstract bool WriteInternal(TImage image);
}
///
/// Provides extensions for an image stream writer.
///
public static class ImageStreamWriterExtensions
{
///
/// Writes a single image into the specified stream.
///
/// Color type.
/// image stream writer.
/// Image to write.
/// True if the writing operation is successful, false otherwise.
public static bool Write(this ImageStreamWriter> writer, TColor[,] image)
where TColor: unmanaged, IColor
{
bool result = false;
using (var uImg = image.Lock())
{
result = writer.Write(uImg);
}
return result;
}
}
}
================================================
FILE: Source/IO/Base/CvInvoke.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System.Drawing;
using System;
using System.Runtime.InteropServices;
using System.Security;
namespace DotImaging
{
///
/// OpenCV video codec name.
///
public class VideoCodec
{
///
/// MPEG1 codec name: "PIM1".
///
public static readonly VideoCodec MPEG1 = VideoCodec.FromName('P', 'I', 'M', '1');
///
/// Motion JPEG codec name: "MJPG".
///
public static readonly VideoCodec MotionJpeg = VideoCodec.FromName('M', 'J', 'P', 'G');
///
/// Intel YUV codec name: "IYUV".
///
public static readonly VideoCodec IntelYUV = VideoCodec.FromName('I', 'Y', 'U', 'V');
///
/// User selection - on Windows dialog will be opened. Value: -1.
///
public static readonly VideoCodec UserSelection = new VideoCodec(-1);
private const int CODEC_NAME_LENGTH = 4;
int codec;
///
/// Creates new video codec from an id.
///
/// Codec id.
private VideoCodec(int codec)
{
this.codec = codec;
}
///
/// Creates new video codec id from 4-character code. For example, FromName('P','I','M','1') is MPEG-1 codec, FromName('M','J','P','G') is motion-jpeg codec etc.
///
/// First char.
/// Second char.
/// Third char.
/// Fourth char.
/// Video codec.
public static VideoCodec FromName(char c1, char c2, char c3, char c4)
{
int codec = (c1 & 255) + ((c2 & 255) << 8) + ((c3 & 255) << 16) + ((c4 & 255) << 24);
return new VideoCodec(codec);
}
///
/// Creates new video codec id from 4-character string.
///
/// 4-character string codec name.
/// Video codec.
public static VideoCodec FromName(string codecName)
{
if (codecName.Length != CODEC_NAME_LENGTH)
throw new Exception("Codec name is 4-characters long!");
return VideoCodec.FromName(codecName[0], codecName[1], codecName[2], codecName[3]);
}
///
/// Casts video codec to an 32-bit integer.
///
/// Video codec.
/// 32-bit integer representation of the video codec.
public static implicit operator int(VideoCodec videoCodec)
{
return videoCodec.codec;
}
///
/// Creates video codec from the 32-bit integer.
///
/// 32-bit code.
/// New codec name.
public static explicit operator VideoCodec(int code)
{
return new VideoCodec(code);
}
///
/// Creates video codec from the 4-character string.
///
/// 4-character string.
/// New codec name.
/// Invalid string length.
public static explicit operator VideoCodec(string code)
{
return VideoCodec.FromName(code);
}
///
/// Gets the string representation of the codec name.
///
/// String representation.
public override string ToString()
{
unsafe
{
fixed (int* intPtr = &this.codec)
{
sbyte* chPtr = (sbyte*)intPtr;
return new string(chPtr, 0, CODEC_NAME_LENGTH);
}
}
}
}
///
/// OpenCV capture properties for camera and video.
///
internal enum CaptureProperty: int
{
PosMsec = 0,
PosFrames = 1,
FrameWidth = 3,
FrameHeight = 4,
FPS = 5,
FrameCount = 7,
/************** camera properties ******************/
Brightness = 10,
Contrast = 11,
Saturation = 12,
Hue = 13,
Gain = 14,
Exposure = 15,
/************** camera properties ******************/
ConvertRGB = 16
}
///
/// OpenCV image load mode.
///
[Flags]
internal enum ImageLoadType : int
{
///
/// Loads the image as is (including the alpha channel if present)
///
Unchanged = -1,
///
/// Loads the image as an intensity image
///
Grayscale = 0,
///
/// Loads the image in the RGB format
///
Color = 1,
///
/// Loads the image of any color
///
AnyColor = 4,
///
/// Loads the image of any depth
///
AnyDepth = 2
}
///
/// Internal class for OpenCV core / highgui library invocation.
///
internal static class CvInvoke
{
public const CallingConvention CvCallingConvention = CallingConvention.Cdecl;
public const string OPENCV_CORE_LIBRARY = "opencv_core2412";
public const string OPENCV_HIGHGUI_LIBRARY = "opencv_highgui2412";
#region Core
[DllImport(OPENCV_CORE_LIBRARY, CallingConvention = CvCallingConvention)]
public unsafe static extern void cvReleaseMat(ref CvMat* mat);
//[SuppressUnmanagedCodeSecurity]
[DllImport(OPENCV_CORE_LIBRARY, CallingConvention = CvCallingConvention)]
public unsafe static extern void cvReleaseImage(ref IplImage* image);
#endregion
#region Video reader
//[SuppressUnmanagedCodeSecurity]
[DllImport(OPENCV_HIGHGUI_LIBRARY, CallingConvention = CvCallingConvention)]
public static extern IntPtr cvCreateCameraCapture(int index);
[DllImport(OPENCV_HIGHGUI_LIBRARY, CallingConvention = CvCallingConvention)]
public static extern IntPtr cvCreateFileCapture([MarshalAs(UnmanagedType.LPStr)] string filename);
//[SuppressUnmanagedCodeSecurity]
[DllImport(OPENCV_HIGHGUI_LIBRARY, CallingConvention = CvCallingConvention)]
public static extern void cvReleaseCapture(ref IntPtr capture);
//[SuppressUnmanagedCodeSecurity]
[DllImport(OPENCV_HIGHGUI_LIBRARY, CallingConvention = CvCallingConvention)]
public static extern int cvGrabFrame(IntPtr capture);
//[SuppressUnmanagedCodeSecurity]
[DllImport(OPENCV_HIGHGUI_LIBRARY, CallingConvention = CvCallingConvention)]
public static extern IntPtr cvQueryFrame(IntPtr capture);
//[SuppressUnmanagedCodeSecurity]
[DllImport(OPENCV_HIGHGUI_LIBRARY, CallingConvention = CvCallingConvention)]
public static extern double cvGetCaptureProperty(IntPtr capture, CaptureProperty propertyId);
//[SuppressUnmanagedCodeSecurity]
[DllImport(OPENCV_HIGHGUI_LIBRARY, CallingConvention = CvCallingConvention)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool cvSetCaptureProperty(IntPtr capture, CaptureProperty propertyId, double value);
public static Size GetImageSize(IntPtr capturePtr)
{
return new Size
{
Width = (int)CvInvoke.cvGetCaptureProperty(capturePtr, CaptureProperty.FrameWidth),
Height = (int)CvInvoke.cvGetCaptureProperty(capturePtr, CaptureProperty.FrameHeight)
};
}
public static bool SetImageSize(IntPtr capturePtr, Size newSize)
{
bool success;
success = CvInvoke.cvSetCaptureProperty(capturePtr, CaptureProperty.FrameWidth, newSize.Width);
success &= CvInvoke.cvSetCaptureProperty(capturePtr, CaptureProperty.FrameHeight, newSize.Height);
return success;
}
#endregion
#region Video writer
///
/// Creates video writer structure.
///
/// Name of the output video file.
/// 4-character code of codec used to compress the frames. See class.
/// Frame rate of the created video stream.
/// Size of video frames.
/// If true, the encoder will expect and encode color frames, otherwise it will work with grayscale frames
/// The video writer
//[SuppressUnmanagedCodeSecurity]
[DllImport(OPENCV_HIGHGUI_LIBRARY, CallingConvention = CvCallingConvention)]
public static extern IntPtr cvCreateVideoWriter([MarshalAs(UnmanagedType.LPStr)] String filename, int fourcc, double fps, Size frameSize, [MarshalAs(UnmanagedType.Bool)] bool isColor);
///
/// Writes/appends one frame to video file.
///
/// video writer structure.
/// the written frame
/// True on success, false otherwise
//[SuppressUnmanagedCodeSecurity]
[DllImport(OPENCV_HIGHGUI_LIBRARY, CallingConvention = CvCallingConvention)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool cvWriteFrame(IntPtr writer, IntPtr image);
///
/// Finishes writing to video file and releases the structure.
///
/// pointer to video file writer structure
//[SuppressUnmanagedCodeSecurity]
[DllImport(OPENCV_HIGHGUI_LIBRARY, CallingConvention = CvCallingConvention)]
public static extern void cvReleaseVideoWriter(ref IntPtr writer);
#endregion
#region Image IO
//[SuppressUnmanagedCodeSecurity]
[DllImport(OPENCV_HIGHGUI_LIBRARY, CallingConvention = CvCallingConvention)]
public unsafe static extern IplImage* cvLoadImage([MarshalAs(UnmanagedType.LPStr)] String filename, ImageLoadType loadType);
//[SuppressUnmanagedCodeSecurity]
[DllImport(OPENCV_HIGHGUI_LIBRARY, CallingConvention = CvCallingConvention)]
public unsafe static extern bool cvSaveImage([MarshalAs(UnmanagedType.LPStr)] String filename, IplImage* image, IntPtr parameters);
public const int CV_IMWRITE_JPEG_QUALITY = 1;
public const int CV_IMWRITE_PNG_COMPRESSION = 16;
public const int CV_IMWRITE_PXM_BINARY = 32;
[DllImport(OPENCV_HIGHGUI_LIBRARY, CallingConvention = CvCallingConvention)]
public unsafe static extern CvMat* cvEncodeImage([MarshalAs(UnmanagedType.LPStr)] string ext, CvMat* image, int* parameters = null);
[DllImport(OPENCV_HIGHGUI_LIBRARY, CallingConvention = CvCallingConvention)]
public unsafe static extern CvMat* cvDecodeImageM(void* buffer, ImageLoadType loadType);
#endregion Image IO
}
}
================================================
FILE: Source/IO/IO.csproj
================================================
x64
DotImaging.IO
DotImaging
true
bin\DotImaging.IO.xml
true
5.3.0
DotImaging.IO
Loading and saving images and image streams (file, in-memory, camera, video, directory).
image-encode, image-decode, image-load, image-save, image-directory, camera-capture, multiple-camera-capture, video-capture, video-write
Darko Jurić
Darko Jurić
https://raw.githubusercontent.com/dajuric/dot-imaging/master/Deploy/Licence.txt
https://raw.githubusercontent.com/dajuric/dot-imaging/master/Deploy/Logo/logo-small.png
https://raw.githubusercontent.com/dajuric/dot-imaging/
https://raw.githubusercontent.com/dajuric/dot-imaging/
true
../../Deploy/NuGet/bin/
Readme.txt
runtimes\win10-x64\%(FileName)%(Extension)
Always
runtimes/win10-x64/native/
runtimes\ubuntu.16.04-x64\%(FileName)%(Extension)
Always
runtimes/ubuntu.16.04-x64/native/
================================================
FILE: Source/IO/ImageIO.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
namespace DotImaging
{
///
/// Provides methods for image saving and loading
///
public static class ImageIO
{
#region Load (file)
private unsafe static IImage load(string fileName, ImageLoadType imageLoadType)
{
var iplImagePtr = CvInvoke.cvLoadImage(fileName, imageLoadType);
var image = (*iplImagePtr).AsImage((_) =>
{
if (iplImagePtr == null) return;
CvInvoke.cvReleaseImage(ref iplImagePtr);
});
return image;
}
///
/// Loads an image with the specified path and name as it is.
///
/// Image file name.
/// Image.
public unsafe static IImage LoadUnchanged(this string fileName)
{
return load(fileName, ImageLoadType.Unchanged);
}
///
/// Loads an image with the specified path and name and performs and RGB conversion.
///
/// Image filename.
/// Image.
public unsafe static Bgr[,] LoadColor(this string fileName)
{
Bgr[,] im = null;
using (var uIm = load(fileName, ImageLoadType.Color) as Image>)
im = uIm.Clone();
return im;
}
///
/// Loads an image with the specified path and name and performs and gray conversion.
///
/// Image filename.
/// Image.
public unsafe static Gray[,] LoadGray(this string fileName)
{
Gray[,] im = null;
using (var uIm = load(fileName, ImageLoadType.Grayscale) as Image>)
im = uIm.Clone();
return im;
}
#endregion
#region Save (file)
///
/// Saves the provided image. If the image has non-supported color or depth false value is returned.
///
/// Image to save.
/// Filename.
/// True if the image is saved, false otherwise.
public unsafe static bool TrySave(IImage image, string fileName)
{
IplImage iplImage = default(IplImage);
try
{
iplImage = image.AsCvIplImage();
}
catch
{
return false;
}
CvInvoke.cvSaveImage(fileName, &iplImage, IntPtr.Zero);
return true;
}
///
/// Saves the specified image.
///
/// Image color.
/// Image to save.
/// Image filename.
private unsafe static void Save(this Image image, string fileName)
where TColor : unmanaged, IColor
{
var iplImage = image.AsCvIplImage();
CvInvoke.cvSaveImage(fileName, &iplImage, IntPtr.Zero);
}
///
/// Saves the specified image.
///
/// Image color.
/// Image to save.
/// Image filename.
private unsafe static void Save(this TColor[,] image, string fileName)
where TColor: unmanaged, IColor
{
using (var img = image.Lock())
{
var iplImage = img.AsCvIplImage();
CvInvoke.cvSaveImage(fileName, &iplImage, IntPtr.Zero);
}
}
#region Save-gray
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Gray[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Gray[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Gray[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Gray[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Gray[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Gray[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Gray[,] image, string fileName)
{
image.Save>(fileName);
}
#endregion
#region Save-bgr
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Bgr[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Bgr[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Bgr[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Bgr[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Bgr[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Bgr[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Bgr[,] image, string fileName)
{
image.Save>(fileName);
}
#endregion
#region Save-bgra
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Bgra[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Bgra[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Bgra[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Bgra[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Bgra[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Bgra[,] image, string fileName)
{
image.Save>(fileName);
}
///
/// Saves the specified image.
///
/// Image to save.
/// Image filename.
public static void Save(this Bgra[,] image, string fileName)
{
image.Save>(fileName);
}
#endregion
#endregion
#region Encode
///
/// Encodes the specified image into the Jpeg byte array.
///
/// Image to encode.
/// Jpeg quality [0..100] where 100 is the highest quality.
/// Jpeg byte array.
public static byte[] EncodeAsJpeg(this Gray[,] image, int jpegQuality = 95)
{
return encodeAsJpeg(image, jpegQuality);
}
///
/// Encodes the specified image into the Jpeg byte array.
///
/// Image to encode.
/// Jpeg quality [0..100] where 100 is the highest quality.
/// Jpeg byte array.
public static byte[] EncodeAsJpeg(this Bgr[,] image, int jpegQuality = 95)
{
return encodeAsJpeg(image, jpegQuality);
}
///
/// Encodes the specified image into the Jpeg byte array.
///
/// Image to encode.
/// Jpeg quality [0..100] where 100 is the highest quality.
/// Jpeg byte array.
public static byte[] EncodeAsJpeg(this Gray[,] image, int jpegQuality = 95)
{
return encodeAsJpeg(image, jpegQuality);
}
///
/// Encodes the specified image into the Jpeg byte array.
///
/// Image to encode.
/// Jpeg quality [0..100] where 100 is the highest quality.
/// Jpeg byte array.
public static byte[] EncodeAsJpeg(this Bgr[,] image, int jpegQuality = 95)
{
return encodeAsJpeg(image, jpegQuality);
}
///
/// Encodes the specified image into the PNG byte array.
///
/// Image to encode.
/// PNG compression level [0..9] where 9 is the highest compression.
/// PNG byte array.
public static byte[] EncodeAsPng(this Gray[,] image, int pngCompression = 3)
{
return encodeAsPng(image, pngCompression);
}
///
/// Encodes the specified image into the PNG byte array.
///
/// Image to encode.
/// PNG compression level [0..9] where 9 is the highest compression.
/// PNG byte array.
public static byte[] EncodeAsPng(this Bgr[,] image, int pngCompression = 3)
{
return encodeAsPng(image, pngCompression);
}
///
/// Encodes the specified image into the PNG byte array.
///
/// Image to encode.
/// PNG compression level [0..9] where 9 is the highest compression.
/// PNG byte array.
public static byte[] EncodeAsPng(this Bgra[,] image, int pngCompression = 3)
{
return encodeAsPng(image, pngCompression);
}
///
/// Encodes the specified image into the PNG byte array.
///
/// Image to encode.
/// PNG compression level [0..9] where 9 is the highest compression.
/// PNG byte array.
public static byte[] EncodeAsPng(this Gray[,] image, int pngCompression = 3)
{
return encodeAsPng(image, pngCompression);
}
///
/// Encodes the specified image into the PNG byte array.
///
/// Image to encode.
/// PNG compression level [0..9] where 9 is the highest compression.
/// PNG byte array.
public static byte[] EncodeAsPng(this Bgr[,] image, int pngCompression = 3)
{
return encodeAsPng(image, pngCompression);
}
///
/// Encodes the specified image into the PNG byte array.
///
/// Image to encode.
/// PNG compression level [0..9] where 9 is the highest compression.
/// PNG byte array.
public static byte[] EncodeAsPng(this Bgra[,] image, int pngCompression = 3)
{
return encodeAsPng(image, pngCompression);
}
///
/// Encodes the specified image into the specified image type byte array.
///
/// Image to encode.
/// Image type extension (.bmp, .png, .jpg)
/// Image type byte array.
public static byte[] Encode(this Gray[,] image, string extension)
{
return encode(image, extension, null);
}
///
/// Encodes the specified image into the specified image type byte array.
///
/// Image to encode.
/// Image type extension (.bmp, .png, .jpg)
/// Image type byte array.
public static byte[] Encode(this Bgr[,] image, string extension)
{
return encode(image, extension, null);
}
///
/// Encodes the specified image into the specified image type byte array.
///
/// Image to encode.
/// Image type extension (.bmp, .png, .jpg)
/// Image type byte array.
public static byte[] Encode(this Bgra[,] image, string extension)
{
return encode(image, extension, null);
}
///
/// Encodes the specified image into the specified image type byte array.
///
/// Image to encode.
/// Image type extension (.bmp, .png, .jpg)
/// Image type byte array.
public static byte[] Encode(this Gray[,] image, string extension)
{
return encode(image, extension, null);
}
///
/// Encodes the specified image into the specified image type byte array.
///
/// Image to encode.
/// Image type extension (.bmp, .png, .jpg)
/// Image type byte array.
public static byte[] Encode(this Bgr[,] image, string extension)
{
return encode(image, extension, null);
}
///
/// Encodes the specified image into the specified image type byte array.
///
/// Image to encode.
/// Image type extension (.bmp, .png, .jpg)
/// Image type byte array.
public static byte[] Encode(this Bgra[,] image, string extension)
{
return encode(image, extension, null);
}
static byte[] encodeAsJpeg(TColor[,] image, int jpegQuality = 95)
where TColor : unmanaged, IColor
{
if (jpegQuality < 0 || jpegQuality > 100)
throw new ArgumentOutOfRangeException("Jpeg quality must be in range: 0-100.");
int[] parameters = new int[] { CvInvoke.CV_IMWRITE_JPEG_QUALITY, jpegQuality, 0 };
return encode(image, ".jpg", parameters);
}
static byte[] encodeAsPng(TColor[,] image, int pngCompression = 3)
where TColor : unmanaged, IColor
{
if (pngCompression < 0 || pngCompression > 9)
throw new ArgumentOutOfRangeException("Png compression must be in range: 0-9.");
int[] parameters = new int[] { CvInvoke.CV_IMWRITE_PNG_COMPRESSION, pngCompression, 0 };
return encode(image, ".png", parameters);
}
static unsafe byte[] encode(TColor[,] image, string extension, int[] parameters)
where TColor : unmanaged, IColor
{
CvMat* matEncoded; //a single-row image
using (var uImg = image.Lock())
{
fixed (int* paramsPtr = parameters)
{
var mat = uImg.AsCvMat();
matEncoded = CvInvoke.cvEncodeImage(extension, &mat, paramsPtr);
}
}
byte[] imEncoded = new byte[matEncoded->Step * matEncoded->Height];
fixed (byte* arrPtr = &imEncoded[0])
{
Copy.UnsafeCopy(matEncoded->ImageData, (IntPtr)arrPtr, imEncoded.Length);
}
CvInvoke.cvReleaseMat(ref matEncoded); //TODOD: check if this deferences the image
return imEncoded;
}
#endregion
#region Decode
///
/// Decodes (and converts if necessary) an image as color image using the specified byte array.
///
/// Encoded image.
/// Decoded image.
public unsafe static Bgr[,] DecodeAsColorImage(this byte[] encodedImage)
{
return decodeImage>(encodedImage, ImageLoadType.Color);
}
///
/// Decodes (and converts if necessary) an image as gray image using the specified byte array.
///
/// Encoded image.
/// Decoded image.
public unsafe static Gray[,] DecodeAsGrayImage(this byte[] encodedImage)
{
return decodeImage>(encodedImage, ImageLoadType.Grayscale);
}
unsafe static TColor[,] decodeImage(byte[] encodedImage, ImageLoadType loadType)
where TColor : unmanaged, IColor
{
CvMat* matDecoded;
fixed (byte* encodedImPtr = encodedImage)
{
CvMat mat = CvMat.FromUserData((IntPtr)encodedImPtr, encodedImage.Length, 1, encodedImage.Length, CvMat.CvChannelDepth.CV_8U, 1);
matDecoded = CvInvoke.cvDecodeImageM(&mat, ImageLoadType.Color);
}
var imDecoded = (*matDecoded).ToArray();
CvInvoke.cvReleaseMat(ref matDecoded);
return imDecoded;
}
#endregion
}
}
================================================
FILE: Source/IO/Readers/CameraCapture.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.Drawing;
namespace DotImaging
{
///
/// Represents camera stream-able source and provides functions and properties to access a device in a stream-able way.
///
public class CameraCapture: VideoCaptureBase
{
int cameraIdx = 0;
///
/// Creates capture from camera.
///
/// Camera index.
public CameraCapture(int cameraIdx = 0)
{
this.cameraIdx = cameraIdx;
this.CanSeek = false;
this.IsLiveStream = true;
this.Open(); //to enable property change
}
///
/// Opens the camera stream.
///
public override void Open()
{
if (capturePtr != IntPtr.Zero)
return;
capturePtr = CvInvoke.cvCreateCameraCapture(cameraIdx);
if (capturePtr == IntPtr.Zero)
throw new Exception("Cannot open camera stream! It seems that camera device can not be found.");
}
///
/// Gets or sets the brightness of the camera.
/// If the property is not supported by device 0 will be returned.
///
public double Brightness
{
get { return CvInvoke.cvGetCaptureProperty(capturePtr, CaptureProperty.Brightness); }
set { CvInvoke.cvSetCaptureProperty(capturePtr, CaptureProperty.Brightness, value); }
}
///
/// Gets or sets the contrast of the camera.
/// If the property is not supported by device 0 will be returned.
///
public double Contrast
{
get { return CvInvoke.cvGetCaptureProperty(capturePtr, CaptureProperty.Contrast); }
set { CvInvoke.cvSetCaptureProperty(capturePtr, CaptureProperty.Contrast, value); }
}
///
/// Gets or sets the exposure of the camera.
/// If the property is not supported by device 0 will be returned.
///
public double Exposure
{
get { return CvInvoke.cvGetCaptureProperty(capturePtr, CaptureProperty.Exposure); }
set { CvInvoke.cvSetCaptureProperty(capturePtr, CaptureProperty.Exposure, value); }
}
///
/// Gets or sets the gain of the camera.
/// If the property is not supported by device 0 will be returned.
///
public double Gain
{
get { return CvInvoke.cvGetCaptureProperty(capturePtr, CaptureProperty.Gain); }
set { CvInvoke.cvSetCaptureProperty(capturePtr, CaptureProperty.Gain, value); }
}
///
/// Gets or sets the hue of the camera.
/// If the property is not supported by device 0 will be returned.
///
public double Hue
{
get { return CvInvoke.cvGetCaptureProperty(capturePtr, CaptureProperty.Hue); }
set { CvInvoke.cvSetCaptureProperty(capturePtr, CaptureProperty.Hue, value); }
}
///
/// Gets or sets the saturation of the camera.
/// If the property is not supported by device 0 will be returned.
///
public double Saturation
{
get { return CvInvoke.cvGetCaptureProperty(capturePtr, CaptureProperty.Saturation); }
set { CvInvoke.cvSetCaptureProperty(capturePtr, CaptureProperty.Saturation, value); }
}
///
/// Gets or sets the frame size of the camera.
///
public new Size FrameSize
{
get { return CvInvoke.GetImageSize(capturePtr); }
set { CvInvoke.SetImageSize(capturePtr, value); }
}
///
/// Gets or sets the frame rate of the camera.
/// If the property is not supported by device 0 will be returned.
///
public new double FrameRate
{
get { return CvInvoke.cvGetCaptureProperty(capturePtr, CaptureProperty.FPS); }
set { CvInvoke.cvSetCaptureProperty(capturePtr, CaptureProperty.FPS, value); }
}
///
/// Gets the available device count.
/// Warning: the function closes existing streams, so use it before any camera capture object is created.
///
public static int CameraCount
{
get
{
int cameraIdx = 0;
while (true)
{
var capturePtr = CvInvoke.cvCreateCameraCapture(cameraIdx);
if (capturePtr != IntPtr.Zero)
{
CvInvoke.cvReleaseCapture(ref capturePtr);
cameraIdx++;
}
else
break;
}
return cameraIdx;
}
}
}
}
================================================
FILE: Source/IO/Readers/FileCapture.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.IO;
using System.Linq;
namespace DotImaging
{
///
/// Provides functions and properties to access video file in a streamable way.
///
public class FileCapture: VideoCaptureBase
{
private static readonly string[] supportedRemoteFiles = new string[] { ".mp4", ".webm" };
private static readonly string[] supportedLocalFiles = new string[] { ".mp4", ".avi", ".divx", ".webm", ".wmv" };
string fileName = null;
///
/// Creates capture from video file.
///
///
/// Local file, http uri, ftp uri or a named pipe.
/// In case of named pipe use: String.Format(@"\\.\pipe\{0}", pipeName) where pipeName is the name of the pipe.
///
public FileCapture(string sourceName)
{
if (sourceName.Contains(@"\\.\pipe\"))
{
this.CanSeek = false;
}
else if (Uri.IsWellFormedUriString(sourceName, UriKind.Absolute))
{
var fileExt = Path.GetExtension(sourceName);
if (supportedRemoteFiles.Any(x => x.Equals(fileExt.ToLower())) == false)
throw new UriFormatException(String.Format("Uri must point to a supported video file ({0}).", String.Join(", ", supportedRemoteFiles)));
this.CanSeek = true;
}
else
{
if (!File.Exists(sourceName))
throw new FileNotFoundException(String.Format("The file {0} can not be found.", sourceName));
var fileExt = Path.GetExtension(sourceName);
if (supportedLocalFiles.Any(x => x.Equals(fileExt.ToLower())) == false)
throw new UriFormatException(String.Format("File must be a supported video file ({0}).", String.Join(", ", supportedLocalFiles)));
this.CanSeek = true;
}
this.fileName = sourceName;
this.Open(); //to enable property change
}
///
/// Opens the video file stream.
///
public override void Open()
{
if (capturePtr != IntPtr.Zero)
return;
capturePtr = CvInvoke.cvCreateFileCapture(fileName);
if (capturePtr == IntPtr.Zero)
throw new Exception("Cannot open FileStream!");
}
///
/// Gets the current position in the stream as frame offset.
///
public override long Position
{
get { return (long)CvInvoke.cvGetCaptureProperty(capturePtr, CaptureProperty.PosFrames); }
protected set { }
}
///
/// Sets the position within the current stream.
/// Warning: the underlying OpenCV function seeks to nearest key-frame, therefore the seek operation may not be frame-accurate.
///
/// A frame index offset relative to the origin parameter.
/// A value of type System.IO.SeekOrigin indicating the reference point used to obtain the new position.
/// The new position within the current stream.
public override long Seek(long offset, System.IO.SeekOrigin origin = SeekOrigin.Current)
{
var frameIndex = base.Seek(offset, origin);
CvInvoke.cvSetCaptureProperty(capturePtr, CaptureProperty.PosFrames, frameIndex);
return Position;
}
}
}
================================================
FILE: Source/IO/Readers/ImageDirectoryCapture.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace DotImaging
{
///
/// Represents directory stream-able source and provides functions and properties to access data in a stream-able way.
///
public class ImageDirectoryCapture : ImageStreamReader
{
long currentFrame = 0;
#region Initialization
///
/// Creates an instance of .
///
/// The directory path.
/// The image search pattern.
/// Use natural sorting, otherwise raw image order is used.
/// If true searches the current directory and all subdirectories. Otherwise, only top directory is searched.
/// Directory can not be found.
public ImageDirectoryCapture(string dirPath, string searchPattern, bool useNaturalSorting = true, bool recursive = false)
: this(dirPath, new string[] { searchPattern }, useNaturalSorting, recursive)
{ }
///
/// Creates an instance of .
///
/// The directory path.
/// The image search patterns.
/// Use natural sorting, otherwise raw image order is used.
/// If true searches the current directory and all subdirectories. Otherwise, only top directory is searched.
/// Directory can not be found.
public ImageDirectoryCapture(string dirPath, string[] searchPatterns, bool useNaturalSorting = true, bool recursive = false)
{
FileReadFunction = ImageIO.LoadUnchanged;
if (Directory.Exists(dirPath) == false)
throw new DirectoryNotFoundException(String.Format("Dir: {0} cannot be found!", dirPath));
DirectoryInfo directoryInfo = new DirectoryInfo(dirPath);
this.IsLiveStream = false;
this.CanSeek = true;
this.DirectoryInfo = directoryInfo;
var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
if (useNaturalSorting)
{
this.FileInfos = directoryInfo.EnumerateFiles(searchPatterns, searchOption)
.OrderBy(f => f.FullName, new NaturalSortComparer()) //in case of problems replace f.FullName with f.Name
.ToArray();
}
else
{
this.FileInfos = directoryInfo.EnumerateFiles(searchPatterns, searchOption)
.ToArray();
}
}
#endregion
///
/// Open the current stream. This overload does not do anything.
///
public override void Open() { }
///
/// Closes the current stream. This overload resets position to zero.
///
public override void Close()
{
currentFrame = 0;
}
object syncObj = new object();
///
/// Reads an image from the stream.
///
/// Read image.
/// True if the reading operation was successful, false otherwise.
protected override bool ReadInternal(out IImage image)
{
lock (syncObj)
{
image = default(IImage);
if (this.Position >= this.Length)
return false;
image = FileReadFunction(FileInfos[currentFrame].FullName);
currentFrame++;
}
return true;
}
///
/// Gets the total number of files in the specified directory which match the specified search criteria.
///
public override long Length { get { return FileInfos.Length; } }
///
/// Gets the current position within the stream.
///
public override long Position { get { return currentFrame; } }
///
/// Sets the position within the current stream.
///
/// A frame index offset relative to the origin parameter.
/// A value of type indicating the reference point used to obtain the new position.
/// The new position within the current stream.
public override long Seek(long offset, SeekOrigin origin = SeekOrigin.Current)
{
this.currentFrame = base.Seek(offset, origin);
return Math.Max(0, Math.Min(currentFrame, this.Length));
}
#region Specific function
///
/// Gets the source directory info.
///
public DirectoryInfo DirectoryInfo
{
get;
private set;
}
///
/// Gets the ordered set of files which compose the current image directory stream.
///
public FileInfo[] FileInfos
{
get;
private set;
}
///
/// Gets the current image file name.
/// If the position of the stream is equal to the stream length null is returned.
///
public string CurrentImageName
{
get { return (this.Position < FileInfos.Length) ? FileInfos[this.Position].FullName : null; }
}
Func fileReadFunction;
///
/// Gets or sets the file read function.
/// A default reading function loads image as it is (unchanged).
///
public Func FileReadFunction
{
get { return fileReadFunction; }
set
{
if (value == null)
new ArgumentNullException("File read function can not be null.");
fileReadFunction = value;
}
}
#endregion
}
}
================================================
FILE: Source/IO/Readers/VideoCaptureBase.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.Drawing;
namespace DotImaging
{
///
/// Represents the base class for video capture that shares common functions and properties with camera and file capture.
///
public abstract class VideoCaptureBase : ImageStreamReader
{
///
/// Internal OpenCV pointer for the capture object.
///
protected IntPtr capturePtr;
///
/// Releases all resources allocated by capture.
///
public override void Close()
{
if (capturePtr != IntPtr.Zero)
CvInvoke.cvReleaseCapture(ref capturePtr);
}
object syncObj = new object();
///
/// Reads the next image in the stream and advances the position by one.
///
/// Read image.
/// True if the reading operation was successful, false otherwise.
protected override bool ReadInternal(out IImage image)
{
bool status = false;
image = default(IImage);
lock (syncObj)
{
IntPtr cvFramePtr;
cvFramePtr = CvInvoke.cvQueryFrame(capturePtr);
if (cvFramePtr != IntPtr.Zero)
{
image = IplImage.FromPointer(cvFramePtr).AsImage();
this.Position++;
status = true;
}
}
return status;
}
///
/// Gets the length in number of frames.
///
public override long Length
{
get { return (long)CvInvoke.cvGetCaptureProperty(capturePtr, CaptureProperty.FrameCount); }
}
///
/// Gets or sets whether to force conversion of an input image to Bgr color type.
///
public bool ConvertRgb
{
get { return (int)CvInvoke.cvGetCaptureProperty(capturePtr, CaptureProperty.ConvertRGB) != 0; }
set { CvInvoke.cvSetCaptureProperty(capturePtr, CaptureProperty.ConvertRGB, value ? 0 : 1); }
}
///
/// Gets the frame size.
///
public Size FrameSize
{
get { return CvInvoke.GetImageSize(capturePtr); }
}
///
/// Gets the frame rate.
///
public float FrameRate
{
get { return (float)CvInvoke.cvGetCaptureProperty(capturePtr, CaptureProperty.FPS); }
}
}
}
================================================
FILE: Source/IO/Utilities/NaturalSortComparer.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace DotImaging
{
///
/// Provides functions for natural string comparison.
/// Reference: .
///
class NaturalSortComparer: IComparer
{
private bool isAscending;
///
/// Creates a new instance of .
///
/// Sorts in ascending order, otherwise descending.
public NaturalSortComparer(bool inAscendingOrder = true)
{
this.isAscending = inAscendingOrder;
}
#region IComparer Members
///
/// Compares two strings.
///
/// First string.
/// Second string.
/// 0 - the same objects, -1, +1 otherwise depending whether the first string precedes the second one or not.
public int Compare(string x, string y)
{
throw new NotImplementedException();
}
#endregion
#region IComparer Members
int IComparer.Compare(string x, string y)
{
if (x == y)
return 0;
string[] x1, y1;
if (!table.TryGetValue(x, out x1))
{
x1 = Regex.Split(x.Replace(" ", ""), "([0-9]+)");
table.Add(x, x1);
}
if (!table.TryGetValue(y, out y1))
{
y1 = Regex.Split(y.Replace(" ", ""), "([0-9]+)");
table.Add(y, y1);
}
int returnVal;
for (int i = 0; i < x1.Length && i < y1.Length; i++)
{
if (x1[i] != y1[i])
{
returnVal = PartCompare(x1[i], y1[i]);
return isAscending ? returnVal : -returnVal;
}
}
if (y1.Length > x1.Length)
{
returnVal = 1;
}
else if (x1.Length > y1.Length)
{
returnVal = -1;
}
else
{
returnVal = 0;
}
return isAscending ? returnVal : -returnVal;
}
private static int PartCompare(string left, string right)
{
int x, y;
if (!int.TryParse(left, out x))
return left.CompareTo(right);
if (!int.TryParse(right, out y))
return left.CompareTo(right);
return x.CompareTo(y);
}
#endregion
private Dictionary table = new Dictionary();
}
}
================================================
FILE: Source/IO/Utilities/PathExtensions.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.Collections.Generic;
using System.IO;
namespace DotImaging
{
///
/// Defined functions can be used as object extensions.
/// Provides methods for string which is treated as file and directory path.
///
static class PathExtensions
{
///
/// Returns an enumerable collection of file information that matches a specified search pattern and search subdirectory option.
///
/// Directory info.
/// The search strings (e.g. new string[]{ ".jpg", ".bmp" }
///
/// One of the enumeration values that specifies whether the search operation
/// should include only the current directory or all subdirectories. The default
/// value is .
///
/// An enumerable collection of files that matches and .
public static IEnumerable EnumerateFiles(this DirectoryInfo dirInfo, string[] searchPatterns, SearchOption searchOption = SearchOption.TopDirectoryOnly)
{
var fileInfos = new List();
foreach (var searchPattern in searchPatterns)
{
var dirFileInfos = dirInfo.EnumerateFiles(searchPattern, searchOption);
fileInfos.AddRange(dirFileInfos);
}
return fileInfos;
}
}
}
================================================
FILE: Source/IO/Writers/ImageWriterExtension.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.IO;
namespace DotImaging
{
///
/// Provides extensions for image extraction from image streams.
///
public static class ImageWriterExtension
{
///
/// Reads the image source and save the extracted images to the specified folder.
///
/// Image stream reader.
/// Output directory.
/// Image file name format.
/// Progress function executed after a frame is saved.
public static void SaveFrames(this ImageStreamReader imageSource, string outputDir,
string fileNameFormat = "img-{0:000}.png",
Action onFrameCompletition = null)
{
if (!Directory.Exists(outputDir))
Directory.CreateDirectory(outputDir);
if (imageSource.CanSeek)
imageSource.Seek(0, SeekOrigin.Begin);
var idx = 0;
foreach (var frame in imageSource) //use video stream as IEnumerable (must support seek operation)
{
if (frame != null) //some videos skip key frames (discard those frames)
{
var path = Path.Combine(outputDir, String.Format(fileNameFormat, idx));
ImageIO.TrySave(frame, path); //TODO-noncritical: add compression options
}
if(onFrameCompletition != null)
onFrameCompletition((float)(idx + 1) / imageSource.Length);
idx++;
}
}
}
}
================================================
FILE: Source/IO/Writers/VideoWriter.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.Drawing;
namespace DotImaging
{
///
/// Video writer that writes images into video file.
///
public class VideoWriter : ImageStreamWriter
{
object syncObj = new object();
IntPtr videoObjPtr = IntPtr.Zero;
///
/// Gets the output file name.
///
public string OutputFileName { get; private set; }
///
/// Gets whether the frame must consist of 3-channels (color) or from just one (grayscale).
///
public bool ColorFrames { get; private set; }
///
/// Gets the codec used to encode frames.
///
public VideoCodec Codec { get; private set; }
///
/// Gets the number of frames per second.
///
public float FrameRate { get; private set; }
///
/// Gets the frame size.
///
public Size FrameSize { get; private set; }
///
/// Creates new video writer (with default codec).
///
/// Video file name.
/// Video frame size.
/// Specifies the number of frames per second.
/// Specifies whether the image is color image (3 channels) or grayscale image (one channel).
public VideoWriter(string fileName, Size frameSize, float fps = 30, bool isColor = true)
: this(fileName, frameSize, fps, isColor, VideoCodec.MotionJpeg)
{ }
///
/// Creates new video writer.
///
/// Video file name.
/// Video frame size.
/// Specifies the number of frames per second.
/// Specifies whether the image is color image (3 channels) or grayscale image (one channel).
/// Specifies used codec for video encoding.
public VideoWriter(string fileName, Size frameSize, float fps, bool isColor, VideoCodec videoCodec)
{
this.CanSeek = false;
this.IsLiveStream = true;
this.OutputFileName = fileName;
this.ColorFrames = isColor;
this.Codec = videoCodec;
this.FrameSize = frameSize;
this.FrameRate = fps;
this.Open(); //to enable property change
}
///
/// Opens the video file stream.
///
public override void Open()
{
if (videoObjPtr != IntPtr.Zero)
return;
videoObjPtr = CvInvoke.cvCreateVideoWriter(OutputFileName, (int)Codec, FrameRate, FrameSize, ColorFrames);
if (videoObjPtr == IntPtr.Zero)
throw new Exception(String.Format("Cannot open FileStream! Please check that the selected codec ({0}) is supported.", Codec));
}
///
/// Gets the current position in the stream as frame offset.
///
public override long Position
{
get;
protected set;
}
///
/// Gets the current stream length which is not constant and is the same as position.
///
public override long Length
{
get { return this.Position; }
}
///
/// Writes the provided image to the stream.
///
/// Image to write.
/// True, if the operation was successful, false otherwise.
protected unsafe override bool WriteInternal(IImage image)
{
bool isSuccessful;
lock (syncObj)
{
if (image.ColorInfo.ChannelCount == 3 && !ColorFrames)
throw new Exception("Image must be grayscale!");
if (image.ColorInfo.ChannelCount == 1 && ColorFrames)
throw new Exception("Image must be color!");
if (image.ColorInfo.ChannelCount != 3 && ColorFrames)
throw new Exception("Color images must have 3 channels!");
if (!image.Size.Equals(FrameSize))
throw new Exception("Input image must be the same size as defined frame size!");
this.Position++;
var iplImg = image.AsCvIplImage();
IplImage* iplImgPtr = (IplImage*)&iplImg;
isSuccessful = CvInvoke.cvWriteFrame(videoObjPtr, (IntPtr)iplImgPtr);
}
return isSuccessful;
}
///
/// Closes video writer.
/// Use dispose method to remove any additional resources.
///
public override void Close()
{
if (videoObjPtr != IntPtr.Zero)
CvInvoke.cvReleaseVideoWriter(ref videoObjPtr);
}
}
}
================================================
FILE: Source/IO.Web/.nuSpec/readmeIO.Web.txt
================================================
Provides support for image or video download/streaming (direct video link or Youtube links).
1) image loading:
new Uri("http://vignette3.wikia.nocookie.net/disney/images/5/5d/Lena_headey_.jpg")
.GetBytes()
.DecodeAsColorImage()
.Show(); //requires UI package
2) video streaming:
var sourceName = String.Empty;
var pipeName = new Uri("https://www.youtube.com/watch?v=Vpg9yizPP_g").NamedPipeFromYoutubeUri(); //Youtube
sourceName = String.Format(@"\\.\pipe\{0}", pipeName);
//sourceName = "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"; //direct http streaming
//------------------------------------------------------------------
ImageStreamReader reader = new FileCapture(sourceName);
reader.Open();
//seek if you can
if(reader.CanSeek)
reader.Seek((int)(reader.Length * 0.25), System.IO.SeekOrigin.Begin);
//read video frames
Bgr[,] frame = null;
do
{
reader.ReadTo(ref frame);
if (frame == null)
break;
frame.Show(scaleForm: true);
((double)reader.Position / reader.Length).Progress();
}
while (!(Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape));
3) video download:
string fileExtension;
pipeName = new Uri("https://www.youtube.com/watch?v=Vpg9yizPP_g").NamedPipeFromYoutubeUri(out fileExtension); //Youtube
pipeName.SaveNamedPipeStream("out" + fileExtension);
Discover more types as you type :)
================================================
FILE: Source/IO.Web/IO.Web.csproj
================================================
DotImaging.IO.Web
DotImaging
AnyCPU
bin\DotImaging.IO.Web.xml
true
5.3.0
DotImaging.IO.Web
Image or video download/streaming (direct video link or Youtube links).
web-image, image-download, video-download, video-streaming, Youtube, web-video
Darko Jurić
Darko Jurić
https://raw.githubusercontent.com/dajuric/dot-imaging/master/Deploy/Licence.txt
https://raw.githubusercontent.com/dajuric/dot-imaging/master/Deploy/Logo/logo-small.png
https://raw.githubusercontent.com/dajuric/dot-imaging/
https://raw.githubusercontent.com/dajuric/dot-imaging/
true
../../Deploy/NuGet/bin/
Readme.txt
================================================
FILE: Source/IO.Web/NamedPipeExtensions.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.IO;
using System.Threading.Tasks;
using System.IO.Pipes;
using System.Net;
using VideoLibrary;
namespace DotImaging
{
///
/// Provides named pipe creation extension for Uri, string and Stream.
///
public static class NamedPipeExtensions
{
#region Reading
///
/// Creates a new named pipe from a file stream.
///
/// File name.
/// Named pipe.
/// Function executed when progress changes. Return true to cancel the operation, false to continue.
/// Pipe name.
public static string NamedPipeFromFileName(this string fileName, string namedPipeName = "filePipe", Func onProgress = null)
{
if (File.Exists(fileName))
throw new ArgumentException("The provided file does not exist.", nameof(fileName));
Stream source = File.OpenRead(fileName);
return NamedPipeFromStreamAsync(source, namedPipeName, onProgress, () =>
{
source.Dispose();
});
}
///
/// Creates a new named pipe from a link (video-link if used in conjunction with IO package).
///
/// Uri to web file.
/// Named pipe.
/// Function executed when progress changes. Return true to cancel the operation, false to continue.
/// Pipe name.
public static string NamedPipeFromVideoUri(this Uri uri, string namedPipeName = "webPipe", Func onProgress = null)
{
var request = (HttpWebRequest)WebRequest.Create(uri.AbsoluteUri);
WebResponse response = request.GetResponse();
Stream source = response.GetResponseStream();
return NamedPipeFromStreamAsync(source, namedPipeName, onProgress, () =>
{
source.Dispose();
response.Dispose();
});
}
///
/// Creates a new named pipe from a Youtube video link.
///
/// Uri to Youtube video file.
/// Video-file extension.
/// Named pipe.
/// Function executed when progress changes. Return true to cancel the operation, false to continue.
/// Pipe name.
public static string NamedPipeFromYoutubeUri(this Uri youtubeUri, out string fileExtension, string namedPipeName = "youtubeVideoPipe", Func onProgress = null)
{
if (youtubeUri.Host != "www.youtube.com")
throw new ArgumentException("The provided URI is not valid Youtube URI.");
var youtubeVideo = YouTube.Default.GetVideo(youtubeUri.AbsoluteUri);
fileExtension = youtubeVideo.FileExtension;
VideoClient vc = new VideoClient();
Stream source = vc.Stream(youtubeVideo);
return NamedPipeFromStreamAsync(source, namedPipeName, onProgress, () =>
{
source.Dispose();
vc.Dispose();
});
}
///
/// Creates a new named pipe from a Youtube video link.
///
/// Uri to Youtube video file.
/// Named pipe.
/// Function executed when progress changes. Return true to cancel the operation, false to continue.
/// Pipe name.
public static string NamedPipeFromYoutubeUri(this Uri youtubeUri, string namedPipeName = "youtubeVideoPipe", Func onProgress = null)
{
string fileExtension;
return NamedPipeFromYoutubeUri(youtubeUri, out fileExtension, namedPipeName, onProgress);
}
///
/// Creates a new named pipe from a Youtube video link.
///
/// Source stream.
/// Named pipe.
/// Function executed when progress changes. Return true to cancel the operation, false to continue.
/// Action executed when a reading operation finishes.
/// Pipe name.
public static string NamedPipeFromStreamAsync(this Stream source, string namedPipeName, Func onProgress = null, Action onFinish = null)
{
if (source == null)
new ArgumentNullException(nameof(source));
Task.Factory.StartNew(() =>
{
using (NamedPipeServerStream target = new NamedPipeServerStream(namedPipeName))
{
target.WaitForConnection();
target.WaitForPipeDrain();
int bytes, copiedBytes = 0;
var buffer = new byte[1024];
while ((bytes = source.Read(buffer, 0, buffer.Length)) > 0)
{
target.Write(buffer, 0, bytes);
copiedBytes += bytes;
if (onProgress != null)
{
bool shouldCancel = onProgress((float)copiedBytes / source.Length);
if (shouldCancel)
break;
}
}
target.Flush();
if (onFinish != null) onFinish();
}
});
return namedPipeName;
}
#endregion
#region Writing
///
/// Copies the named pipe stream to the specified stream.
///
/// Pipe name.
/// Destination stream.
public static void CopyNamedPipeStream(this string pipeName, Stream target)
{
using (NamedPipeClientStream clientPipe = new NamedPipeClientStream(pipeName))
{
clientPipe.Connect();
int bytes, copiedBytes = 0;
var buffer = new byte[1024];
while ((bytes = clientPipe.Read(buffer, 0, buffer.Length)) > 0)
{
target.Write(buffer, 0, bytes);
copiedBytes += bytes;
/*if (onProgress != null)
{
bool shouldCancel = onProgress((float)copiedBytes / clientPipe.Length);
if (shouldCancel)
break;
}*/
}
target.Flush();
}
}
///
/// Saves the named pipe stream to the specified file.
///
/// Pipe name.
/// Destination file.
public static void SaveNamedPipeStream(this string pipeName, string targetFile)
{
using (Stream target = File.Create(targetFile))
{
CopyNamedPipeStream(pipeName, target);
}
}
#endregion
}
}
================================================
FILE: Source/IO.Web/WebImageExtensions.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.IO;
using System.Net;
namespace DotImaging
{
///
/// Provides extensions for getting images from the Web.
///
public static class WebImageExtensions
{
///
/// Gets the bytes from the Web using the specified uri.
///
/// File Web location.
/// Function executed when progress changes. Return true to cancel the operation, false to continue.
/// Encoded image or undefined output in case if the operation is canceled.
public static byte[] GetBytes(this Uri uri, Func onProgress = null)
{
byte[] output = null;
var request = (HttpWebRequest)WebRequest.Create(uri.AbsoluteUri);
using (WebResponse response = request.GetResponse())
using (Stream source = response.GetResponseStream())
using(MemoryStream target = new MemoryStream())
{
int bytes, copiedBytes = 0;
var buffer = new byte[1024];
while ((bytes = source.Read(buffer, 0, buffer.Length)) > 0)
{
target.Write(buffer, 0, bytes);
copiedBytes += bytes;
if (onProgress != null)
{
bool shouldCancel = onProgress((float)copiedBytes / response.ContentLength);
if (shouldCancel)
break;
}
}
target.Flush();
output = target.ToArray();
}
return output;
}
}
}
================================================
FILE: Source/Image/.nuSpec/readmeImage.txt
================================================
Provides .NET native array imaging extensions. Color-spaces and channel depth conversion is included.
Implements slim generic image class when fast pixel manipulation is needed.
To get compatibility for other image types install appropriate extension - NuGet package (e.g. Imaging.BitmapInterop).
1) Color and depth conversion:
Bgr[,] image = ImageIO.LoadColor("sample.jpg"); //requires DotImaging.IO package
Gray grayFloatIm = image.ToGray()
.Cast();
2) Splitting and merging channels:
Bgra[,] image = new Bgra[480, 640];
Gray[][,] channels = image.SplitChannels(0, 1, 2); //take B, G and R channel
Bgr bgrIm = channels.MergeChannels, byte>();
3) Unsafe operations:
Bgr[,] image = new Bgr[240, 320];
using(var unmanagedImage = image.Lock()) //create unmanaged structure that shares data with the array
{
Bgr8* ptr = (Bgr8*)unmanagedImage.GetData(10, 10);
ptr->B = 111;
}
4) OpenCV compatibility:
Gray[,] image = new Gray[240, 320];
IplImage iplIm = image.AsOpenCvImage(); //to OpenCV image
Gray[,] imFromIpl = iplIm.AsImage().Clone(); //to array
5) LINQ:
Bgr[,] image = ImageIO.LoadColor("sample.jpg").Clone();
//get the modified blue channel
var modifiedImage = image.AsEnumerable()
.Select(x => x.B / 2)
.ToArray2D(image.Size());
6) Misc
Hsv[,] image = new Hsv[240, 320];
image.SetValue(new Hsv(10, 10, 255)); //set pixels value
Console.WriteLine(image.Size()); //write image size
Console.WriteLine(image.ColorInfo()); //write color info
...
Discover more extensions as you type :)
================================================
FILE: Source/Image/ColorTypeConversions/ColorInfo.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
namespace DotImaging
{
///
/// Gets color information from color type and depth type.
///
public class ColorInfo: IEquatable
{
static ConcurrentDictionary colorInfos = new ConcurrentDictionary();
///
/// Color type (IColor).
///
public Type ColorType { get; private set; }
///
/// Number of channels that color has.
///
public int ChannelCount { get; private set; }
///
/// Number of bytes per channel.
///
public int ChannelSize { get; private set; }
///
/// Channel type. Only primitive types are supported.
///
public Type ChannelType { get; private set; }
///
/// Color size in bytes. Number of channels multiplied by channel size.
///
public int Size { get { return this.ChannelSize * this.ChannelCount; } }
///
/// Gets color info (depth is taken from color).
///
/// Member of
/// Color info
public static ColorInfo GetInfo()
//where TColor : IColor
{
return GetInfo(typeof(TColor));
}
///
/// Gets color info (depth is taken from color).
///
/// Color type. (member of IColor)
/// Color info
public static ColorInfo GetInfo(Type colorType)
{
return colorInfos.GetOrAdd(colorType, getInfo);
}
private static ColorInfo getInfo(Type colorType)
{
ColorInfo ci = new ColorInfo();
ci.ColorType = colorType;
Type channelType; int numberOfChannels;
getChannelInfo(colorType, out channelType, out numberOfChannels);
ci.ChannelCount = numberOfChannels;
ci.ChannelType = channelType;
ci.ChannelSize = Marshal.SizeOf(channelType);
return ci;
}
private static void getChannelInfo(Type colorType, out Type channelType, out int numberOfChannels)
{
numberOfChannels = 0;
var channelTypes = colorType
.GetFields(BindingFlags.Public | ~BindingFlags.Static) //if BindingFlags.Instance and if colorType is byte => zero length array
.Select(x => x.FieldType)
.ToArray();
//ensure that all types are the same
var _channelType = channelTypes[0];
if (channelTypes.Where(x => x.Equals(_channelType)).Count() != channelTypes.Length)
throw new Exception("Public fields must have the same type!");
if (channelTypes.Length == 0)
throw new Exception("Color structure must have at least one public field!");
if (!_channelType.IsValueType)
throw new Exception("Channel type must be a value type!");
if (!_channelType.IsPrimitive)
throw new Exception("Channel type must be a primitive type!");
channelType = _channelType;
numberOfChannels = channelTypes.Length;
}
///
/// Determines whether the object is equal compared to the specified object.
/// A default comparison is used. Please see overloads.
///
/// Other object.
/// True if two objects are equal, false otherwise.
public bool Equals(ColorInfo other)
{
return Equals(other, ComparableParts.Default);
}
///
/// Indicates what parts of color info should be compared.
///
[Flags]
public enum ComparableParts
{
///
/// Checks color depth type
///
Depth = 0x1,
///
/// Checks if one color can be casted to other (if colors are binary compatible).
///
BinaryCompatible = 0x3,
///
/// Checks color type and depth type (if it is true all other properties are equal as well)
///
Default = 0x4
}
///
/// Compares two color infos.
///
/// Other color info.
/// Indicates what to compare. Default is: ComparableParts.Default.
///
public bool Equals(ColorInfo other, ComparableParts cParts)
{
if(cParts == ComparableParts.Default)
{
return this.ColorType == other.ColorType &&
this.ChannelType == other.ChannelType;
}
if (cParts == ComparableParts.BinaryCompatible)
{
var castable = (this.ChannelCount == other.ChannelCount) && (this.ChannelType == other.ChannelType);
return castable;
}
if (cParts == ComparableParts.Depth)
{
var depth = this.ChannelType == other.ChannelType;
return depth;
}
throw new Exception("Unknown comparison!");
}
///
/// Get string representation.
///
/// String
public override string ToString()
{
return String.Format("<{0}, {1}>", this.ColorType.Name, this.ChannelType.Name);
}
}
///
/// Provides extensions for color to array conversion.
///
public static class ColorToArrayExtensions
{
///
/// Converts color to array of type .
///
/// Color type.
/// Channel type.
/// Color
/// Array whose length is the same as color's number of channels.
public static TDepth[] ColorToArray(this TColor color)
where TColor : IColor
where TDepth : struct
{
var fields = typeof(TColor).GetFields(BindingFlags.Public | ~BindingFlags.Static);
TDepth[] arr = new TDepth[fields.Length];
for (int i = 0; i < fields.Length; i++)
{
var rawVal = fields[i].GetValue(color);
arr[i] = (TDepth)Convert.ChangeType(rawVal, typeof(TDepth));
}
return arr;
}
}
}
================================================
FILE: Source/Image/ColorTypeConversions/ColorSpaces/Bgr.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace DotImaging
{
///
/// Represents Bgr color type of type color depth .
///
[StructLayout(LayoutKind.Sequential)]
public struct Bgr : IColor3
where T : unmanaged
{
///
/// Creates new Bgr color.
///
/// Blue
/// Green
/// Red
public Bgr(T b, T g, T r)
{
this.B = b;
this.G = g;
this.R = r;
}
///
/// Gets or sets the blue component.
///
public T B;
///
/// Gets or sets the green component.
///
public T G;
///
/// Gets or sets the red component.
///
public T R;
///
/// Gets the string color representation.
///
/// String color representation.
public override string ToString()
{
return string.Format("B: {0}, G: {1}, R: {2}", B, G, R);
}
///
/// Gets the index of the blue component.
///
public const int IdxB = 0;
///
/// Gets the index of the green component.
///
public const int IdxG = 1;
///
/// Gets the index of the red component.
///
public const int IdxR = 2;
///
/// Gets the 8-bit red color.
///
public static Bgr Red { get { return new Bgr { B = 0, G = 0, R = byte.MaxValue }; } }
///
/// Gets the 8-bit blue color.
///
public static Bgr Blue { get { return new Bgr { B = byte.MaxValue, G = 0, R = 0 }; } }
///
/// Gets the 8-bit green color.
///
public static Bgr Green { get { return new Bgr { B = 0, G = byte.MaxValue, R = 0 }; } }
///
/// Gets the 8-bit black color.
///
public static Bgr Black { get { return new Bgr { B = 0, G = 0, R = 0 }; } }
///
/// Gets the 8-bit white color.
///
public static Bgr White { get { return new Bgr { B = byte.MaxValue, G = byte.MaxValue, R = byte.MaxValue }; } }
///
/// Converts 8-bit Bgr to 8-bit gray intensity.
///
/// Source color.
/// Destination color.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Convert(Bgr bgr, ref Gray gray)
{
int val = ((bgr.R << 1) + //2 * red
(bgr.G << 2) + bgr.G + //5 * green
bgr.B //1 * blue
) >> 3; //divide by 8
gray.Intensity = (byte)val;
}
///
/// Converts 8-bit Bgr to 8-bit Bgra.
///
/// Source color.
/// Destination color.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Convert(Bgr bgr, ref Bgra bgra)
{
bgra.B = bgr.B;
bgra.G = bgr.G;
bgra.R = bgr.R;
bgra.A = System.Byte.MaxValue;
}
///
/// Converts 8-bit Bgr to 8-bit Bgra.
///
/// Source color.
/// Destination color.
/// Opacity.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Convert(Bgr bgr, ref Bgra bgra, byte opacity = System.Byte.MaxValue)
{
bgra.B = bgr.B;
bgra.G = bgr.G;
bgra.R = bgr.R;
bgra.A = opacity;
}
///
/// Converts 8-bit Bgr to 8-bit Hsv color. Value range for 8-bit HSv color is [0..180].
///
/// Source color.
/// Destination color.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Convert(Bgr bgr, ref Hsv hsv)
{
byte rgbMin, rgbMax;
rgbMin = bgr.R < bgr.G ? (bgr.R < bgr.B ? bgr.R : bgr.B) : (bgr.G < bgr.B ? bgr.G : bgr.B);
rgbMax = bgr.R > bgr.G ? (bgr.R > bgr.B ? bgr.R : bgr.B) : (bgr.G > bgr.B ? bgr.G : bgr.B);
hsv.V = rgbMax;
if (hsv.V == 0)
{
hsv.H = 0;
hsv.S = 0;
return;
}
hsv.S = (byte)(255 * (rgbMax - rgbMin) / rgbMax);
if (hsv.S == 0)
{
hsv.H = 0;
return;
}
int hue = 0;
if (rgbMax == bgr.R)
{
hue = 0 + 60 * (bgr.G - bgr.B) / (rgbMax - rgbMin);
if (hue < 0)
hue += 360;
}
else if (rgbMax == bgr.G)
{
hue = 120 + 60 * (bgr.B - bgr.R) / (rgbMax - rgbMin);
}
else //rgbMax == bgr.B
{
hue = 240 + 60 * (bgr.R - bgr.G) / (rgbMax - rgbMin);
}
hsv.H = (byte)(hue / 2); //scale [0-360] . [0-180] (only needed for byte!)
//Debug.Assert(hue >= 0 && hue <= 360);
}
}
///
/// Provides extension conversion methods for 8-bit Bgr type.
///
public static class BgrColorConversionExtensions
{
///
/// Converts 8-bit Bgr color to 8-bit gray.
///
/// 8-bit Bgr color.
/// 8-bit gray
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Gray ToGray(this Bgr bgr)
{
Gray gray = default(Gray);
Bgr.Convert(bgr, ref gray);
return gray;
}
///
/// Converts 8-bit Bgr color to 8-bit Hsv color.
///
/// 8-bit Bgr color.
/// 8-bit Hsv color.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Hsv ToHsv(this Bgr bgr)
{
Hsv hsv = default(Hsv);
Bgr.Convert(bgr, ref hsv);
return hsv;
}
}
///
/// Represents 8-bit Bgr color type.
/// Its usage should be restricted only for unsafe pixel manipulation.
///
public struct Bgr8
{
///
/// Gets or sets the blue component.
///
public byte B;
///
/// Gets or sets the green component.
///
public byte G;
///
/// Gets or sets the red component.
///
public byte R;
}
}
================================================
FILE: Source/Image/ColorTypeConversions/ColorSpaces/Bgra.cs
================================================
#region Licence and Terms
// DotImaging Framework
// https://github.com/dajuric/dot-imaging
//
// Copyright © Darko Jurić, 2014-2019
// darko.juric2@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System.Runtime.InteropServices;
namespace DotImaging
{
///
/// Represents Bgra color type of type depth .
///
[StructLayout(LayoutKind.Sequential)]
public struct Bgra : IColor4
where T: unmanaged
{
///
/// Creates new Bgra color.
///
/// Blue
/// Green
/// Red
/// Alpha (transparency).
public Bgra(T b, T g, T r, T a)
{
this.B = b;
this.G = g;
this.R = r;
this.A = a;
}
///
/// Gets or sets the blue component.
///
public T B;
///
/// Gets or sets the green component.
///
public T G;
///
/// Gets or sets the red component.
///
public T R;
///
/// Gets or sets the alpha component.
///
public T A;
///
/// Gets the string color representation.
///
/// String color representation.
public override string ToString()
{
return string.Format("B: {0}, G: {1}, R: {2}, A: {3}", B, G, R, A);
}
///
/// Gets the index of the blue component.
///
public const int IdxB = 0;
///
/// Gets the index of the green component.
///
public const int IdxG = 1;
///
/// Gets the index of the red component.
///
public const int IdxR = 2;
///
/// Gets the index of the alpha component.
///
public const int IdxA = 3;
///
/// Converts 8-bit Bgra to 8-bit Bgr color.
///
/// Source color.
/// Destination color.
public static void Convert(Bgra bgra, ref Bgr bgr)
{
bgr.B = bgra.B;
bgr.G = bgra.G;
bgr.R = bgra.R;
}
///
/// Converts 8-bit Bgra to 8-bit Gray.
///
/// Source color.
/// Destination color.
public static void Convert(Bgra bgra, ref Gray gray)
{
Bgr bgr = default(Bgr